how to repeat infinitely the whole svg - 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>

Related

Gap SVG circle/ellipse with vertical linecap edges

I am drawing an SVG ellipse and I want two gaps, positioned center top and bottom:
<ellipse fill="none" stroke="black" stroke-width cx="15" cy="15" rx="12.55" ry="13.45" stroke-dasharray="19.65 1.5 39.32 1.5"/>
But I want the gap edges to be vertical, like if I a straight line was drawn through the un-gapped ellipse:
<g stroke-width="1.5">
<ellipse stroke="black" fill="none" cx="15" cy="15" rx="12.55" ry="13.45"/>
<path stroke="white" d="M15 35 V30">
</g>
I can't do that, because the line is not transparent. The gaps should look like nothing has been drawn there and not alter or overlay the background.
Further unsuccessful experiments:
stroke-linecap="square" on example #1
stroke="transparent" for the line in ex. #2.
stroke="transparent" stroke-occupacy="1" for the line in ex. #2.
What can I do?
jsfiddle
This is a typical case for using a mask. Everything that coincides with the white parts of the mask is drawn as is, everything that coincides with the black parts becomes transparent.
<svg viewBox="0 0 40 40" height="90vh">
<mask id="mask">
<rect width="100%" height="100%" fill="white" />
<path stroke="black" stroke-width="5" d="M15 35 V0" />
</mask>
<ellipse stroke="black" fill="none" stroke-width="1.5"
mask="url(#mask)"
cx="15" cy="15" rx="12.55" ry="13.45" />
</svg>

Edge / corner color issues with SVG line / path

This:
<svg width=100 height=100>
<g transform="translate(0.5, 0.5)" stroke=red fill=none>
<line x1=10 y1=10 x2=10 y2=50 />
<path d="M20,10 H20 V50 H20 Z" />
<path d="M30,10 H31 V50 H30 Z" />
<path d="M40,10 H42 V50 H40 Z" />
<path d="M50,10 H52 V50 H50 Z" />
</g>
</svg>
produces image like this in Chrome (zoomed in so it's obvious):
Top part
Bottom part
Note that the edges of the lines and the corners of the rectangles are of a slightly lighter red.
This looks like it's anti-aliasing, but trying shape-rendering="crispEdges" suggestion in this answer did not fully work. The problem is that it then cuts the line by 1px instead:
<svg width=100 height=100>
<g shape-rendering="crispEdges" stroke=red fill=none>
<line x1=10 y1=10 x2=10 y2=50 />
<path d="M20,10 H20 V50 H20 Z" />
<path d="M30,10 H31 V50 H30 Z" />
<path d="M40,10 H42 V50 H40 Z" />
<path d="M50,10 H52 V50 H50 Z" />
</g>
</svg>
Top part
Bottom part
Is there a way to fix this somehow, so I get the same line color across the specified coordinate range?
On Win64 Chrome, I'm only seeing the antialiasing on the first two elements.
The explanation for the line element is simple. Because you are translating down by half a pixel, the two line ends are ending halfway up/down a pixel. Hence you will get antialiasing in that case. Adjust the coords, or add stroke-linecap="square" to fix that.
Illustration:
<svg viewBox="0 0 70 40" width="420">
<g transform="translate(10,10)">
<g fill="none" stroke="#ccc" id="grid">
<rect width="10" height="10"/>
<rect x="10" width="10" height="10"/>
<rect y="10" width="10" height="10"/>
<rect x="10" y="10" width="10" height="10"/>
</g>
<!-- line (as is) -->
<line x1="5" y1="20" x2="5" y2="5" stroke="#00c8" stroke-width="10"/>
<line x1="5" y1="20" x2="5" y2="5" stroke="red" stroke-width="1"/>
</g>
<g transform="translate(40,10)">
<use xlink:href="#grid"/>
<!-- rectamngle corner -->
<path d="M 5,20 L 5,5 L 20,5" fill="none" stroke="#00c8" stroke-width="10"/>
<path d="M 5,20 L 5,5 L 20,5" fill="none" stroke="red" stroke-width="1"/>
</g>
</svg>
As for the zero width rectangle. Not sure what's happening there. It is only slightly lighter. It is likely a rendering bug in Skia. It may only effect the GPU renderer of Skia (I didn't check). The GPU renderer has a few more rendering bugs on these sort of edge cases than the CPU rendering path. If you care, you could file a bug about it.
<svg width=100 height=100>
<g transform="translate(0.5, 0.5)" stroke=red fill=none>
<line x1=10 y1=10 x2=10 y2=50 stroke-linecap="square"/>
<path d="M20,10 H20 V50 H20 Z" />
</g>
</svg>

SVG hide an object until needed

