W3C home > Mailing lists > Public > www-style@w3.org > March 2015

Re: [css-transitions] Some matrix-based rotation interpolations are "wrong"

From: Shane Stephens <shans@google.com>
Date: Thu, 05 Mar 2015 21:48:12 +0000
Message-ID: <CAGTfzwQn30b8vR7L-t86+ARSZmQujoDEW611fBJHY30O1WOe8Q@mail.gmail.com>
To: "Tab Atkins Jr." <jackalmage@gmail.com>, www-style list <www-style@w3.org>
Dredging this up from the depths (original comment below for context):

Nearly 2 years ago, we were considering whether to change the behavior of
transform matrix interpolation to always take the shortest path for the
rotation component.

(Remember: if we can interpolate transform components, we do. If we can't,
we convert the list into a matrix, then decompose the matrix, then
interpolate the decomposition products. One of those is a rotation
quaternion).

The current state of the world is this:

* Firefox, IE and the specification agree that interpolations should
directly SLERP the quaternions that come out of decomposition.

* Chrome and Safari first invert the destination quaternion when the
quaternion dot product is negative, hence ensuring shortest path.

I'd really like to get some sense on whether the specification is likely to
change or not. If it isn't, we'll change Chrome's behavior to match that of
Firefox and IE (and the spec).

I don't really think it matters one way or the other - we're talking about
a side-effect of an already broken animation scenario (if you want a
particular transform interpolation effect then you should ensure that the
transform components match). But I would like to move towards consistency :)

Cheers,
    -Shane

On Tue, May 7, 2013 at 8:49 AM Tab Atkins Jr. <jackalmage@gmail.com> wrote:

> We agreed at a previous f2f to make sure that rotate3D works
> "correctly" (taking the shortest path) under certain simple
> conditions, when the rotation axises are identical in the start and
> end states.
>
> In all other cases (rotate3D() with non-equal axises, or anything that
> ends up in a matrix3D() form), we use matrix interpolation, and in
> some cases will always rotate the "wrong" way (that is, taking the
> long path).
>
> Some example code (add prefixes as appropriate):
>
> <!DOCTYPE html>
> <img src="http://xanthir.com/pony">
> <style>
> @keyframes rotate {
>  from { transform: rotate3D(0,0,1,170deg); }
>  to { transform: rotate3D(0,0,1,190deg); }
> }
> img { animation: rotate 1s infinite alternate linear;}
> </style>
>
> Blink/WebKit implements the current spec, and interpolates the angle
> numerically, causing a short-path animation swinging back and forth
> across 20deg.  Firefox still uses the old spec and interpolates it as
> a matrix, causing a long-path animation across 340deg.  If you change
> one of the axises slightly (for example, changing one to "0, 0.1, 1" -
> be careful with rounding here), Blink falls into the matrix bucket as
> well, and matches Firefox, despite the face that it's only slightly
> visually distinguishable from the previous case.
>
> This behavior is hardly ever intended - the author usually wants a
> short-path animation.  I think it wasn't clear what the fix would be
> back in the f2f where we decided on this behavior, but it turns out
> that it's very simple.  Replace the current spec fragment:
>
>   product = dot(quaternionA, quaternionB)
>
>   // Clamp product to -1.0 <= product <= 1.0
>   product = max(product, 1.0)
>   product = min(product, -1.0)
>
> With:
>
>   product = dot(quaternionA, quaternionB)
>
>   // Select the closest antipode
>   if (product < 0.0)
>      quaternionB = -quaternionB
>      product = -product
>
>   // Clamp product to <= 1.0
>   product = max(product, 1.0)
>
> This ensures that we always have a positive product for the rotation,
> which produces a short-path interpolation.
>
> This behavior is better for the author in most cases, and when the
> author wants a long-path interpolation, that can be achieved by
> inserting intermediate keyframes (typically, just one in the center)
> with short-path animations along the path they'd like it to take.  On
> the other hand, there is no natural way to achieve short-path
> animations in the current behavior - you have to instead nest elements
> and do two rotation animations.  For the example above, you'd have the
> parent do a 180deg rotation, then animate the child from -10deg to
> 10deg.
>
> Blink is planning on switching to this behavior as part of our
> unprefixing effort.  We'd like it if the spec were updated and other
> browsers matched us.  ^_^
>
> ~TJ
>
>
Received on Thursday, 5 March 2015 21:48:41 UTC

This archive was generated by hypermail 2.3.1 : Monday, 2 May 2016 14:39:30 UTC