I’m trying to understand if it’s possible to accumulate animations with the Web API animation and I can’t seem to figure it out.
//move element very fast to 100,100 with no duration
el.animate([{transform: 'translate(100px, 100px)'}], {duration: 0, fill: 'forwards'});
//add another movement after that with duration
el.animate([{transform: 'translateX(200px)'}], {duration: 0, fill: 'forwards', composite: 'accumulate'});
Everything happens properly, the box moves to 100,100 then the animation starts. The problem is, at the end of the animation, the boxes moves up like it has suddenly lost the Y transform. It is possible to keep the Y transform at the end? I thought fill: 'forwards' + composite : 'accumulate'
would do that …
Note: once in a while, it does behave properly so I’m not sure what’s going on. The expected behavior is
- Move box to 100,100
- Then apply a relative transform, meaning the box would end up at 300,100
const el = document.querySelector('.box');
el.animate([{transform: 'translate(100px, 100px)'}], {duration: 0, fill: 'forwards'});
el.animate([{transform: 'translateX(200px)'}], {duration: 2000, fill: 'forwards', composite: 'accumulate'});
.container{
display: block;
height: 100vh;
overflow: hidden;
}
.box{
position: absolute;
width: 300px;
height: 200px;
background-color: brown;
}
<div class="container">
<div class="box">
</div>
</div>
2
Answers
I think in order to achieve that, you would need to remove the transform and set your animate function with
left
andtop
properties.As I clearly understand from your post and have tested it a bit, you wanted your current box to remain in the last position where the second animations ends. The transform function I think it is a bit tricky though as it is somehow resetting the Y axis position and it pushes your box to the top of the container for some reason.
I believe it is better to work both of your animations with the aforementioned properties.
I am attaching you a reproducible example which for me the animations are working as expected from what you described.
I hope that can help you with what you seek.
As far as I remember
composite
option is not that smart, it compiles different types of transforms into one, but much more like string concatenation. This behavior can change in the future based on different vendors.For the time being, you can use
DOMMatrix
to perform the operations you want prior to animating the element. This gives you quiet a bit of control on how you would want ‘composite’ to behave.In the example I am using a dom manipulation library but you can easily get the promise from native
Element.animate
viafinished
prop. The rest is getting the current transformation matrix viagetComputedStyle
and using that to accumulate transformations viaDOMMatrix.prototype
. In this example, I am usingDOMMAtrix.prototype.translateSelf
.