Skip to content

Commit 7edda18

Browse files
committed
animate
1 parent a5c88dc commit 7edda18

2 files changed

Lines changed: 64 additions & 33 deletions

File tree

‎src/lib/socials.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ export const socials = [
2626
},
2727
{
2828
name: 'Last.fm',
29-
url: 'https://last.fm/user/aaronmamparo',
29+
url: 'https://last.fm/user/amamparo',
3030
icon: 'lastfm'
3131
},
3232
{
3333
name: 'Email',
34-
url: 'mailto:aaron@mamparo.com',
34+
url: 'mailto:aaronmamparo@gmail.com',
3535
icon: 'email'
3636
}
3737
];

‎src/routes/+page.svelte‎

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import { SiBluesky } from 'svelte-icons-pack/si';
1111
import { SiSoundcloud } from 'svelte-icons-pack/si';
1212
import { SiLastdotfm } from 'svelte-icons-pack/si';
13+
import { onMount } from 'svelte';
14+
15+
let mounted = false;
1316
1417
const iconComponents = {
1518
linkedin: { component: Linkedin, isLucide: true },
@@ -23,13 +26,20 @@
2326
2427
// Calculate positions for icons in a circle
2528
function getIconPosition(index, total) {
26-
const angle = (index * 360 / total) - 90; // Start from top
27-
const radius = 140; // Distance from center
29+
const angle = (index * 360 / total) - 90; // Position around circle
30+
const radius = 140; // Fixed radius
2831
const radian = angle * Math.PI / 180;
2932
const x = Math.cos(radian) * radius;
3033
const y = Math.sin(radian) * radius;
31-
return `transform: translate(${x}px, ${y}px)`;
34+
return { x, y };
3235
}
36+
37+
onMount(() => {
38+
// Trigger animation after a short delay
39+
setTimeout(() => {
40+
mounted = true;
41+
}, 100);
42+
});
3343
</script>
3444

3545
<svelte:head>
@@ -54,35 +64,39 @@
5464
</div>
5565
</div>
5666

57-
<!-- Social Icons arranged in circle -->
67+
<!-- Social Icons carousel container -->
5868
<div class="absolute inset-0 flex items-center justify-center">
59-
{#each socials as social, index (social.name)}
60-
<a
61-
href={social.url}
62-
target="_blank"
63-
rel="noopener noreferrer"
64-
title={social.name}
65-
style={getIconPosition(index, socials.length)}
66-
class="absolute p-3 rounded-full
67-
bg-transparent text-gray-400
68-
hover:text-neon-cyan
69-
border border-gray-800 hover:border-neon-cyan/50
70-
transition-all duration-300
71-
hover:shadow-[0_0_20px_rgba(0,255,255,0.3)]
72-
flex items-center justify-center"
73-
>
74-
{#if iconComponents[social.icon].isLucide}
75-
<svelte:component
76-
this={iconComponents[social.icon].component}
77-
class="w-7 h-7 transition-transform duration-300 hover:scale-110"
78-
/>
79-
{:else}
80-
<div class="w-7 h-7 flex items-center justify-center transition-transform duration-300 hover:scale-110">
81-
<Icon src={iconComponents[social.icon].component} size="28" />
82-
</div>
83-
{/if}
84-
</a>
85-
{/each}
69+
<div class="absolute inset-0 {mounted ? 'carousel-stop' : 'carousel-spin'}">
70+
{#each socials as social, index (social.name)}
71+
{@const pos = getIconPosition(index, socials.length)}
72+
<a
73+
href={social.url}
74+
target="_blank"
75+
rel="noopener noreferrer"
76+
title={social.name}
77+
style="transform: translate({pos.x}px, {pos.y}px); transition-delay: {index * 75}ms; opacity: {mounted ? 1 : 0}"
78+
class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 p-3 rounded-full
79+
bg-transparent text-gray-400
80+
hover:text-neon-cyan
81+
border border-gray-800 hover:border-neon-cyan/50
82+
hover:shadow-[0_0_20px_rgba(0,255,255,0.3)]
83+
flex items-center justify-center
84+
transition-opacity duration-700 ease-out
85+
{mounted ? '' : 'pointer-events-none'}"
86+
>
87+
{#if iconComponents[social.icon].isLucide}
88+
<svelte:component
89+
this={iconComponents[social.icon].component}
90+
class="w-7 h-7 transition-transform duration-300 hover:scale-110"
91+
/>
92+
{:else}
93+
<div class="w-7 h-7 flex items-center justify-center transition-transform duration-300 hover:scale-110">
94+
<Icon src={iconComponents[social.icon].component} size="28" />
95+
</div>
96+
{/if}
97+
</a>
98+
{/each}
99+
</div>
86100
</div>
87101
</div>
88102
</div>
@@ -105,4 +119,21 @@
105119
padding: 0;
106120
background-color: #0a0a0f;
107121
}
122+
123+
:global(.carousel-spin) {
124+
animation: carousel-rotate 2s cubic-bezier(0.4, 0.0, 0.2, 1) forwards;
125+
}
126+
127+
:global(.carousel-stop) {
128+
transform: rotate(0deg);
129+
}
130+
131+
@keyframes carousel-rotate {
132+
from {
133+
transform: rotate(360deg);
134+
}
135+
to {
136+
transform: rotate(0deg);
137+
}
138+
}
108139
</style>

0 commit comments

Comments
 (0)