This is probably really simple but I am starting to learn svg and am confused by the behavior of the following code:
<svg>
<defs>
<path id="thepath" fill="none" stroke="#000000" d="M25,0 L200,200" />
</defs>
<rect x="25" y="0" width="50" height="100" fill="slategrey">
<animateTransform id="one"
attributeType="xml"
attributeName="transform"
type="rotate"
from="0 50 50"
to="360 50 50"
dur="1s"
repeatCount="indefinite"
end ="onemove.end"/>
<animateMotion id="onemove" dur="3s">
<mpath xlink:href="#thepath"/>
</animateMotion>
</rect>
What I am expecting to happen is the rectangle rotate in a circle on a center point. Which it does.
I expect it to also travel down the path. Which it does.
I expect it to stop rotating once it is down the path. Which I think it does.
I expect it to stay at the end of the path. Which it does not.
It resets to the start point and has stopped rotation. So I am not sure if the reset stopped the rotation or the actual end statement stopped rotation.
So my question is two fold: why does it reset and how do I prevent that.
Also, any links to good svg tutorials would be appreciated. While I am finding a lot tutorials, I think I am not finding quality because I have a feeling this is a very simple issue I should already know from my research.
I think I need something in the path to prevent the reset but I have no idea what.
Thanks in advance.
You need to add fill="freeze" to the <animateMotion> so it will freeze the effect at the end. See: SVG - Chapter 19 Animation, Timing Attributes:
<animateMotion id="onemove" dur="3s" fill="freeze">
<mpath xlink:href="#thepath"/>
</animateMotion>
See it working here: JSFiddle
There is a W3C SVG Tutorial written in SVG. A very good community-maintained SVG Tutorial at MDN and the SVG Specification itself which is very readable and has many examples. It's the best reference, but you should also try out everything in different browsers using CodePen or JSFiddle.
Related
<g id="Closed_Eyes">
<path d="Closed eye data" />
</g>
<g id="Open_Eyes">
<animate dur="0" attributeName="opacity" from="1" to="0" repeatCount="indefinite" />
<path d="Open eye data" />
</g>
I have an SVG face and like to animate blinking eyes. The animate does not work because the duration is zero, but if I change zero to some time, it is animate opacity. I should not be using opacity but I must use hiding on the open_Eyes object. The idea is that if we hide open_Eyes, the background close_Eyes shows and then shows. This will give if eyes are blinking. Kindly guide me on how we can animate blinking with animate.
I tried with opacity, but it changes the opacity with time. That is wrong. Perhaps I need two animations. First, hide the open_Eyes object and then show it.
Using dur="0" in animate won't work. If you just want to toggle the object you could either use a really small duration value (wouldn't recommend it though) or use the set tag like this:
<animate dur="0.001s" attributeName="opacity" from="1" to="0" repeatCount="indefinite" />
or this
<set attributeName="visibility" to="hidden" fill="freeze" />
You also dont need the repeatCount if you just want it to stay invisible or when using no duration. Use fill="freeze" instead, as seen in the second code example i made, to keep the state after the animation finished.
I'm new to the svg library (HTML5 svg tag and related) and trying to learn. I'm working on a little diagram editor in VueJS using svg. I know how to create a rectangle and even a path from one rectangle/circle/etc to another, but I'm not unclear how to approach creating a path that starts and ends at the same rectangle (i.e., a loop) - something like this
I don't care that much where the start and end points intersect the rectangle, though I'd prefer they were relatively close to one another or at least on the same edge of the rectangle.
Thanks for any nudges in the right direction.
Just create a <path> that consists of a bezier curve whose control points form a rectangle.
<svg viewBox="0 0 100 100">
<rect x="50" y="10" width="50" height="40" fill="#4472c4"/>
<path d="M 50,20 C 10,20 10,40, 50,40" fill="none" stroke="red"/>
<!-- Show grey lines to indicate the bezier control points -->
<line x1="50" y1="20" x2="10" y2="20" fill="none" stroke="lightgrey" stroke-width="0.5"/>
<line x1="50" y1="40" x2="10" y2="40" fill="none" stroke="lightgrey" stroke-width="0.5"/>
</svg>
I want to create an SVG that has the animation attributes that can continue the animation on mouse over.
On mouse out, I want the animation to continue to its end of duration before ending.
I am unable to achieve this as my animation always ends abruptly.
<svg viewBox="0 0 300 100" xmlns="http://www.w3.org/2000/svg">
<!-- Simple color fill -->
<circle cx="50" cy="50" r="40" fill="teal" >
<animate attributeName="fill" values="teal;cyan;teal;" dur="1s" calcMode="paced" repeatCount="indefinite" begin="mouseover" end="mouseout" />
</circle>
</svg>
Understand that we can achieve a slightly seamless feel by adding the fill="freeze" attribute.
However it brings back the issue of the colour not being the same as from where it left off.
Any idea how we can create a smooth animation on mouse over just by using svg attributes?
I hope to not use Javascript.
When attempting to combine an attribute animation and a transformation animation in SVG, I end up with two different end results in Chromium (78.0.3904.97) and Firefox (70.0.1), both on Linux:
Chromium:
Firefox:
The former behaviour is what I expect, since both animations are supposed to be applied. The radius animation must be placed within the element it's applied on, and the animateTransform element inside any element.
Furthermore, Firefox applies the radius animation if the transformation animation is removed.
Why am I not getting the expected behaviour across browsers? This level of SMIL is supposed to be supported by both.
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="480" height="480" viewBox="0 0 480 480" >
<circle cx="200" cy="200" r="150" stroke="black" fill="none"/>
<g>
<circle cx="200" cy="200" r="150" stroke="red" fill="none">
<animate
attributeName="r"
attributeType="XML"
values="150;200"
begin="0s"
dur="2s"
fill="freeze"
repeatCount="1"/>
</circle>
<animateTransform
attributeName="transform"
attributeType="XML"
type="translate"
values="0 0;40 30"
begin="0s"
dur="2s"
fill="freeze"
repeatCount="1"/>
</g>
</svg>
Solved.
It's a valid way to stack animations, and the Chromium rendering is the correct one.
The incomplete rendering in Firefox is due to a regression on the v70 branch: https://bugzilla.mozilla.org/show_bug.cgi?id=1592546
I am trying out some animations and transformations in an SVG image.
I am trying to translate and resize and translate a path as well as animate the rotation of it.
It appears I can only translate and resize or rotate at a time. If I try them all together then the translate and resize do not hold: if I remove the animation then they are moved and the right size.
This behavior is consistent across Linux and OSX as well as FF and Safari.
Example:
<use
id="tengear"
fill="#ffffff"
stroke="#E2E2E2"
stroke-width="3"
transform="scale(0.40) translate(62, 180)"
style="filter:url(#distanceBlurFar)"
xlink:href="#tengearuse"
>
<animateTransform
attributeType="XML"
attributeName="transform"
type="rotate"
from="0,162,280" to="360,162,280"
begin="0s" dur="11"
repeatCount="indefinite"
/>
</use>
This should be small and moved as well as rotating. However it is big and not moved but is rotating.
<use
id="tengear"
fill="#ffffff"
stroke="#E2E2E2"
stroke-width="3"
transform="scale(0.40) translate(62, 180)"
style="filter:url(#distanceBlurFar)"
xlink:href="#tengearuse">
</use>
This one is moved and rotated but not rotating.
Can someone help me out on how to get this working?
*you will need to assume that the use and other references are valid
Full source here
It turns out that it was a RTFM problem.
Go to the spec and read about additive="sum" and additive="replace"
Now it reads like:
<use id="tengear" fill="#ffffff" stroke="#E2E2E2" stroke-width="2.5" transform="scale(0.25) translate(390, 360)" style="filter:url(#distanceBlurClose)" xlink:href="#tengearuse">
<animateTransform
attributeType="XML"
attributeName="transform"
type="rotate"
from="0,390,360" to="360,390,360"
begin="0s" dur="11"
repeatCount="indefinite"
additive="sum"
/>
</use>
It is unclear what you are trying to do and it would help if you cut your example to a size where you could post it here. It sounds as if you should use animateTransform and animateMotion. I often start by finding an example which already works and then gradually modifying it to include my own requirements. And always only use as little functionality as possible
See http://www.w3schools.com/svg/el_animatetransform.asp