UPDATE: I’ve heavily edited the following based on feedback from Dr. Hoffmann.
One implementation issue I discovered with regards to <animateTransform>
is
how to accumulate repeated transformations.
Consider the following example:
<svg xmlns="http://www.w3.org/2000/svg">
<path d="M-2 50h4v -90h4l -6 -10 -6 10h4z" fill="blue">
<animateTransform attributeName="transform" attributeType="XML"
type="skewX" fill="freeze" from="0" to="22" dur="0.3s"
repeatCount="3" accumulate="sum"/>
</path>
</svg>
A skew operation produces a transformation matrix with one element set to tan(angle), so here it would be tan(22) at the end of the simple duration. After 3 repetitions, what would be the value of this element? If we just accumulate the animation parameters (i.e. angle=22), then we’d get tan(3 * 22), i.e. tan(66). However, if we accumulate using post-multiplication of matrices the answer is not tan(3 * 22) but 3 * tan(22).
In the graphic below the black outline represents the result if we just add up the animation parameters (i.e. skew by 66 degrees), whilst the red outline represents the result when we use matrix multiplication.
In my testing, in Opera 9.62 the arrow ends up inside the black outline whereas in Batik 1.7 it ends up inside the red outline.
So which is correct? SVG
1.1
says that for additive animation (additive="sum"
) with <animateTransform>
we
should post-multiply matrices.
However, is the addition used when performing additive animation the same as the addition used when accumulating repetitions? SMILANIM 3.3.1 seems to suggest some relationship between the two when it says:
[The cumulative attribute] is ignored if the target attribute value does not support addition
However, in the SVG Tiny 1.2 Test Suite a different view has been taken. See Dr. Hoffmann’s comments below for a proper explanation. My understanding is that different addition is to be used at different stages of the compositing.
When we are calculating cumulative values, SMIL3 gives us the formula:
fi(t) = (f(d) * i) + f(t - (i*d))
This simply operates on the animation parameters. So in the example at the beginning, it means tan(3 * 22). However, when we come to composite with underlying values in the animation sandwich, a different kind of addition is used. For this, SMIL3 gives the following formula:
F(t,u) = u + ff(t)
Here, for <animateTransform>
we should use matrix post-multiplication, i.e.
3 * tan(22).
No, clearly tan(3 * 22) is correct, because there is no specific rule for accumulation in SVG, therefore it applies what is defined in SMIL and this is the addition of the values of the animated attribute and not some multiplication of some abstract effect.
How to calculate the animation effect, is much better described in SMIL2 and SMIL3. This results in a clear procedure and leads clearly to the correct result, simply because the effect of cumulation is calculated much earlier than that of the relation to the underlying value, what is (only) modified for animateTransform by SVG.
I provided exhaustive test for this issues about additive and cumulative behaviour for the SVGT 1.2 test suite, testing all combinations for from-to, from-by, by and values animations.