What is the difference of SVG's additive="sum" between duration - svg

The difference of the following code?
Why the result is different from?
I thought it was the same.
However, different results when the cell actually animation.
<svg width="1000" height="1000">
<circle cx="10" cy="10" r="10">
<animate
attributeType="XML" attributeName="cx"
dur="10s" values="100; 200; 100"
repeatCount="indefinite" />
<animate
attributeType="XML" attributeName="cx"
dur="10s" values="0; 300; 0"
repeatCount="indefinite" additive="sum" />
</circle>
</svg>
<svg width="1000" height="1000">
<circle cx="10" cy="10" r="10">
<animate
attributeType="XML" attributeName="cx"
dur="19s" values="100; 200; 100"
repeatCount="indefinite" />
<animate
attributeType="XML" attributeName="cx"
dur="1s" values="0; 300; 0"
repeatCount="indefinite" additive="sum" />
</circle>
</svg>

Its not the time thats additive, if thats what you think, its the value of the attribute (cx).
As you have 2 animations running at the same time, cx will build up as a combination of whatever the values of cx are on each animation.
On the 2nd example. As one of the animations is only 1 second long, it will fluctuate very fast, on top of a slower animation.
If you forget about the additive for the moment, and just replace the 2nd cx value with cy on both, you will see why the animations are fundamentally different as well.

Related

SVG animation delay not working - repeated instantly

I am trying to create an SVG animation (basically I am moving a filter). How can I delay the animation after it is completed, so it does not restart immediatly. I tried setting an id and then adding the id.end + time but this is not working - the animation is repeated immediatly. Thanks for the help!
<mask id="mask1_1_7" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="92" height="82">
<rect id="MovingLayer_2" width="92" height="82" fill="#C4C4C4">
<animateTransform id="op"
attributeName="transform"
attributeType="XML"
type="translate"
from="0 0"
to="92 0"
dur="3s"
begin="0s;op.end+3s"
repeatCount="indefinite"
/>
</rect>
</mask>
As #enxaneta pointed out, using repeatCount="1" fixed the issue

SVG animateTransform toggle only working once

