How can I animate a <path> object in SVG - svg

<g id = "doc">
/*Doc*/
<path d = "M 100 100 L 150 100 L 170 120 L 170 190 L 100 190 L 100 100 Z M 150 100 L 150 120
L 170 120 M 120 140 L 150 140 M 120 160 L 150 160" stroke = "black" stroke-width = "8px" fill = "white" transform = "translate(350, 110)">
</path>
</g>
<animate xlink:href = "#doc" attributeName = "x" from = "450" to = "1000" dur = "4" repeatCount = "indefinite" />
If I try to animate the with the id = "doc", which is located inside a tag, the animation is not working. Thanks for help!

Your SVG was a bloated file icon:
The only animation I can think of is:
<svg viewBox="0 0 90 110" style="background:pink;height:180px">
<path d="m10 10 50 0 20 20 0 70-70 0 0-90zm50 0 0 20 20 0m-50 20 30 0m-30 20 30 0"
stroke="black" stroke-width="8px" fill="white">
<animatemotion path="m0 0h100" dur="4s" repeatCount="indefinite"/>
</path>
</svg>
Update - animationMotion doesn't work in Chrome IMG and OBJECT tags
animationMotion does work inside an IMG tag in FireFox
To make it work in Chrome, change it to an animateTransform animation
Since my favorite pastime on a lazy Sunday is to clean SVGs, here is your code:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1320 520" style="background:pink" fill="black" stroke="black">
<g id="deviceleft">
<rect x="355" y="80" width="12" height="85" rx="5" />
<rect x="355" y="185" width="12" height="40" rx="5" />
<rect x="10" y="10" width="350" height="500" stroke-width="5" rx="10" fill="lightblue" />
<circle cx="335" cy="35" r="8" fill="grey" stroke-width="7" />
</g>
<g id="deviceright">
<rect x="1305" y="110" width="12" height="85" rx="5" />
<rect x="1305" y="210" width="12" height="40" rx="5" />
<rect x="1010" y="60" width="300" height="400" fill="grey" stroke-width="5" rx="10" />
<rect x="1105" y="60" width="110" height="25" rx="10" />
<circle cx="1185" cy="72" r="6" stroke="grey" stroke-width="4" />
<rect x="1135" y="68" width="35" height="8" fill="darkgrey" rx="5" />
</g>
<g transform="translate(0 175)">
<path d="m435 60 500 0m-1 0-19-10m19 10-19 10" stroke-width="6" />
<path d="m385 20 50 0 20 20 0 70-70 0 0-90zm50 0 0 20 20 0m-50 20 30 0m-30 20 30 0" stroke-width="8"
fill="white">
<animateTransform attributeName="transform" type="translate" dur="4s" values="50 0;450 0"
repeatCount="indefinite" />
</path>
</g>
</svg>

Related

SVG pathLength on circle not defining circle's circumference?

According to https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle, the pathLength attribute is supposed to define the "total length for the circle's circumference", however, when I use stroke-dasharray, it doesn't seem to line up?
<svg width="100" height="100" viewBox="0 0 1 1">
<circle
cx="0.5"
cy="0.5"
stroke-width="0.5"
r="0.25"
pathLength="360"
stroke-dasharray="180 360"
stroke-dashoffset="0"
stroke="black"
fill="none"
/>
</svg>
According to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/pathLength as well, this should be half-filled, thus a semi-circle, however it's slightly less than a semi-circle. If I have stroke-dasharray set to 360 360 instead, it doesn't fully close when, if I understand how the pathLength attribute is supposed to work, it should.
Am I misunderstanding pathLength or stroke-dasharray?
Edit: it seems to work differently across browsers...?
Chromium:
Firefox:
Safari:
Edit 2:
When I get their total lengths, it's different across browsers! Is this intended? Is it possible to solve this issue?
As #enxaneta commented. The smaller the viewBox, the bigger the problem is. In this example it is only the last one (viewBox="0 0 100 100") that looks OK in Chrome.
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 1 1">
<path d="M0 .5 L1 .5" stroke-width=".01" stroke="gray"/>
<circle cx=".5" cy=".5" r=".4" stroke="black" stroke-width=".2" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 10 10">
<path d="M0 5 L10 5" stroke-width=".1" stroke="gray"/>
<circle cx="5" cy="5" r="4" stroke="black" stroke-width="2" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 50 50">
<path d="M0 25 L50 25" stroke-width=".5" stroke="gray"/>
<circle cx="25" cy="25" r="20" stroke="black" stroke-width="10" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 100 100">
<path d="M0 50 L100 50" stroke-width="1" stroke="gray"/>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="20" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>

