w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 664 forks source link

[svg-2][css-transitions] Can we fix arc interpolation? #10195

Open LeaVerou opened 7 months ago

LeaVerou commented 7 months ago

Currently paths are naively interpolated by matching up segments and points and interpolating them as numbers. This is defined in the SVG 2 spec:

For animation, two d property values can only be interpolated smoothly when the path data strings contain have the same structure, (i.e. exactly the same number and types of path data commands which are in the same order). If an animation is specified and the lists of path data commands do not have the same structure, then the values must be interpolated using the discrete animation type.

If the list of path data commands have the same structure, then each parameter to each path data command must be interpolated separately as real numbers. Flags and booleans must be interpolated as fractions between zero and one, with any non-zero value considered to be a value of one/true.

So basically, control points are animated separately, and flags (of which the arc command has two!) just flip halfway. As you can see in this demo this produces terrible, terrible results.

Here is another example: a dynamic pie chart using CSS transitions on d to animate across state changes (using a 3s duration to clearly show what’s happening):

https://github.com/w3c/csswg-drafts/assets/175836/3b88b0ce-0254-41a4-b546-fd5fb58ef4b8

We can easily fix this by adopting smarter interpolation rules for arc commands, which interpolate the actual features of the arc (offset, angle, radii, etc.) instead of the coordinate points and flags. Can we do this? Is it web compatible?

tabatkins commented 7 months ago

First, that video is incredible. The web platform rules.

I'm not sure about web-compat, but worst case we can trigger this some other way.

But yeah, I don't see a reason why arcs couldn't be animated by their features, and it would give a better result in any situation I can imagine. Even with complex paths that happen to include an arc - they'll have to animate arc-to-arc anyway, and you almost certainly want the smoother, more reasonable behavior of feature-animation rather than control point-animation (+ discrete flag flips).

Specifically, the features would be :

The only cases I can immediately imagine being a little weird are if you're changing only the flags, because in either case changing a flag also reverses the angle of the end point relative to the start point, so it'll cause the arc to shrink to zero partway thru the animation. If you wanted to invert a pie wedge to the complement, which you can do just by flipping the size flag, to get a good animation (aka the wedge just spinning around the center and growing/shrinking to the new size) you'd also want to invert the start/end point, so it kinda rotates into the new position (rather than the endpoint just sweeping 360deg around). But I think that's the necessary behavior, and you might very well want the "shrink to zero" in some cases.

myfonj commented 7 months ago

Historical side note: at this point, for the "pie graph" (circle segments) colouring and animating (like in the video), stroke-dasharray and stroke-dashoffset are abused in the wild, like so:

<style>
circle { animation: 8s a infinite ease-in-out; }
@keyframes a {
<..>% { stroke-dasharray: <"like angle">, 360; stroke-dashoffset: <"start, 0=45deg">; }
}
</style>
<body>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-1,-1,2,2">
 <circle r=".5" pathlength="360" fill="none" stroke="currentcolor"></circle>
</svg>

(Sandbox)

svgeesus commented 7 months ago

The interconversion between the SVG syntax (which ensures that the path command starts at the current point, and ends with the new current point) and the meaningful parameterization that literally everyone else uses for elliptical arcs is given with ass-clenching detail in

F.6 Elliptical arc implementation notes