If you click two subsequent times on the rectangle, you see an animation toggling on and off:
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="project-10-activator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<animateTransform id="activate_project_10" begin="click" fill="freeze" dur="0.01s"></animateTransform>
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze"></set>
</rect>
<rect id="project-10-inactivator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<animateTransform id="inactivate_project_10" begin="click" fill="freeze" dur="0.01s"></animateTransform>
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 0" to="33.140625 10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
</text>
</svg>
I want that to work as many times as you may want, but it only works once; afterwards the rotation start point for the first click is for some reason shifted by -90 deg, as you'll notice from upon the 3rd click. Any ideas?
UPDATE
I noticed the following, if that may help to solve the problem (still unable to solve it): Try out the following with the snippet above:
A) Click on the rectangle once
B) Click on the rectangle again, to get the label back to its original position
C) Before clicking on the rectangle for the third time, copy the four animateTransform tags inside the text tag into a js variable let's say yourSavedAnimateTransformString, then delete them from the markup, e.g. via
document.getElementsByClassName("timeline-project-label")[0].innerHTML =
document.getElementsByClassName("timeline-project-label")[0]
.childNodes[0].outerHTML +
document.getElementsByClassName("timeline-project-label")[0]
.childNodes[1].outerHTML;
, then reinsert them at the exact same place with js, e.g. via
document.getElementsByClassName("timeline-project-label")[0].innerHTML +=
yourSavedAnimateTransformString
Then, click on the rectangle a third and a fourth time, and you'll see that it will work for the third and fourth time without refreshing the page, but fail again for subsequent clicks, unless you repeat this delete-re-insert procedure on every 2nd click on the rectangle, which is a rather hacky not-solution to me.
I supposed that this info may be useful to solve my problem, as it indicates that my problem's somehow related to an unaccessible tracked state of the present animateTransform tags, which can be eliminated by renewing these tags on every 2nd click.
As this is not a real solution, I'd still really like to understand what's going on here..?
UPDATE 2
How come that the snippet above actually does not ainmate the transforms AT ALL in Safari?? According to the specs, animateTransform is supported for all except IE... (for which I'll use Fakesmile when done..)?
I've only noticed it now; you may check my problem in FF and Chrome, where the snippet behaves as described.
Doing it programmatically via document.getElementById("activate_project_10").beginElement() does actually work, but is this really necessary? Which is the standard approach for svg animatransforms in safari?
Okay, found a solution which works in FF and Chrome. The principal thought was to overwrite, after finishing the last animation of inactivate_project_10 animation, the state of the transform property with the initial value, before triggering the first one of the activate_project_10 animation. All this while thus using replace instead of sum as the value of additive for the last resetting animation, while using accumulate=sum to assure that the accumulated (thus actually the resetted) value is taken for the reset.
And this actually worked:
<svg version="1.1" baseProfile="full" viewBox="0 0 1000 200" xmlns="http://www.w3.org/2000/svg" id="timeline-container">
<rect id="project-10-activator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="block">
<animateTransform id="activate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="inactivate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="activate_project_10.end" fill="freeze"></set>
</rect>
<rect id="project-10-inactivator" class="" stroke="black" stroke-width="2" fill="white" width="20" height="20" x="11" y="142.2" transform="translate(-10,-10)" data-project-id="10" display="none">
<animateTransform id="inactivate_project_10" begin="click" fill="freeze" dur="0.5s"></animateTransform>
<set attributeName="display" to="block" begin="activate_project_10.end" fill="freeze"></set>
<set attributeName="display" to="none" begin="inactivate_project_10.end" fill="freeze"></set>
</rect>
<text data-project-id="10" x="17" y="121.2" transform="rotate(-90,17,121.2)" class="timeline-project-label label-above-project-point">
<tspan>Upper Title</tspan>
<tspan class="project-name-span" x="17" dy="15">lower title</tspan>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 16.609375 139.7156219482422" to="90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="activate_project_10.begin" from="0 0" to="-33.140625 -10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="translate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 0" to="33.140625 10" additive="sum" fill="freeze"></animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" dur="0.5s" repeatCount="1" begin="inactivate_project_10.begin" from="0 16.609375 139.7156219482422" to="-90 16.609375 139.7156219482422" additive="sum" fill="freeze">
</animateTransform>
<animateTransform attributeName="transform" attributeType="XML" type="rotate" repeatCount="1" dur="0.01s" from="-90 17 121.2" to="-90 17 121.2" fill="freeze" additive="replace" accumulate="sum" begin="inactivate_project_10.end"></animateTransform>
</text>
</svg>
The main modifications were:
changed the dur in the two main animateTransforms (inactivate_project_10 and activate_project_10) to the same time as the combined translation + rotation animations of 0.5s.
added the last animateTransform tag to reset the transform state to the initial state to be able to toggle the animation in an endless loop of clicking. Use a particularly short duration (0.01s used) to reset as fast as possible when finishing a toggle cycle, to quickly be ready for the next one, if triggered again.
Yet, I'd still like to know why this is not working AT ALL in Safari..? Even if you use beginElement(), that only works for the first two toggles, and then stops working..

Animate SVG with animateTransform

Trying to animate an SVG element with the skewX. It works, however, not exactly the way I want it to.
Now: the bottom part moves to the left
Goal: the upper part should move to the right instead (and bottom stays in place)
I tried with transform-origin but it didn't work. Any ideas how to solve this mystery?
<svg xmlns="http://www.w3.org/2000/svg" width="102" height="102" viewBox="-50 -50 102 102">
<g>
<rect width="10%" height="50%"
style="fill:none; stroke:red; stroke-with:3;">
<animateTransform
attributeName="transform"
attributeType="XML"
type="skewX"
from="0"
to="-20"
begin="0.5s"
dur="0.2s"
repeatCount="1"
fill="freeze"
id="fallen"/>
</rect>
</g>
</svg>
Use another transform to move the whole thing to the right at the same time as the bottom moves left.
<svg xmlns="http://www.w3.org/2000/svg" width="102" height="102" viewBox="-50 -50 102 102">
<g>
<rect width="10%" height="50%"
style="fill:none; stroke:red; stroke-with:3;">
<animateTransform
attributeName="transform"
attributeType="XML"
type="skewX"
from="0"
to="-20"
begin="0.5s"
dur="0.2s"
repeatCount="1"
fill="freeze"
id="fallen"/>
<animateTransform
attributeName="transform"
attributeType="XML"
type="translate"
from="0"
to="20"
begin="0.5s"
dur="0.2s"
repeatCount="1"
fill="freeze"
additive="sum"/>
</rect>
</g>
</svg>

Animate SVG circle from small to large and back to small

Without using css and js, I would like to animate this svg. I would like for the circles to go from small to large and then back to small. I've gotten the animation to work for small to large but now I can't seem to figure out how to get them to return to their original size.
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="6" cy="8" r="1" style="fill:steelblue;">
<animate attributeType="XML" attributeName="r" from="1" to="6"
dur="1s" begin=".25s" repeatCount="indefinite" />
</circle>
<circle cx="18" cy="8" r="1" style="fill:red;">
<animate attributeType="XML" attributeName="r" from="1" to="6"
dur="1s" begin=".5s" repeatCount="indefinite" />
</circle>
<circle cx="30" cy="8" r="1" style="fill:orange;">
<animate attributeType="XML" attributeName="r" from="1" to="6"
dur="1s" begin=".75s" repeatCount="indefinite" />
</circle>
<circle cx="42" cy="8" r="1" style="fill:green;">
<animate attributeType="XML" attributeName="r" from="1" to="6"
dur="1s" begin="1s" repeatCount="indefinite" />
</circle>
</svg>
Focusing on the 1st circle, I'd like to go from r="1" to r="6" and then back to r="1". This should happen within dur="1s".
Is this possible? If so how? Again, without using external JS or CSS.
Thanks!
Instead of from and to, use values to list a series of values that it should animate between.
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="6" cy="8" r="1" style="fill:steelblue;">
<animate attributeType="XML" attributeName="r" values="1;6;1"
dur="1s" begin="0.25s" repeatCount="indefinite" />
</circle>
<circle cx="18" cy="8" r="1" style="fill:red;">
<animate attributeType="XML" attributeName="r" values="1;6;1"
dur="1s" begin="0.5s" repeatCount="indefinite" />
</circle>
<circle cx="30" cy="8" r="1" style="fill:orange;">
<animate attributeType="XML" attributeName="r" values="1;6;1"
dur="1s" begin="0.75s" repeatCount="indefinite" />
</circle>
<circle cx="42" cy="8" r="1" style="fill:green;">
<animate attributeType="XML" attributeName="r" values="1;6;1"
dur="1s" begin="1s" repeatCount="indefinite" />
</circle>
</svg>

svg animate begin on previous using prev.end

I wanted to animate some paths one after another automatically using animate's begin attribute:
<svg
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="500"
height="500"
viewBox="0 0 20 20">
<path d="M10,10 m0,-5 a5,5 0 0,1 5,5 a5,5 0 0,1 -5,5 a5,5 0 0,1 -5,-5 a5,5 0 0,1 5,-5 z" fill="green">
<animate attributeName="fill" from="green" to="white" begin="0s" dur="1s" fill="freeze" />
<animate attributeName="fill" from="white" to="blue" begin="prev.end" dur="1s" fill="freeze" />
</path>
</svg>
But it seems that the prev.end on the second animation is not working. When I rewrite the animations as below and refer to the first one by ID, it does work.
<animate id="first"
attributeName="fill"
from="green"
to="white"
begin="0s"
dur="1s"
fill="freeze" />
<animate
attributeName="fill"
from="white"
to="blue"
begin="first.end"
dur="1s"
fill="freeze" />
The reason I would like to use prev.end to sync my animations, is because I am generating these animations automatically in JavaScript. Number and order of animations are variable, which makes the use of IDs more difficult for me.

Resources