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

After this change, will Blink match Safari?
If not, Safari can't change its behavior since it relies on the operation
system to do animations...


On Mon, May 6, 2013 at 3:46 PM, 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 Monday, 6 May 2013 23:03:19 UTC