I'm able to move an object along a Bezier Curve but am having some difficulty with 'defs' and 'use'. My object (circle) appears at 0,0 before the animation begins, then appears in the correct position.
<svg viewBox="0 0 500 300" style="border:1px solid black; width:500; height:500;" xmlns="http://www.w3.org/2000/svg" >
<path id="track" d="M100,200 C200,150 300,250 400,200" stroke-width="3" stroke="#000" fill="none"/>
<circle id="circ1" r="10" cx="0" cy="0" fill="red" >
<animateMotion begin="1s" dur="6s" fill="freeze">
<use href="#circ1" cx="100" cy="200"/>
<mpath xlink:href="#track"/>
</animateMotion>
</circle>
</svg>
How can I make it appear at the beginning of the Bezier line, not at 0,0?
You can use <set> elements to set the position of the circle at the begining of the curve. Next at 1s you need to set again the position of the circle on 0,0
<svg viewBox="0 50 500 300" style="border:1px solid black; width:500; height:300;" xmlns="http://www.w3.org/2000/svg" >
<path id="track" d="M100,200 C200,150 300,250 400,200" stroke-width="3" stroke="#000" fill="none"/>
<circle id="circ1" r="10" cx="0" cy="0" fill="red">
<set begin="0" attributeName="cx" to="100" />
<set begin="0" attributeName="cy" to="200" />
<set begin="1s" attributeName="cx" to="0" />
<set begin="1s" attributeName="cy" to="0" />
<animateMotion begin="1s" dur="6s" fill="freeze">
<!--<use href="#circ1" cx="100" cy="200"/>-->
<mpath xlink:href="#track"/>
</animateMotion>
</circle>
</svg>
Yet another solution would be changing the origin of the curve so that it begins in the 0,0.
Please observe that I've changed the value of the viewBox attribute so that you can still see the curve in the middle of the svg canvas.
<svg viewBox="-100 -150 500 300" style="border:1px solid black; width:500; height:300;" xmlns="http://www.w3.org/2000/svg" >
<path id="track" d="M0,0C100,-50,200,50,300,0" stroke-width="3" stroke="#000" fill="none"/>
<circle id="circ1" r="10" cx="0" cy="0" fill="red" >
<animateMotion begin="1s" dur="6s" fill="freeze">
<!--<use href="#circ1" cx="100" cy="200"/>-->
<mpath xlink:href="#track"/>
</animateMotion>
</circle>
</svg>

How to color a region i.e the intersection of two object?

I want to color an intersection of two object, let's say a circle and a rectangle.
What I have tried so far is to defined a path bounding that region then add the fill attribute, but it seems too complicated.
Is there any other ways to do so?
Let me elabotare more one the problem:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<line y2="0.75" x2="103.95" y1="43.15" x1="42.35" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="50.35" x2="201.55" y1="0.75" x1="103.95" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="19.15" x2="239.95" y1="49.55" x1="201.55" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="55.95" x2="282.35" y1="18.35" x1="240.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="37.55" x2="351.15" y1="31.95" x1="0.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
</svg>
I have a set of lines which the end of one is another end of the other.
I have another line intersecing these line.
How could I color the region i.e the triangles formed by these line?
You can use <clipPath> to clip the rect with the circle like so:
svg{width:100vh;}
<svg viewBox="50 50 200 100">
<clipPath id="clip">
<use xlink:href="#c" />
</clipPath>
<g fill="none" stroke="black" >
<circle id="c" cx="100" cy="100" r="30" />
<rect id="r" x="90" y="80" width="80" height="60" />
</g>
<use xlink:href="#r" clip-path="url(#clip)" fill="gold" />
</svg>
You could work with opacity to let the color of an overlapped element shine through like shown here:
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g style="stroke:#000; stroke-width:1">
<circle cx="50" cy="50" r="50" opacity="0.5" style="fill:red" />
<circle cx="100" cy="50" r="50" opacity="0.5" style="fill:yellow" />
<rect x="0" y="70" width="150" height="50" fill-opacity="0.5" style="fill:blue" />
</g>
</svg>
You can also specify the opacity levels separately for stroke and fill by using stroke-opacity and fill-opacity.
Edit:
Looking at your edited question again: when you are dealing with a succession of lines (and curves) you should use <path> elements instead of individual <line> elements. One of its advantages is that it comes with a fill behaviour that is almost exactly as you want it to be. However, to suit the requirements of your example you would need to find the positions where the straight line enters and leaves the zig-zag shape. These positions then define the points used for your filled path. The "original" (non-filled) path is then plotted over the filled path:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<path d="M56,33 103.95,0.75 201.55,50.35 239.95,19.15 260,36z
M0.75,31.95 351.15,37.55" style="fill:yellow" />
<path d="M42.35,43.15 103.95,0.75 201.55,50.35 239.95,19.15 282.35,55.95
M0.75,31.95 351.15,37.55" style="stroke:black;fill:none"/>
</svg>

How to calculate the distance between two points in SVG?

In the Pie chart, whenever a slice is clicked it has to be moved slightly as in the image.
This is the image
How this can be done? What I am doing is,create a virtual arg with radius 10 higher that the original one. Then to find out the distance between these.
After the distance is calculated use the X,Y value to the translate(X,Y) attribute to move the arc slice to specified point
Here is an example :
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 400 400" width="400" height="400" version="1.0">
<g transform="translate(200 200)">
<circle cx="0" cy="0" r="150" stroke="#000" fill="none" />
<path d="M0,-150 Q0,0 106.066,-106.066" fill="none" stroke="red" stroke-width="3" />
<path d="M0,-150 Q0,0 106.066,106.066" fill="none" stroke="red" stroke-width="3" />
<path d="M0,-150 Q0,0 -106.066,106.066" fill="none" stroke="red" stroke-width="3" />
<path d="M0,-150 Q0,0 -106.066,-106.066" fill="none" stroke="red" stroke-width="3" />
</g>
</svg>

Resources