w3c / fxtf-drafts

Mirror of https://hg.fxtf.org/drafts
https://drafts.fxtf.org/
Other
71 stars 50 forks source link

[motion] Blink shipping animation of offset-path path strings #225

Closed ewilligers closed 6 years ago

ewilligers commented 7 years ago

SVG Background

Spec:

Path data animation is only possible when each path data specification within an animation specification has exactly the same list of path data commands.

SMIL implementations have ignored case when comparing path data commands, but have treated H/L/V as distinct line commands, Q/T as distinct quadratic Bezier types and C/S as distinct cubic Bezier types.

Blink shipped CSS animation of the 'd' presentation attribute with this same behavior. The shipped syntax is none | path(<string>) which matches offset-path and matched the spec at the time of implementation (but not shipping as I didn't realize the spec was being changed - SVG #320).

offset-path

The motion-path property: was not animatable, but the offset-path property is animatable, and Blink would like to ship animation (Intent).

More general interpolation

During the Intent conversation, there were suggestions for more general interpolation, between the different line commands, and between lines and splines. There was also the suggestion that the serialization format be specified. I brought this conversation across to SVG #321 and consensus has been reached.

The outcome: animation will be supported between lines and splines, but not between arcs and other command types. Quadratic splines will be promoted as needed to cubic splines. Lines will be promoted as needed to quadratic and cubic splines.

Blink will contribute web platform tests for offset-path path string animation and ray animation. (Tests for animation of the other offset properties have already been contributed. Implementation of basic shapes has begun in a polyfill but not yet in Blink.)

Blink's implementation of SMIL path animation won't change at this time.

However, 'd' presentation attribute animation will change: the CSS path animation implementation will be common for d and offset-path.

Serialization format

The serialization format will use absolute commands: e.g. nothing lowercase, no B (bearing) commands. Thus serialized paths for 'offset-path' and 'd' will contain only M Z L Q C A commands. (There may also be R (Catmull-Rom curve) commands if they can't be losslessly converted to cubic Beziers. Note that B and R are being mentioned for spec completeness, they are not implemented in Blink.)

SVG #320 remains open.

Shipping

This change is expected to ship in Chrome 64.

Blink implementation of offset-position, offset-anchor and ray path is in progress, not ready to ship.

svgeesus commented 7 years ago

In the very early days of SVG, I briefly argued that paths should all be non-uniform rational basis splines (NURBS) because that would give us two desirable properties - perspective transforms on the points were the same as perspective transforms on the curves, and two NURBS of arbitrary length could be smoothly interpolated. The downside being that everything, even a line segment, is expressed as a curve. At the time we had only affine transformations, and the early drafts of SVG only allowed animation via script, so compatibility with the cubic and quadratic beziers universally used in industry-standard applications won the day. Probably the right decision at the time, but here we are trying so solve the arbitrary lath interpolation problem a couple of decades later.

I agree that when comparing two d attrs for interpolatability, we should unify exact equivalents (Q & T, C & S, H & L & V) and not unify approximate equivalents (A and QTCS and R). The easiest way to do that is to define a canonical form of a d attr. The promotions you mention all seem reasonable to me; do they then get reflected back into the DOM or are this hidden, animation-time changes only?

Animation of offset-path sounds great. Happy to see this.

Also glad to see you will contribute tests to WPT for those changes - please let me know if you need a review.

css-meeting-bot commented 7 years ago

The Working Group just discussed offset-path strings, and agreed to the following resolutions:

The full IRC log of that discussion <TabAtkins> Topic: offset-path strings
<TabAtkins> GitHub: https://github.com/w3c/fxtf-drafts/issues/225
<florian> Action Florian to propose text to resolve issue 1828
<trackbot> Created ACTION-864 - Propose text to resolve issue 1828 [on Florian Rivoal - due 2017-10-11].
<TabAtkins> ericwilligers: When you animate a path string in SVG using both upper and lowercase commands, there's no way to read it back out. But CSS can do so.
<TabAtkins> ericwilligers: So we have a proposal to normalize the path strings to a canonical representation during animation.
<TabAtkins> ericwilligers: Related: You're not allowed to animate between different commands even if they're very similar, like H (horizontal line) to L (any-direction line).
<TabAtkins> ericwilligers: There was a suggestion that we should allow it.
<TabAtkins> ericwilligers: There was little UA participation of this in SVGWG tho, so bringing it up here.
<TabAtkins> shane: I don't think anybody thinks its a *bad* idea, but just low use-cases for explicit promotion.
<TabAtkins> ericwilligers: So I'd like to ship offset-path and d, and it's more useful if you can animate them.
<TabAtkins> TabAtkins: So three proposals:
<TabAtkins> TabAtkins: 1) animate path(), affecting motion-path and d (this already has a resolution on it)
<TabAtkins> TabAtkins: 2) When animating, normalize abs and rel commands (upper and lowercase) to a single canonical form (uppercase, specifically) so you can animate "h" and "H".
<TabAtkins> TabAtkins: 3) When animating, normalize "families" of similar commands into a single canonical command, so H/V/L all become L, etc, because they're just convenience syntaxes for each other and not significant differences that should stop animation.
<TabAtkins> shane: Animation of path() in SVG is pretty underspecified in SVG2 right now.
<TabAtkins> shane: It says that 2 property values can only be inteprolated smoothly when the paths have the same structure (same number and type of command).
<TabAtkins> shane: "type" isn't really specified - could mean individual commands, or ignoring abs/rel, or in families.
<TabAtkins> shane: It's hard to say what SVG2 *intends* to specify here fo rinterpolation.
<TabAtkins> shane: I think you want normalization to reflect interpolation behavior.
<TabAtkins> shane: If we said today that we wanted path() to animate between two lines, it should promote between any two line types.
<TabAtkins> shane: Eric suggets shipping the de facto SVG behavior now, iterate on it later. I'm a little afraid of being able to change that later.
<TabAtkins> shane: I think the current behavior is poor for authors. If you wanna do any animation you have to fall back on tools, and those tools dont' exist today.
<TabAtkins> dino: I think we need to define an animation between two paths of any type.
<TabAtkins> dino: If what we come up with conflicts with what's about to ship, defined in SVG1, that would be sad, but I don't think it would be a horrible break.
<TabAtkins> dino: In general I think we should give authors a better experience.
<TabAtkins> TabAtkins: I think if we ship current SVG and then upgrade later, it'll just make things start animating, which is a minor break and probably fine.
<TabAtkins> shane: But also would change computed style - we'd want eventually to normalize eagerly in computed style.
<TabAtkins> TabAtkins: Ah, that's more of a change than I thought.
<TabAtkins> fremy: I'd like to have Bogdan around.
<birtles> I think there's precedent for this with `transform` (i.e. we define rules for animating between different types of transforms and we also normalize to matrix() in computed style)
<TabAtkins> shane: One of Bogdan's concerns was no use-cases; we completely disagree. As soon as you try to path-animate, you run into this. It's basically every single use.
<birtles> normalizing in computed style also makes parsing the value a lot easier for authors
<TabAtkins> shane: He also thought it might prevent them from doing certain types of OS acceleration.
<TabAtkins> shane: We've implemented generic path animation before, it's more expensive, but not something we should consider a concern I think.
<birtles> there are a lot of SVG scripts hanging around that only deal with the subset of path commands the author could be bothered to deal with, since there are just too many otherwise
<TabAtkins> TabAtkins: I think B commands are significant - you get different animation behavior whether you animate a B or resolve it away. It seems useful to keep.
<TabAtkins> shane: I do think we shouldn't add or remove commands, just promote to the most general.
<TabAtkins> shane: And then we could maybe have magic for when the number of commands don't match, like transforms do with matrix().
<TabAtkins> shane: We have an impl of that, and it works pretty well.
<TabAtkins> astearns: So should we resolve on the abs/rel normalization today?
<TabAtkins> RESOLVED: Computed-value normalize case of path commands (to the absolute version).
<TabAtkins> astearns: And it sounds like we're interested in normalizing similar commands, but don't yet have consensus on details.
<TabAtkins> shane: Should we open something on the CSSWG tracker?
<TabAtkins> astearns: Yes.
<TabAtkins> astearns: Anyone object to the general idea of normalizing similar commands?
<TabAtkins> RESOLVED: Figure out details on normalizing similar commands into more general ones.
tabatkins commented 7 years ago

B should be preserved, I think. Animating between B 0 H 100 and B 90 H 100 gives dramatically different results if you do or don't normalize away the Bs. If you keep the Bs, you get a circular sweep, with a length-100 line turning thru 90 degrees. If you normalize them away (to L 100 0 and L 0 100, I think), you get a line where the endpoint goes straight from the start to finish, and the line changes length from 100 to ~71 back to 100 at the end.

In real-world use-cases, B is extraordinarily useful for rotating a path - rather than screwing around with transforms, you can just define the path once, then prepend a B to put it at the angle you want. This also helps a lot when a particular path segment uses easy-to-define numbers when axis-aligned, but requires trig to figure out the endpoints when rotated - instead, just do it axis-aligned and prepend a B. In both of these situations, normalizing away the B would look pretty bad.

ewilligers commented 6 years ago

This is shipping in Chrome 64.