- CSS values could be changed, but not smoothly
.button { background-color: darkblue; } .button:hover { background-color: deepskyblue; }
.button { background-color: darkblue; } .button:hover { background-color: deepskyblue; }
.button { background-color: darkblue; transition: background-color 1s; } .button:hover { background-color: deepskyblue; }
.button { background-color: darkblue; } .button:hover { animation: pulsate 1s infinite alternate; } @keyframes pulsate { 0% { background-color: darkblue; } 100% { background-color: deepskyblue; } }
element.animate([ {backgroundColor: 'darkblue'}, {backgroundColor: 'deepskyblue'}, {backgroundColor: 'darkblue'} ], {duration: 1000});
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '100px'}, {left: '500px'}, {left: '100px'} ], 1000); </script>
<style> #box { left: 200px; } </style> <script> box.animate([ {left: '200px'}, {left: '600px'}, {left: '200px'} ], 1000); </script>
<style> #box { left: 200px; } </style> <script> box.animate([ {left: '0px', composite: 'add'}, {left: '400px', composite: 'add'}, {left: '0px', composite: 'add'} ], 1000); </script>
<style> #box { left: 100px; } </style>
<script>
box.animate([
{left: '0px', composite: 'add'},
{left: '400px', composite: 'add'},
{left: '0px', composite: 'add'}
], 1000);
</script>
<style> #box { left: 100px; } </style>
<script>
box.animate([
{left: '-50px', composite: 'add'},
{left: '50px', composite: 'add'}
], {duration: 500, iterations: Infinity, direction: 'alternate',
easing: 'ease-in-out'});
</script>
<style> #box { left: 100px; } </style>
<script>
box.animate([
{left: '0px', composite: 'add'},
{left: '800px', composite: 'replace'},
{left: '0px', composite: 'add'}
], 1000);
</script>
<style> #box { left: 0px; } </style> <script> box.animate([ {left: '0px', composite: 'replace'}, {left: '800px', composite: 'replace'}, ], 5000); </script>
<style> #box { left: 0px; } </style> <script> box.animate([ {left: '-50px', composite: 'add'}, {left: '50px', composite: 'add'}, ], {duration: 500, iterations: 10, direction: 'alternate', easing: 'ease-in-out'}); </script>
<style> #box { left: 400px; } </style> <script> box.animate([ {left: '-200px', composite: 'add'}, {left: '200px', composite: 'add'}, ], {duration: 3000, iterations: Infinity, direction: 'alternate', easing: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'}); </script>
<style> #box { left: 400px; top: -200px; } </style> <script> box.animate([ {left: '-200px', composite: 'add'}, {left: '200px', composite: 'add'}, ], {duration: 3000, iterations: Infinity, direction: 'alternate', easing: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'}); box.animate([ {top: '-200px', composite: 'add'}, {top: '200px', composite: 'add'}, ], {duration: 3000, iterations: Infinity, direction: 'alternate', delay: -1500, easing: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'}); </script>
<style> #box { left: 400px; top: -200px; } </style> <script> ... box.animate([ {left: '-50px', composite: 'add'}, {left: '50px', composite: 'add'}, ], {duration: 200, iterations: Infinity, direction: 'alternate', easing: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'}); box.animate([ {top: '-50px', composite: 'add'}, {top: '50px', composite: 'add'}, ], {duration: 200, iterations: Infinity, direction: 'alternate', delay: -100, easing: 'cubic-bezier(0.445, 0.050, 0.550, 0.950)'}); </script>
// Note that composite: 'replace' is implicit box.animate([{left: '100px'}, {left: '200px'}], 1000);
Interpolation
Interpolation
s go through 3 stages:
box.animate([{left: '100px'}, {left: '200px'}], 1000); box.animate([{left: '0px'}, {left: '300px'}], 1000);
Interpolation
is generated for each property in each pair of keyframes
Interpolation
that's used is dependent on the types of the values (here, it's LengthStyleInterpolation
)CSSValue
s are converted into InterpolableValue
s, a minimal representation that we can easily perform calculations onInterpolation
(the most recent one) is createdInterpolableValue
InterpolableValue
to a CSSValue
and applied to the RenderStyle
, so the element will be rendered with the new property valueInterpolation
InterpolableValue
s will need to be added together<style> #box { left: '100px'; } </style> <script> box.animate([{left: '100px', composite: 'add'}, {left: '200px', composite: 'add'}], 1000); box.animate([{left: '0px', composite: 'add'}, {left: '300px', composite: 'add'}], 1000); </script>
Interpolation
s are still generated for each property in each pair of keyframes
Interpolation
InterpolationPipelineStage
s is created
Interpolation
Interpolation
s will be evaluated and their values accumulatedRenderStyle
(as a CSSValue
), and a constant Interpolation
is created from itInterpolation
is created from the underlying value, we get the benefits of its representation as an InterpolableValue
, such as easy additionInterpolableValue
s are passed from each pipeline stage to the next, and combined according to their underlying fraction<style> #box { left: 100px; } </style> <script> box.animate([{left: '0px'}, {left: '800px'}], {duration: 5000, iterations: Infinity}); box.animate([ {left: '-50px', composite: 'add'}, {left: '50px', composite: 'add'}, ], {duration: 500, direction: 'alternate', easing: 'ease-in-out', iterations: Infinity}); </script>
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '0px', composite: 'add'}, {left: '800px', composite: 'replace'} ], 1000); </script>
inherit
line-height
accepts both lengths and numbers<style> #text { line-height: 2; } </style> <script> text.animate([ {lineHeight: '30px', composite: 'add'}, {lineHeight: '40px', composite: 'add'} ], 1000); </script>
<style> #text { line-height: 2; } </style> <script> text.animate([ {lineHeight: '30px', composite: 'add'}, {lineHeight: '40px', composite: 'add'} ], 1000); </script>
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '100px'}, {left: '800px'} ], {duration: 1000, easing: 'cubic-bezier(.42, 0, .58, 1)'}); </script>
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '100px'}, {left: '800px'} ], {duration: 1000, easing: 'cubic-bezier(.41, 1.94, .72, -0.91)'}); </script>
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '100px', fontFamily: 'Verdana'}, {left: '800px', fontFamily: 'Courier New'} ], 1000); </script>
<style> #box { left: 100px; } </style> <script> box.animate([ {left: '100px', fontFamily: 'Verdana'}, {left: '800px', fontFamily: 'Courier New'} ], {duration: 1000, easing: 'cubic-bezier(.41, 1.94, .72, -0.91)'}); </script>
Interpolation
is created for each regionInterpolation
is chosen and added to the pipeline, enabling addition<style> #element { width: 100px; } </style> <script> element.animate([ {width: 'auto', composite: 'add'}, {width: '50px', composite: 'add'} ], {duration: 1000, easing: 'cubic-bezier(.41, 1.94, .72, -0.91)'}); </script>
inherit
<style> #parent { line-height: 2; } #child { line-height: inherit; } </style> <div id="parent"> <div id="child"> Hello, World! </div> </div>
inherit
keyword resolves to the element's parent's valueinherit
is only known at apply timeInterpolableValue
code path doesn't support inherit
yet, so adding with inherit
isn't yet possible
inherit
by deferring the creation of 'interpolations' using the keyword until apply timeInterpolableValue
sInterpolation
creation for partitioning