svg: can anyone help me to draw an arc?

I'm trying to draw an arc with SVG but I'm stucked.
The goal is to get a figure like this:
what I get instead is this:
Those are the SVG tags I'm playing with:
<svg width='500' height='500' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' >
<g style='transform-origin:center;'>
<path d="M 100 50
a 50,50 0 0 0 100,0" stroke="black" fill="red" stroke-width="2" />
</g>
</svg>
Can anybody help me to understan what's wrong on my node?
<svg width='500' height='500' xmlns='http://www.w3.org/2000/svg' version='1.1' xmlns:xlink='http://www.w3.org/1999/xlink' >
<g style='transform-origin:center;'>
<!--
<path d="M 100 50
a 50,50 0 0 0 100,0" stroke="black" fill="red" stroke-width="2" />
-->
<path d="M 50 50
a 50,50 270 1 0 25,15" stroke="black" fill="red" stroke-width="2" />
<path d="M 150 150
a 50,50 270 0 0 125,115" stroke="black" fill="red" stroke-width="2" />
</g>
</svg>
your problem is the large-arc-flag, set it to 1
MDN Reference

Is possible center <g> in <svg>?

I searched on the web and I do not found a solution for my problem, is possible to do that, center my element depending of size of my parent content.
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18c0-9.94-8.06-18-18-18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>
I would put the loader in a symbol. Also I would give the loader and the svg element a viewBox attribute.
svg{border:1px solid;}
<svg width="100%" viewBox="-250 -50 500 100" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<symbol id="the_symbol" viewBox="-2 -2 40 40">
<g stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18A18,18 0 0 0 0,18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</symbol>
<use xlink:href="#the_symbol" x="-20" y="-20" width="36" height="36" fill="none" />
</svg>
UPDATE
The OP is commenting that they want the root svg to take various sizes, while the loader has to be always the same size.
//the size and position of the symbol
let o = {x:36,y:18}
function init(){
let p = getsize(o);
//reset the size and position of the use element
theUse.setAttributeNS(null,"width",p.x)
theUse.setAttributeNS(null,"height",p.x)
theUse.setAttributeNS(null,"x",250-p.y)
theUse.setAttributeNS(null,"y",50-p.y)
}
// a function to calculate the size and position of the use element
function getsize(o){
var p = svg.createSVGPoint();
p.x= o.x;
p.y= o.y;
p = p.matrixTransform(svg.getScreenCTM().inverse());
return p
}
setTimeout(function() {
init();
addEventListener('resize', init, false);
}, 15);
svg{border:1px solid;}
symbol{overflow:visible}
<svg id="svg" width="100%" height="100%" viewBox="0 0 500 100" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<symbol id="the_symbol" viewBox="0 0 36 36">
<g stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18A18,18 0 0 0 0,18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</symbol>
<use id="theUse" xlink:href="#the_symbol" fill="none" />
</svg>

How to start svg pattern from begin for two elements separately and how to setup right coordinate system?

I have two thick lines and I want to apply pattern for this lines. Lines should have the same pattern, but start of drawing pattern should start from (0, 0) for each line separately. In my experiment http://jsfiddle.net/69t09wey/ patterns apply like mask. I.e pattern apply for whole svg canvas as invisible layer and where line is visible, pattern also visible.
<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern-1" width="20" height="20" x="0" y="0" patternUnits = "userSpaceOnUse" >
<path d="M 0 0 L 20 20" fill="none" stroke="#0000ff" stroke-width="1"></path>
</pattern>
<g transform="scale(5)">
<rect x="1" y="1" width="1000" height="1000"
fill="none" stroke="blue" />
<path d="M 1 9 L 200 9"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
<path d="M 1 53 L 200 53"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
</g>
</svg>
If you make your lines the same. Then move the second one by applying a transform. That will shift the coordinate space of the pattern.
<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern-1" width="20" height="20" x="0" y="0" patternUnits = "userSpaceOnUse" >
<path d="M 0 0 L 20 20" fill="none" stroke="#0000ff" stroke-width="1"></path>
</pattern>
<g transform="scale(5)">
<rect x="1" y="1" width="1000" height="1000"
fill="none" stroke="none" />
<path d="M 1 9 L 200 9"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
<path d="M 1 9 L 200 9" transform="translate(0,44)"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
</g>
</svg>

