svg animation path direction - svg

I'm using svg animation tags to animate a group tag along the coordinates of a path tag. Unfortunately, the animation is running in the opposite direction to what I require (I.E going from b to a instead of a to b). Does there exist any attribute which would amend this, something like:
<animateMotion
xlink:href="#group1"
dur="6s"
fill="freeze"
rotate="auto-reverse"
direction="reverse"
>
<mpath xlink:href="#path1" />
</animateMotion>
I know this could be achieved with snap or raphael but as far as I know it's not possible to use anything to the effect of 'rotate="auto-reverse"' in those libraries.
Alternatively, is there a way to reverse the way my path is calculated; can this be achieved with any software?

You could use the keyPoints attribute, along with keyTimes.
<?xml version="1.0"?>
<svg width="120" height="120" viewBox="0 0 120 120"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<path d="M10,110 A120,120 -45 0,1 110 10 A120,120 -45 0,1 10,110"
stroke="lightgrey" stroke-width="2"
fill="none" id="theMotionPath"/>
<!-- Here is a green circle which will be moved along the motion path. -->
<circle cx="" cy="" r="5" fill="green">
<!-- Define the motion path animation -->
<animateMotion dur="6s" repeatCount="indefinite" keyPoints="0;1" calcMode="linear"
keyTimes="0;1">
<mpath xlink:href="#theMotionPath"/>
</animateMotion>
</circle>
<!-- Here is a red one, using the same motionPath but reversed thanks to keyPoints -->
<circle cx="" cy="" r="5" fill="red">
<animateMotion dur="6s" repeatCount="indefinite" keyPoints="1;0" calcMode="linear"
keyTimes="0;1">
<mpath xlink:href="#theMotionPath"/>
</animateMotion>
</circle>
</svg>

Related

Svg alternate animateMotion

I want to have repeating alternate direction for the animation
<animateMotion keyPoints="0;1;0" keyTimes="0;0.5;1" dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath href="#path1"/>
</animateMotion>
Keypoints and KeyTimes are not working
Full code:
<svg width="200" height="200" viewBox="0 0 700 700">
<g>
<path id="path1" d="M200,350 C 200,440 400,150 400,250 M200,350"
fill="none" stroke="blue" stroke-width="7.06" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z"
fill="yellow" stroke="red" stroke-width="7.06" />
<animateMotion keyPoints="0;1;0" keyTimes="0;0.5;1" dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath href="#path1"/>
</animateMotion>
</g>
</svg>
First there is an issue with your code. You are animating a group of shapes and you are using one of those shapes as mpath.
In the next examples I'm animating the triangle over the integral like shape. In order to animate the triangle in both ways I'm rewriting the mpath so that the path will reverse to the starting point.
svg{width:90vh}
<svg viewBox="0 0 700 700">
<path id="path1" d="M200,350 C 200,440 400,150 400,250 C400,150 200,440 200,350" fill="none" stroke="blue" stroke-width="7.06" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06" >
<animateMotion keyPoints="0;1;0" keyTimes="0;0.5;1" dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath href="#path1"/>
</animateMotion>
</path>
</svg>
However if you want the triangle to stay the same side of the curve when reversing, in this case I'm using 2 animations, each one begining when the previous one ends. For the second animation I'm using rotate="auto-reverse"
svg{width:90vh}
<svg viewBox="0 0 700 700">
<path id="path1" d="M200,350 C 200,440 400,150 400,250" fill="none" stroke="blue" stroke-width="7.06" />
<path id="path2" d="M400,250 C400,150 200,440 200,350" fill="none" stroke="blue" stroke-width="7.06" />
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z" fill="yellow" stroke="red" stroke-width="7.06">
<animateMotion id="a1" dur="3s" rotate="auto" begin="0;a2.end">
<mpath href="#path1" />
</animateMotion>
<animateMotion id="a2" dur="3s" rotate="auto-reverse" begin="a1.end">
<mpath href="#path2" />
</animateMotion>
</path>
</svg>
Please observe that the path for the second animation is the path for the first animation reversed.

