{"id":264051,"date":"2018-01-02T08:37:50","date_gmt":"2018-01-02T15:37:50","guid":{"rendered":"http:\/\/css-tricks.com\/?p=264051"},"modified":"2020-03-30T15:31:52","modified_gmt":"2020-03-30T22:31:52","slug":"additive-animation-web-animations-api","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/additive-animation-web-animations-api\/","title":{"rendered":"Additive Animation with the Web Animations API"},"content":{"rendered":"
These features have not landed in any stable browsers at the time of writing. However, everything discussed is already in Firefox Nightly<\/a> by default and key parts are in Chrome Canary<\/a> (with the Experimental Web Platform Features flag enabled), so I recommend using one of those browsers (when reading this article) to see as many of the features in action as possible.<\/p>\n Regardless your preferred method of animation on the web, there will be times that you need to animate the same property in separate animations. Maybe you have a hover effect that scales an image and a click event that triggers a translate \u2014 both affecting the <\/p>\n The second animation in this Web Animations API example is the only one that would be visually rendered in this example as both animations play at the same time and it was the last one defined.<\/p>\n Sometimes we even have grander ideas where we want a foundational animation and then based on some user interaction change in state we smoothly modify the animation a bit midway without affecting its existing duration, keyframes, or easing. CSS Animations and the current Web Animations API in stable browsers today cannot do this out of the box.<\/p>\n The Web Animations specification introduces the The Now both animations will be seen as the browser on the fly figures out the appropriate transformation at a given point in the element’s timeline accounting for both transformations. In our examples, the easing is See the Pen Animation Composite <\/a> by Dan Wilson (@danwilson<\/a>) on CodePen<\/a>.<\/p>\n An individual animation does not just consist of a start state and end state \u2014 it can have its own easing, iteration count, duration, and more keyframes in the middle. While an element is mid animation you can throw an additional transformation on it with its own timing options.<\/p>\n See the Pen Add more transform animations<\/a> by Dan Wilson (@danwilson<\/a>) on CodePen<\/a>.<\/p>\n This example lets you apply multiple animations on the same element, all affecting the When each animation starts, the browser will effectively find where it is in its previously applied animations and start a new rotation animation with the specified timing options. Even if there is already a rotation going in the opposite direction, the browser will do the math to figure out how much a rotation needs to happen. Since each animation in our example starts at the default value (0 for translations and 1 for scaling) we get a smooth start. If we instead had keyframes such as transform<\/code>. By default, those animations do not know anything about the other, and only one will visually be applied (since they are affecting the same CSS property and the other value will be overridden).<\/p>\n
element.animate({\n transform: ['translateY(0)', 'translateY(10px)']\n}, 1000);\n\n\/* This will completely override the previous animation *\/\nelement.animate({\n transform: ['scale(1)', 'scale(1.15)']\n}, 1500);<\/code><\/pre>\n
A New Option<\/h3>\n
composite<\/code> property<\/a> (and the related
iterationComposite<\/code>). The default
composite<\/code> is
'replace'<\/code> and has the behavior we have had for years now where an actively animating property’s value simply replaces any previously set value \u2014 either from a rule set or another animation.<\/p>\n
'add'<\/code> value is where things change from the previous norms.<\/p>\n
element.animate({\n transform: ['scale(1)', 'scale(1.5)']\n}, {\n duration: 1000,\n fill: 'both'\n});\nelement.animate({\n transform: ['rotate(0deg)', 'rotate(180deg)']\n}, {\n duration: 1500,\n fill: 'both',\n composite: 'add'\n});<\/code><\/pre>\n
'linear'<\/code> by default and the animations start at the same time, so we can break out what the effective
transform<\/code> is at any given point. Such as:<\/p>\n
\n
scale(1) rotate(0deg)<\/code><\/li>\n
scale(1.25) rotate(60deg)<\/code> (halfway through first animation, 1\/3 through second)<\/li>\n
scale(1.5) rotate(120deg)<\/code> (end of first, 2\/3 through second)<\/li>\n
scale(1.5) rotate(180deg)<\/code> (end of second)<\/li>\n<\/ul>\n
So Let’s Get Creative<\/h3>\n
transform<\/code> property. To keep from going all out in this example, we limit each animation to a single transformation function at a time (such as only a
scale<\/code>), starting at a default value (such as
scale(1)<\/code> or
translateX(0)<\/code>), and ending at a reasonable random value on that same transformation function, repeated infinitely. The next animation will affect another single function with its own randomized duration and easing.<\/p>\n
element.animate(getTransform(), \/\/e.g. { transform: ['rotate(0deg), 'rotate(45deg)'] }\n{\n duration: getDuration(), \/\/between 1000 and 6000ms\n iterations: Infinity,\n composite: 'add',\n easing: getEasing() \/\/one of two options\n});<\/code><\/pre>\n
\nSince each animation has its own timing options, you are unlikely to see the exact same motion repeated in this example once you have added a few. This gives the animation a fresh feel as you watch it.<\/p>\n{ transform: ['scale(.5)', 'scale(.8)'] }<\/code> we would get a jump because the didn’t have this
scale<\/code> before and all of a sudden starts its animation at half scale.<\/p>\n