JSFiddle - React, Tailwind, and code Playground
by Glenn Marks
HTML
<div id=target></div>
<button id=show type=button>Show</button>
<button id=hide type=button>Hide</button>
<p><strong>Reversed:</strong> <span id=reversed>false</span></p>
<p><strong>Playing:</strong> <span id=playing>false</span></p>
<p><strong>State:</strong> <span id=state>Waiting</span></p>
<pre><code>
Under the new proposal, "State" could say:
- "Waiting"
- "Oooh, I'm warming up!"
- "Running"
- "Half way there"
- "Done - Just cooling down"
- "Waiting" (again)
--------------------------------------------------------------------
<strong>Note for Chrome:</strong> When animation is reversed,
an external event is required to update the finished state,
eg. pointer move or key down event.
There is a bug filed (<a href="https://bugs.chromium.org/p/chromium/issues/detail?id=1141935">star it</a>)
<!-- This is actually where i got most of this code from 😁 -->
</code></pre>
<p><b>Proposal</b></p>
<pre><code>
<span style=color:green>// Proposal usage example</span>
animation.onstart = () => {
state.innerText = "Oooh, I'm warming up!";
var isReverse = animation.playbackrate === -1;
target.style.opacity =
isReverse
? "1"
: "0";
playing.innerText = 'true'
playing.style.cssText += '--color: green'
reversed.innerText = isReverse.toString();
reversed.style.cssText += isReverse
? '--color: green'
: '--color: red';
};
animation.onKeyFrame = (index) => {
switch (index) {
case 0:
state.innerText = "Running";
break;
case 1:
state.innerText = "Half way there";
break;
default:
state.innerText = "Done - Just cooling down";
break;
}
};
</code></pre>
CSS
div {
width: 100px;
height: 100px;
background-color: black;
}
span {
color: var(--color, red);
}
JavaScript
const sustainOpacity = (direction) => {
target.style.opacity = direction === "forward" ?
"1" :
"0";
}
const animation =
target.animate({
opacity: [0, .5, 1]
}, {
delay: 3000,
endDelay: 3000,
duration: 4000
});
animation.onfinish = () => {
sustainOpacity(target.dataset.direction);
if (state.innerText !== 'Waiting') {
state.innerText = "Wait! I've done. When did that happen?"
}
playing.innerText = 'false'
playing.style.cssText += '--color:red'
};
animation.finish();
show.onclick = () => {
if (animation.playbackRate === 1) {
animation.play();
} else {
animation.reverse();
}
animationStart(false); // <= Drop this under new proposal
}
hide.onclick = () => {
if (animation.playbackRate === 1) {
animation.reverse();
} else {
animation.play();
}
animationStart(true); // <= Drop this under new proposal
}
// DROP THIS AS WELL
const animationStart = (isReverse) => {
state.innerText = "Oooh, I'm warming up!";
target.dataset.direction = isReverse ?
"reverse" :
"forward";
target.style.opacity =
target.dataset.direction === "forward" ?
"0" :
"1";
playing.innerText = 'true'
playing.style.cssText += '--color: green'
reversed.innerText = isReverse.toString();
reversed.style.cssText += isReverse ?
'--color: green' :
'--color: red';
}