SVG circle move(animateMotion) under the path

I have to write a code that circles should go under some paths with below SVG
<g>
<g>
<path class="st0" d="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13"/>
</g>
<g>
<path class="st0" d="M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13"/>
</g>
</g>
<circle r="20" fill="blue">
<animateMotion dur="5s" repeatCount="indefinite"
path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13" />
https://codepen.io/lzwdct/pen/poRYVXZ
Imagine the paths are like driveway, and the circle passes under the path(like bridge) it should not appear under the bridge.
Is there any way to implement it?
The way SVG mask works is a bit strange. The element it's applied to will only be rendered where the mask is white and where the mask is black (or just not white) it will be hidden. Another strange effect of SVG masks is that if you are animating an element and apply a mask to the element being animated then the mask will move with the element.
To account for the first part is simple, just add a white rect the size of the SVG itself inside the mask and use smaller black shapes to mask. The way to work around the moving mask is to apply the mask not to the element being animated but to a <g> tag that wraps the element(s) being animated.
If you want the circles to go 'under' a section and then 'over' that same section however, then you'll need to do some animating inside the mask as well. In this example I'm using animateTransform inside the mask's rect child (the black part that does the masking) to shrink it after the circles pass 'under' the bridge, you could just as easily use CSS keyframes though.
I suggest strongly that you also cut down the viewbox since your visual elements are so small compared to the available space, in the example I just estimated but the best way is to re-render your graphics in Illustrator and crop the artboard better to your objects.
Also most of the additional markup produced by Illustrator is not needed if the SVG will be inline in HTML. You can lose pretty much everything except the viewBox as shown in my example since those other attributes are mostly only used when the SVG is rendered as an image, hope this helps.
svg {
max-width: 500px;
}
.st0,
.st1 {
fill: none;
stroke: #8ea5ae;
stroke-width: 50;
stroke-miterlimit: 10;
}
.st1 {
stroke-linecap: round
}
.st2 {
fill: none;
stroke: #758992;
stroke-width: 50;
stroke-miterlimit: 10;
}
<svg viewBox="0 0 1015 855">
<mask id="myMask">
<!-- Pixels under white are rendered -->
<rect x="0" y="0" width="1015" height="855" fill="white" />
<!-- Pixels under black are hidden -->
<rect class="moveme" x="315" y="335" height="150" width="150" transform="rotate(45 395 395)">
<animateTransform attributeName="transform"
attributeType="XML"
type="scale"
keyTimes="0; 0.25999; 0.26; 1"
values="1; 1; 0; 0"
dur="5s"
additive="sum"
repeatCount="indefinite"/>
</rect>
</mask>
<path class="st0" d="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13" />
<path class="st1" d="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07
c29.29-29.29,76.78-29.29,106.07,0" />
<path class="st2" d="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
s179.15-68.34,247.49,0" />
<path class="st0" d="M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91 c-48.89-48.89-128.09-48.95-176.91-0.13" />
<path class="st2" d="M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07 s-76.78-29.29-106.07,0" />
<path class="st1" d="M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49 s-179.15-68.34-247.49,0" />
<!-- Group the circles and apply the mask to the group, not the circles -->
<g mask="url(#myMask)">
<circle r="20" fill="blue">
<animateMotion dur="5s" repeatCount="indefinite" path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13" />
</circle>
<circle r="20" fill="blue">
<animateMotion dur="5s" repeatCount="indefinite" path="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
s179.15-68.34,247.49,0 M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07
s-76.78-29.29-106.07,0" />
</circle>
<circle r="20" fill="blue">
<animateMotion dur="5s" repeatCount="indefinite" path="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07
c29.29-29.29,76.78-29.29,106.07,0 M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49
s-179.15-68.34-247.49,0" />
</circle>
</g>
<!-- uncomment the rect below to visualize the animation applied to the mask -->
<!-- <rect x="315" y="335" height="150" width="150" fill="#f00" opacity=".1" transform="rotate(45 395 395)">
<animateTransform attributeName="transform"
attributeType="XML"
type="scale"
keyTimes="0; 0.25999; 0.26; 1"
values="1; 1; 0; 0"
dur="5s"
additive="sum"
repeatCount="indefinite"/>
</rect>-->
</svg>

