solomonlai.ng/demo-v4-extended-loop.js
Solomon Laing 800b2864a6
All checks were successful
continuous-integration/drone/push Build is passing
feat: updated styling and animations
2026-02-13 09:07:38 +10:30

126 lines
3.9 KiB
JavaScript

// Version 4: Extended Loop with Smooth Transitions
// Creates a much longer animation cycle that loops smoothly without harsh resets
const staggerVisualizerEl = document.querySelector('.stagger-visualizer');
const fragment = document.createDocumentFragment();
const grid = [12, 6];
const col = grid[0];
const row = grid[1];
const numberOfElements = col * row;
for (let i = 0; i < numberOfElements; i++) {
let div = document.createElement('div');
div.className = 'part';
div.dataset.index = i;
fragment.appendChild(div);
}
staggerVisualizerEl.appendChild(fragment);
// Extended animation cycle - 20 seconds total, much longer so loop is less jarring
const staggersAnimation = anime.createTimeline({
easing: 'easeInOutSine',
loop: true,
autoplay: false
});
staggersAnimation
// Initial expansion phase
.add('.part', {
translateX: anime.stagger('-.15rem', { grid: grid, from: 'center', axis: 'x' }),
translateY: anime.stagger('-.15rem', { grid: grid, from: 'center', axis: 'y' }),
scale: 0.5,
duration: 300,
easing: 'easeOutQuad',
delay: anime.stagger(60, { grid: grid, from: 'center' })
}, 0)
// Chaotic burst phase
.add('.part', {
translateX: (el, i) => anime.utils.random(-10, 10),
translateY: (el, i) => anime.utils.random(-10, 10),
scale: (el) => anime.utils.random(0.7, 1.3),
rotate: (el) => anime.utils.random(-120, 120),
duration: 800,
easing: 'easeOutQuad',
delay: anime.stagger(80, { grid: grid, from: 'center' })
})
// Floating drift phase 1
.add('.part', {
translateY: (el, i) => anime.utils.random(-6, 6),
rotate: (el) => anime.utils.random(-60, 60),
duration: 2000,
easing: 'easeInOutSine',
delay: (el, i) => i * 20 + anime.utils.random(-200, 200)
})
// Gentle swirl inward
.add('.part', {
translateX: (el, i) => anime.utils.random(-5, 5),
translateY: (el, i) => anime.utils.random(-5, 5),
rotate: (el) => anime.utils.random(-45, 45),
duration: 1500,
easing: 'easeInOutQuad',
delay: anime.stagger(50, { grid: grid, from: 'center' })
})
// Floating drift phase 2 - different direction
.add('.part', {
translateY: (el, i) => anime.utils.random(-8, 8),
rotate: (el) => anime.utils.random(-30, 30),
duration: 2200,
easing: 'easeInOutSine',
delay: (el, i) => i * 22 + anime.utils.random(-150, 150)
})
// Slow convergence
.add('.part', {
translateX: (el) => anime.utils.random(-2, 2),
translateY: (el) => anime.utils.random(-2, 2),
rotate: (el) => anime.utils.random(-15, 15),
duration: 1800,
easing: 'easeInOutQuad',
delay: anime.stagger(60, { grid: grid, from: 'center' })
})
// Gentle return to center with subtle movement
.add('.part', {
translateX: (el) => {
const index = parseInt(el.dataset.index);
return anime.utils.random(-1, 1);
},
translateY: (el) => {
const index = parseInt(el.dataset.index);
return anime.utils.random(-1, 1);
},
rotate: 0,
scale: 1,
opacity: 1,
duration: 2500,
easing: 'easeOutQuad',
delay: anime.stagger(50, { grid: grid, from: 'center' })
})
// Long rest phase with breathing effect
.add('.part', {
scale: (el) => anime.utils.random(0.95, 1.05),
opacity: (el) => anime.utils.random(0.8, 1),
duration: 3000,
easing: 'easeInOutSine',
delay: (el, i) => i * 15
})
// Return to perfect rest
.add('.part', {
translateX: 0,
translateY: 0,
rotate: 0,
scale: 1,
opacity: 1,
duration: 1500,
easing: 'easeOutQuad',
delay: anime.stagger(40, { grid: grid, from: 'center' })
});
staggersAnimation.play();