Reputation: 15
The JS Animation is using the built in JS Animate function https://developer.mozilla.org/en-US/docs/Web/API/Element/animate
myRef.current.animate(
[
{transform: `translatey(32.5px)`, offset: 0},
{transform: `translatey(-2260px)`, offset: 0.9},
{transform: `translatey(-2260px)`, offset: 0.95},
{transform: `translatey(-2247.5px)`, offset: 1}
],
{
duration: 4000,
easing: 'cubic-bezier(0.33, 1, 0.68, 1)',
fill: 'forwards',
iterations: 1,
}
)
vs
.test {
animation: 4s cubic-bezier(0.33, 1, 0.68, 1) forwards spin1;
}
@keyframes spin1 {
0% {
transform: translatey(32.5px);
}
90% {
transform: translatey(-2260px);
}
95% {
transform: translatey(-2260px);
}
100% {
transform: translatey(-2247.5px);
}
}
Expected same result from both but for some reason the JS one snaps onto the offsets, while the CSS one is smoother and doesn't snap.
Upvotes: 0
Views: 55
Reputation: 137133
This is because in CSS, the animation-timing-function
affects each KeyFrame
instead of the whole animation:
.anim {
height: 300px;
background: pink;
border: 2px solid purple;
animation: 8s cubic-bezier(0, -1, 1, 0) forwards anim;
}
@keyframes anim {
0% { width: 50px }
25% { width: 150px }
50% { width: 250px }
75% { width: 350px }
100% { width: 450px }
}
Here you can see the <code>animation-timing-function</code> has been applied 4 times.
<div class="anim"></div>
The easing
property you've set in your KeyframeEffect
option object is the one that applies to the entire iteration duration of the keyframe effect. This doesn't apply on each KeyFrame
, but on the whole animation:
const el = document.querySelector(".anim");
el.animate(
[
{ width: "50px" },
{ width: "150px" },
{ width: "250px" },
{ width: "350px" },
{ width: "450px" },
],
{
duration: 8000,
fill: "forwards",
easing: "cubic-bezier(0, -1, 1, 0)",
},
);
.anim {
height: 300px;
background: pink;
border: 2px solid purple;
}
Here you can see the <code>easing</code> timing function has been applied only once.
<div class="anim"></div>
To get the same effect as with CSS animation-timing-function
, you need to set it to all your KeyFrame
objects.
const el = document.querySelector(".anim");
el.animate(
[
{ width: "50px", easing: "cubic-bezier(0, -1, 1, 0)" },
{ width: "150px", easing: "cubic-bezier(0, -1, 1, 0)" },
{ width: "250px", easing: "cubic-bezier(0, -1, 1, 0)" },
{ width: "350px", easing: "cubic-bezier(0, -1, 1, 0)" },
{ width: "450px", easing: "cubic-bezier(0, -1, 1, 0)" },
],
{
duration: 8000,
fill: "forwards"
},
);
.anim {
height: 300px;
background: pink;
border: 2px solid purple;
}
Here you can see the <code>easing</code> timing function has been applied 4 times.
<div class="anim"></div>
Or to avoid repeating many times the same values:
const el = document.querySelector(".anim");
el.animate(
{
width: [ "50px", "150px", "250px", "350px" ],
easing: [ "cubic-bezier(0, -1, 1, 0)" ],
},
{
duration: 8000,
fill: "forwards"
},
);
.anim {
height: 300px;
background: pink;
border: 2px solid purple;
}
Here you can see the <code>easing</code> timing function has been applied 4 times.
<div class="anim"></div>
Upvotes: 1