Can i create a circle that follow an existing line in svg?

As the title suggests, i'm trying to create an animation in svg with a point/circle that follows an irregular path. I am using the animateTransform, for example:
<animateTransform attributeName="transform"
attributeType="XML"
type="translate"
from="0 60 70"
to="360 60 70"
dur="10s"
repeatCount="definite"/>
Can i implement this method (in svg) to let the circle to follow the path, or i have to use necessarily javascript?
If i can do it in svg could you give me a basic example with an explanation?
You can use the <animateMotion> element.
Example adapted from MDN:
<svg viewBox="0 0 200 100" xmlns="http://www.w3.org/2000/svg">
<path id="path" fill="none" stroke="lightgrey"
d="M20,50 C20,-50 180,150 180,50 C180-50 20,150 20,50 z" />
<circle r="5" fill="red">
<animateMotion dur="10s" repeatCount="indefinite">
<mpath xlink:href="#path"/>
</animateMotion>
</circle>
</svg>

SVG: animateMotion along animated path

When I use animateMotion along an animated path, Firefox (26) follow the original path while Opera (17) and Chrome (32) follow the changing path. For example, in the following svg the red rectangle ends at position of 100,10 in FF while at 50,10 in other browsers:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 100 100">
<path id="p" stroke="black" stroke-width="1" d="M 0,10 100,10"/>
<rect id="r" x="-5" y="-5" width="10" height="10" fill ="red"/>
<animate xlink:href="#p" attributeName="d" to="M 0,10 50,10" dur="5s" fill="freeze" repeatCount="1"/>
<animateMotion xlink:href="#r" dur="5s" fill="freeze" repeatCount="1">
<mpath xlink:href="#p"/>
</animateMotion>
</svg>
What is the correct behavior according to the SVG spec?
The animated path should be used, there's an open Firefox bug on that.

how to repeat infinitely the whole svg

I mean after my SVG stops completing the animation I want the animation to start over again and end and then again start over and so on.
I tried:
<svg>
<animate repeatCount="indefinite"/>
</svg>
But it doesn't work.
See example animMotion01 in the w3 SVG spec for a fairly reduced example illustrating SVG animation (including use of repeatCount="indefinite"):
<svg width="5cm" height="3cm" viewBox="0 0 500 300"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink" >
<desc>Example animMotion01 - demonstrate motion animation computations</desc>
<rect x="1" y="1" width="498" height="298"
fill="none" stroke="blue" stroke-width="2" />
<!-- Draw the outline of the motion path in blue, along
with three small circles at the start, middle and end. -->
<path id="path1" d="M100,250 C 100,50 400,50 400,250"
fill="none" stroke="blue" stroke-width="7.06" />
<circle cx="100" cy="250" r="17.64" fill="blue" />
<circle cx="250" cy="100" r="17.64" fill="blue" />
<circle cx="400" cy="250" r="17.64" fill="blue" />
<!-- Here is a triangle which will be moved about the motion path.
It is defined with an upright orientation with the base of
the triangle centered horizontally just above the origin. -->
<path d="M-25,-12.5 L25,-12.5 L 0,-87.5 z"
fill="yellow" stroke="red" stroke-width="7.06" >
<!-- Define the motion path animation -->
<animateMotion dur="6s" repeatCount="indefinite" rotate="auto" >
<mpath xlink:href="#path1"/>
</animateMotion>
</path>
</svg>

Resources