Before we get into anything else, please behold this gross hack:
<html>
<head></head>
<style>
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.spinny {
width: 100px;
height: 100px;
animation-name: spin;
animation-duration: var(--theta);
animation-iteration-count: infinite;
animation-timing-function: linear;
}
</style>
<body>
<h1>Animation demo</h1>
<div style="" class="spinny">:(</div>
<div style="--theta: 4000ms" class="spinny">:)</div>
<div style="--theta: 2000ms" class="spinny">:D</div>
<div style="--theta: 500ms" class="spinny">XD</div>
</body>
</html>
Please load this into a file and view it on your local machine.
We create an animation class (spinny
) using a relatively boring animation (spin
). We then create four divs showing varying degrees of rotation.
The interesting part is the use of CSS custom properties. The --theta
property is used via var(--theta)
in the spinny
class definition; whenever that class is used, it’s going to attempt to spin the element. However, the speed of the animation is going to be based on the animation-duration
property, which is not defined for the first element. But, if you look at the other three divs, you see a style
attribute being set which binds that custom property to a particular–and more importantly element-specific–value, and so the animation speed for each element is different.
I’ve been doing some…weird…things with Phoenix LiveView recently. I’m not ready to talk about it yet much. However, the salient point is that LiveView will patch DOM elements and properties at the behest of the server.
So, imagine if you have a bunch of elements that you want to animate but you don’t want the server to have to do everything. Say, for example, you have a sprite that needs to move across the screen.
Well, the server can of course push down new positions for every step of the way. That’s great, but means the poor server has to do a lot of work to keep up with many clients at 60fps. And for the end user, if the latency gets too high or the server takes too long between updates, it looks like the div is teleporting across its path.
What if instead, we had a CSS animation that offset the sprite in the direction of travel? That would animate at 60fps and do all of the work client-side. Because animations are reset every time the element is touched (due to something about how LiveView does DOM patching, though of course other methods exist) if a server update comes through mid-animation with a new position that’s fine–we’re using a linear interpolation anyways, so restarting the same animation from a new position on the same trajectory won’t matter. When the server update comes to say “hey, we’re no longer moving”, the class just needs to be left off in the update.
Pretty neat–or as a colleague put it:
haha holy shit that’s the product of a deranged mind, and I’m all for it