- 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);
InterpolationInterpolations 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)CSSValues are converted into InterpolableValues, a minimal representation that we can easily perform calculations on
Interpolation (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 value
InterpolationInterpolableValues 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>
Interpolations are still generated for each property in each pair of keyframes
Interpolation
InterpolationPipelineStages is created
InterpolationInterpolations will be evaluated and their values accumulated
RenderStyle (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 addition
InterpolableValues 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>
inheritline-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 timeInterpolableValuesInterpolation creation for partitioning