SVG Animation rotate

I've got a very annoying Problem using rotations in my SVG Animation. The problem is: I have an object, which I want to move along a specific path. So far it works well. But if I try to rotate this object at the end of the path it doesn't work. Sometimes my Object disappears because it's outside the viewbox and I have to try many values for the x and y values of the rotate statement until it works. And then it only works if I set the duration to 0.001s so it rotates instant, because actually my object switches to a much higher point in the viewbox and begins to rotate and only the final position is right but you see it rotating down or up around any point so it doesn't really work. I have no idea how to get the x and y values which I need to rotate the object around its own axis. Here is the code example, I hope you know how to solve this problem:
<defs>
<g id="Karte" visibility="hidden">
<!--Karte-->
<rect x="0" y="0" width="980" height="550" style="stroke: none; fill: rgb(189,248,137)" />
<!--Straßen-->
<path id="Straße1" d="M 510 0 L 510 120 0 120 0 150 980 150 980 120 540 120 540 0" style="stroke: none; fill: lightgrey" />
<rect id="Straße2" x="0" y ="320" width="980" height="20" style="stroke:none; fill: lightgrey" />
<rect id="Straße3" x="0" y="500" width="980" height="30" style="stroke:none; fill: lightgrey" />
<rect id="Straße4" x="25" y="340" width="30" height="160" style="stroke:none; fill: lightgrey" />
<rect id="Straße5" x="930" y="340" width="30" height="160" style="stroke:none; fill: lightgrey" />
<path id="campus" d="M 515 150 L 515 170 510 170 510 300 525 300 525 320 650 320 650 300 665 300 665 170 545 170 545 150" style="stroke:none; fill: lightgrey" />
<polyline id="rampe1" points="570,300 570,307 635,317 635,320" style="stroke-width: 1; fill:none" />
<polyline id="rampe2" points="580,300 580,303 645,313 645,320" style="stroke-width: 1; fill:none" />
<g id="Treppe1">
<line x1="515" y1="153" x2="545" y2="153" stroke-width="0.5" />
<line x1="515" y1="157" x2="545" y2="157" stroke-width="0.5" />
<line x1="515" y1="161" x2="545" y2="161" stroke-width="0.5" />
<line x1="515" y1="165" x2="545" y2="165" stroke-width="0.5" />
</g>
<g id="Treppe2">
<line x1="525" y1="303" x2="565" y2="303" stroke-width="0.5" />
<line x1="525" y1="307" x2="565" y2="307" stroke-width="0.5" />
<line x1="525" y1="311" x2="565" y2="311" stroke-width="0.5" />
<line x1="525" y1="315" x2="565" y2="315" stroke-width="0.5" />
</g>
<set attributeName="visibility" to="visible" begin="0s" />
</g>
</defs>
<!--Figuren-->
<defs>
<g id="John" visibility="hidden">
<circle cx="520" cy="100" r="5" />
<line x1="520" y1="104" x2="520" y2="115" stroke-width="2" />
<line x1="520" y1="104" x2="520" y2="117" stroke-width="1" />
<polyline points="520,100 523.5,108 520,112" style="fill:none" />
<polyline points="520,100 514,104 520,108" style="fill:none" />
<set attributeName="visibility" to="visible" begin="0s" />
</g>
</defs>
<!--Animation-->
<use xlink:href="#Karte" />
<use x="420" y="360" transform="rotate(90 910 490)" xlink:href="#John" >
<animateMotion path="M 0 0 L -900 -10" begin="0s" dur="6s" fill="freeze" />
<animateTransform attributeName="transform" type="rotate" from="90 940 490" to="180 940 490" begin="6s" dur="0.001" fill="freeze"/>
<animateMotion path="M-900 -10 L -900 -190" begin="6.01s" dur="3.98s" fill="freeze" />
<animateTransform attributeName="transform" type="rotate" from="180 970 490" to="270 970 490" begin="10s" dur="0.001" fill="freeze"/>
<animateMotion path="M -900 -190 L -450 -190" begin="10.01" dur="4.98" fill="freeze" />
<animateTransform attributeName="transform" type="rotate" from="270 940 490" to="180 940 490" begin="15s" dur="0.001" fill="freeze"/>
<animateMotion path="M -450 -190 L -390 -190" begin="15" dur="1" fill="freeze" />
</use>
</svg>

Resources