console.log(gsap.version); // need 3.9+
const slimes = gsap.utils.toArray(".star");
const tl = gsap.timeline();
tl.paused( true )
.to(".star", {
keyframes:{
"25%":{y:0},
"50%":{y:-100, ease:"sine"},
"75%":{y:0, ease:"sine.in"},
"100%":{x:450, ease:"none"}
},
duration:2,
stagger:0.5
})
play.addEventListener("click", ()=> tl.restart());
Percentage-Based Keyframes
Keyframes
Ex)
// timeline
let tl = gsap.timeline();
tl.to(".box", {
x: 100
})
.to(".box", {
y: 100
})
.to(".box", {
x: 0
})
.to(".box", {
y: 0
});
// keyframes
gsap.to(".box", {
keyframes: {
25%: {x:100, y:0},
50%: {x:100, y:100},
75%: {x:0, y:100, rotate: 360},
100%: {y:0, x:0},
easeEach: 'none'
},
duration: 4
});
// Array-based keyframes
gsap.to(".box", {
keyframes: {
x: [0, 100, 100, 0, 0],
y: [0, 0, 100, 100, 0],
ease: "power1.inOut"
},
duration: 2
});
// keyframes object
gsap.to(".box", {
keyframes: [
{x:100},
{y:100, ease:'power2.out'},
{x:0},
{y:0, ease:'power2.in'}
],
rotate:360,
transformOrigin:'center center'
});
Object keyframes – v3.0
gsap.to(".elem", {
keyframes: [
{x: 100, duration: 1, ease: 'sine.out'}, // finetune with individual eases
{y: 200, duration: 1, delay: 0.5}, // create a 0.5 second gap
{rotation: 360, duration: 2, delay: -0.25} // overlap by 0.25 seconds
],
ease: 'expo.inOut' // ease the entire keyframe block
});
Percentage keyframes – v3.9
gsap.to(".elem", {
keyframes: {
"0%": { x: 100, y: 100},
"75%": { x: 0, y: 0, ease: 'sine.out'}, // finetune with individual eases
"100%": { x: 50, y: 50 },
easeEach: 'expo.inOut' // ease between keyframes
},
ease: 'none' // ease the entire keyframe block
duration: 2,
})
Simple Array-based keyframes – v3.9
gsap.to(".elem", {
keyframes: {
x: [100, 0, 50],
y: [100, 0, 50]
easeEach: 'sine.inOut' // ease between keyframes
ease: 'expo.out' // ease the entire keyframe block
},
duration: 2,
})
Test 1
gsap.set("svg", { opacity: 1 });
gsap.to(".ball", {
keyframes: {
"0%": { yPercent: 0, scaleX: 1, scaleY: 1 },
"7%": { yPercent: 5, scaleY: 0.9, scaleX: 1.1, ease: "sine.in" },
"25%": { yPercent: 100, scaleY: 1.15, scaleX: 0.9, ease: "sine.in" },
"50%": { yPercent: 500, scaleX: 1, scaleY: 1, ease: "none" },
"60%": { scaleX: 1.6, scaleY: 0.4, ease: "none" },
"65%": { yPercent: 500, scaleX: 1, scaleY: 1 },
"100%": { yPercent: 0, scaleX: 1, scaleY: 1 },
easeEach: "sine.out"
},
duration: 0.8,
repeat: -1,
transformOrigin: "center bottom"
});
gsap.to(".shadow", {
scale: 0.7,
duration: 0.4,
repeat: -1,
yoyo: true,
ease: "sine.inOut",
transformOrigin: "center"
});
Test 2
gsap.to(".box", {
keyframes: {
y: [0, 80, -10, 30, 0],
ease: "none", // <- ease across the entire set of keyframes (defaults to the one defined in the tween, or "none" if one isn't defined there)
easeEach: "power2.inOut" // <- ease between each keyframe (defaults to "power1.inOut")
},
rotate: 180,
ease: "elastic", // <- the "normal" part of the tween. In this case, it affects "rotate" because it's outside the keyframes
duration: 5,
stagger: 0.2,
repeat: -1
});
Callbacks
gsap.to(".elem", {
keyframes: [
{x: 100, duration: 1},
{y: 200, duration: 1, onComplete: () => { console.log('complete')}},
{rotation: 360, duration: 2, delay: -0.25, ease: 'sine.out'}
]
});
gsap.to(".elem", {
keyframes: {
"0%": { x: 100, y: 100},
"75%": { x: 0, y: 0, ease: 'power3.inOut'},
"100%": { x: 50, y: 50, ease: 'none', onStart: () => { console.log('start')} }
},
duration: 2,
})