Can strokes be used as part of clip-paths in SVGs? - svg

I am in the middle of writing SVG output from MuPDF, and I've run up against what seems to be a limitation in the capabilities of SVG. I thought I'd ask here in case this was a known problem with a known workaround (or in case I'm doing something stupid!)
I have the following SVG:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="21.59cm" height="27.94cm" viewBox="0 0 600 600">
<path stroke-width="12" fill="none" stroke="#0000ff" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
<clipPath id="cp0">
<path stroke-width="12" fill="none" stroke="#000000" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
</clipPath>
<g clip-path="url(#cp0)">
<rect fill="#ff0000" x="0" y="0" width="600" height="600"/>
</g>
</svg>
This draws a stroked path (shaped like '[' in blue). Then it sets the same path to be a clipping path, and fills the clipping path in red.
I was hoping that the clipping path would be set to the stroked version of the path, and hence the red shape would exactly overwrite the blue one. In my tests here however, the "fill or strokedness" of the path is ignored, and the path is "filled" - hence I get a red square drawn within the blue shape.
Is there a way to get the behaviour I was hoping for? Or am I going to have to write code to manually flatten and stroke paths before outputting them to SVG?
Thanks in advance for any replies!

Clip-paths in svg are meant to be just the shape, not the traits of the shape, so in other words you'll not get the stroke included. What you can do is use a mask instead, setting the stroke of the path in the mask to white.
Here's an example:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 600 600">
<defs>
<mask id="m0" maskUnits="userSpaceOnUse" x="0" y="0" width="600" height="600">
<path fill="none" stroke="white" stroke-width="5" d="M 150 300 L 80 300 L 80 370 L 150 370" />
</mask>
</defs>
<path stroke-width="12" fill="none" stroke="#0000ff" d="M 150 300 L 80 300 L 80 370 L 150 370 " />
<g mask="url(#m0)">
<rect fill="yellow" x="0" y="0" width="600" height="600" />
</g>
</svg>

Related

How to fill a color to a donut SVG path by percentage by starting from left side?

I have a donut SVG path. It must start from left side to fill a color and must end at the right side and it must fill by percentage.
See this:
(source: eksiup.com)
I tried to achieve this rotating clipPath like this:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 92 100">
<defs>
<clipPath id="knobMask">
<path style="fill: #ff554e;" d="
M 17.72, 74.28
a 40, 40,0, 1, 1, 56.56, 0
l 4.25, 4.25
a 46, 46, 0, 1, 0-65.06 ,0 Z" />
</clipPath>
</defs>
<g>
<g id="Layer_1" data-name="Layer 1">
<g id="Path_34688-6" data-name="Path 34688-6">
/>
</g>
<path d="M17.72,74.28a40,40,0,1,1,56.56,0l4.25,4.25a46,46,0,1,0-65.06,0Z" />
<g clip-path="url(#knobMask)" transform="rotate(-45,45,45)">
<path style="fill: #ff554e;" d="M 17.72,74.28
a 40,40,0,1,1,56.56,0
l 4.25,4.25
a 46,46,0,1,0-65.06,0Z" />
</g>
</g>
But no luck. How can I fill a color to this path starting from left side by percentage?
Here is the JS Fiddle
Basically I want this:
(source: eksiup.com)
As I've commented there is a simpler way to achieve this. You simplify the path to d="M 17.72,74.28a 40,40,0,1,1,56.56,0" and use fill="none" and stroke="10" for example. For the red path you are using the same d as before and you use stroke-dasharray to reduce the apparent length of the path. If you are using this d the total length of the path is 188.53 so you can use 188.53 / 2 = 94.265 : stroke-dasharray=94.265"
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 92 100" width="200">
<defs>
<path id="base" fill="none" stroke-width="10" d="
M 17.72, 74.28
a 40, 40,0, 1, 1, 56.56, 0" />
</defs>
<use xlink:href="#base" stroke="black" />
<use xlink:href="#base" stroke="#ff554e" stroke-dasharray="94.265" />
</svg>
In the next example I'm using javascript to calculate the value of the dash and the value of the gap. Please use the input type range to change the values.
let totallength=base.getTotalLength();
itr.addEventListener("input",()=>{
let newSDA = (Number(itr.value)*totallength) / 100;
let gap = totallength - newSDA
red.setAttributeNS(null,"stroke-dasharray",`${newSDA} ${gap}`)
})
svg{border:1px solid}
<p><input id="itr" type="range" /></p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 92 100" width="200">
<defs>
<path id="base" fill="none" stroke-width="10" d="
M 17.72, 74.28
a 40, 40,0, 1, 1, 56.56, 0" />
</defs>
<use xlink:href="#base" stroke="black" />
<use xlink:href="#base" id="red" stroke="#ff554e" stroke-dasharray="94.265" />
</svg>

svg object didn't work along with the path Why not?

Why didn't work along with path line?
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="595px" height="841px" viewBox="0 0 595px 841px" enable-background="new 0 0 595 841" xml:space="preserve"
style="border:1px solid green">
<g id="car">
<path fill="#00CC92" d="M405.1,607.225c0,0,1.731-1.022,9.084-1.086c0.466-0.007,9.269-8.254,9.678-8.561
c0.99-0.767,1.194-1.284,3.667-1.476c3.028,0,20.601-0.025,20.601-0.025s6.229-0.332,7.736,2.434
c0.479,0.575,4.434,7.237,4.503,7.596c0,0,0.135,0.159,0.333,0.498c0.472,0.805,1.341,3.723,1.813,6.777
c0.052,0.191,0.09,0.383,0.09,0.588v3.354c0,1.232-1.003,2.236-2.236,2.236h-0.102c0.064-0.365,0.102-0.734,0.102-1.119
c0-3.705-3.002-6.707-6.707-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119h-29.271
c0.064-0.365,0.103-0.734,0.103-1.119c0-3.705-3.003-6.707-6.708-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119
h-2.338c-1.233,0-2.236-1.004-2.236-2.236v-3.354C400.002,613.97,399.728,610.13,405.1,607.225z M442.483,605.027l11.307-0.556
l-1.246-2.798c0,0-0.767-2.235-3.354-2.235s-6.707,0-6.707,0V605.027z M421.076,606.298l3.296-0.217
c0.716-1.591,1.546-2.459,2.306-2.612c0.92-0.192,1.311,0.798,1.311,0.798v1.571l12.258-0.805v-5.558
c0,0-10.725-0.038-11.843-0.038s-2.689,1.954-2.689,1.954L421.076,606.298z M458.133,618.441c0,2.473-1.999,4.473-4.472,4.473
s-4.472-2-4.472-4.473c0-2.471,1.999-4.471,4.472-4.471S458.133,615.97,458.133,618.441z M415.653,618.441
c0,2.473-1.999,4.473-4.472,4.473c-2.472,0-4.472-2-4.472-4.473c0-2.471,2-4.471,4.472-4.471
C413.654,613.97,415.653,615.97,415.653,618.441z">
</path>
</g>
<path fill="none" id="motionPath" stroke="green" stroke-width="8"
d="M400,618c0,0-127,66-112-52s134-264-90-251s-63-117-56-170"></path>
<animateMotion xlink:href="#car" dur="5s" begin="click" fill="freeze" >
<mpath xlink:href="#motionPath"></mpath>
</animateMotion>
</svg>
The problem you are having is due to the fact that the position of the car on the page is added to the (animated) position along the path. So when you click the car, it jumps to effectively:
(motionPath.x + car.x, motionPath.y + car.y)
To fix this, you have to do one of two things:
position the motion path so it starts at (0,0) on the page (the top left), or
position the car at (0,0).
Since you want the car to start where it is on the page, so you can click on it, you are basically forced to choose option #1.
In the example below I've changed the motion path to one that starts at (0,0). I've just used a simple line because I don't have the time to work out the new coordinates for your whole path.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="595px" height="841px" viewBox="0 0 595px 841px" enable-background="new 0 0 595 841" xml:space="preserve"
style="border:1px solid green">
<g>
<path id="car"
fill="#00CC92" d="M405.1,607.225c0,0,1.731-1.022,9.084-1.086c0.466-0.007,9.269-8.254,9.678-8.561
c0.99-0.767,1.194-1.284,3.667-1.476c3.028,0,20.601-0.025,20.601-0.025s6.229-0.332,7.736,2.434
c0.479,0.575,4.434,7.237,4.503,7.596c0,0,0.135,0.159,0.333,0.498c0.472,0.805,1.341,3.723,1.813,6.777
c0.052,0.191,0.09,0.383,0.09,0.588v3.354c0,1.232-1.003,2.236-2.236,2.236h-0.102c0.064-0.365,0.102-0.734,0.102-1.119
c0-3.705-3.002-6.707-6.707-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119h-29.271
c0.064-0.365,0.103-0.734,0.103-1.119c0-3.705-3.003-6.707-6.708-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119
h-2.338c-1.233,0-2.236-1.004-2.236-2.236v-3.354C400.002,613.97,399.728,610.13,405.1,607.225z M442.483,605.027l11.307-0.556
l-1.246-2.798c0,0-0.767-2.235-3.354-2.235s-6.707,0-6.707,0V605.027z M421.076,606.298l3.296-0.217
c0.716-1.591,1.546-2.459,2.306-2.612c0.92-0.192,1.311,0.798,1.311,0.798v1.571l12.258-0.805v-5.558
c0,0-10.725-0.038-11.843-0.038s-2.689,1.954-2.689,1.954L421.076,606.298z M458.133,618.441c0,2.473-1.999,4.473-4.472,4.473
s-4.472-2-4.472-4.473c0-2.471,1.999-4.471,4.472-4.471S458.133,615.97,458.133,618.441z M415.653,618.441
c0,2.473-1.999,4.473-4.472,4.473c-2.472,0-4.472-2-4.472-4.473c0-2.471,2-4.471,4.472-4.471
C413.654,613.97,415.653,615.97,415.653,618.441z">
</path>
</g>
<path fill="none" id="motionPath" stroke="green" stroke-width="8"
d="M 0,0 L -250,-470" transform="translate(431,609)"></path>
<animateMotion xlink:href="#car" dur="5s" begin="click" fill="freeze" >
<mpath xlink:href="#motionPath"></mpath>
</animateMotion>
</svg>
You may be wondering why, if the motion path has been moved, why it still being displayed in the same place? The reason is that is that I've added a transform to the motion path so the start corresponds to the centre of the car, which is at approximately (431,609). This doesn't affect the animateMotion because it only cares about what's in the d attribute. It ignores the transform attribute.
Update
Another alternative is to just position both the path and the car so that they start at (0,0). Then wrap the whole thing in a group that you transform to the final position. That allows you to also use the rotate attribute in your animation.
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="595px" height="841px" viewBox="0 0 595 841"
style="border:1px solid green">
<g transform="translate(431,609)">
<g id="car">
<path transform="translate(-431,-626)"
fill="#00CC92" d="M405.1,607.225c0,0,1.731-1.022,9.084-1.086c0.466-0.007,9.269-8.254,9.678-8.561
c0.99-0.767,1.194-1.284,3.667-1.476c3.028,0,20.601-0.025,20.601-0.025s6.229-0.332,7.736,2.434
c0.479,0.575,4.434,7.237,4.503,7.596c0,0,0.135,0.159,0.333,0.498c0.472,0.805,1.341,3.723,1.813,6.777
c0.052,0.191,0.09,0.383,0.09,0.588v3.354c0,1.232-1.003,2.236-2.236,2.236h-0.102c0.064-0.365,0.102-0.734,0.102-1.119
c0-3.705-3.002-6.707-6.707-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119h-29.271
c0.064-0.365,0.103-0.734,0.103-1.119c0-3.705-3.003-6.707-6.708-6.707s-6.707,3.002-6.707,6.707c0,0.385,0.038,0.754,0.103,1.119
h-2.338c-1.233,0-2.236-1.004-2.236-2.236v-3.354C400.002,613.97,399.728,610.13,405.1,607.225z M442.483,605.027l11.307-0.556
l-1.246-2.798c0,0-0.767-2.235-3.354-2.235s-6.707,0-6.707,0V605.027z M421.076,606.298l3.296-0.217
c0.716-1.591,1.546-2.459,2.306-2.612c0.92-0.192,1.311,0.798,1.311,0.798v1.571l12.258-0.805v-5.558
c0,0-10.725-0.038-11.843-0.038s-2.689,1.954-2.689,1.954L421.076,606.298z M458.133,618.441c0,2.473-1.999,4.473-4.472,4.473
s-4.472-2-4.472-4.473c0-2.471,1.999-4.471,4.472-4.471S458.133,615.97,458.133,618.441z M415.653,618.441
c0,2.473-1.999,4.473-4.472,4.473c-2.472,0-4.472-2-4.472-4.473c0-2.471,2-4.471,4.472-4.471
C413.654,613.97,415.653,615.97,415.653,618.441z">
</path>
</g>
<path fill="none" id="motionPath" stroke="green" stroke-width="8"
d="M 0,0 L -250,-470"/>
<animateMotion xlink:href="#car" dur="5s" begin="click" fill="freeze"
rotate="auto-reverse">
<mpath xlink:href="#motionPath"></mpath>
</animateMotion>
</g>
</svg>

Rotate circle and position arc over it with start and end angle

Hi is there any way to design the below picture with SVG or any other way?
Please find the SVG Code for the circle with head
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="110px" height="110px" viewBox="0 0 110 110" enable-background="new 0 0 110 110" xml:space="preserve">
<g>
<title>Sample</title>
<g>
<path d="M60.391,23.712V0H48.975v23.571c-21.802,2.619-37.87,20.953-37.87,43.041c0,23.995,19.536,43.391,43.411,43.391
c23.855,0,43.392-19.396,43.392-43.391C97.907,44.736,81.202,26.543,60.391,23.712z M22.501,66.682
c0-17.628,14.369-31.998,32.015-31.998c17.626,0,31.995,14.37,31.995,31.998c0,17.625-14.299,32.065-31.995,32.065
C36.8,98.747,22.501,84.307,22.501,66.682z"/>
</g>
Head
Based on the head angle in the example 332° the circle should rotate
Red Arc
Based on the start and end position of the arc it should start from there with displaying the start and end position as in the picture 50 and 180.
Please help me to design :-)
Try this i used rect and circle instead of path
svg{
background:#223D50;
}
<svg width="100%" height="100%" viewbox="0 0 100 100">
<rect x="40" y="30" width="3" height="12" fill="grey" transform="rotate(-28 42 50)"/>
<circle cx="42" cy="53" r="10" stroke-width="3" stroke="grey" fill="none"/>
<circle cx="42" cy="53" r="18" fill="transparent" stroke-width="5" stroke="red" stroke-dasharray="36.11111% 100%" stroke-dashoffset="0" transform="rotate(-30 42, 53)"/>
<text x="36" y="55" fill="white" font-size="5">Check</text>
</svg>

SVG inverse marker mask/clip-path

I've tried unsuccessfully to replace the white triangle, the marker-start, with an inverse mask/clip-path in order to cut the end of the arrow in shape of the marker instead of painting it white.
Not sure if marker masks can be defined.
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" id="mySVG" viewBox="-100 0 200 200" height="600" width="700">
<defs>
<marker refY="0.5" refX="0.0" markerHeight="4" markerWidth="2" orient="auto" id="head">
<path fill="#D0D0D0" d="M0,0 L0.5,0.5 L0,1 L-0.5,0.5 Z"/>
</marker>
<marker refY="0.6" refX="0.1" markerHeight="4" markerWidth="2" orient="auto" id="tail">
<clip-Path id="cp1" d="M0 0 V1.3 L0.6 0.6 Z">
<path fill="white" d="M0 0 V1.3 L0.6 0.6 Z" />
<clip-Path>
</marker>
</defs>
<path id="myArrow" marker-start="url(#tail)" marker-end="url(#head)" d="M -66.38265586443396 22.21132594835645 A 70 70 0 0 0 66.38265586443396 22.21132594835645" fill="none" stroke="#D0D0D0" stroke-width="8" clip-path="url(#cp1)"/>
Markers are independent symbols which are positioned and drawn at the various points in the path after the path has been drawn.
It sounds like you are trying to use them to clip out bits of the path. This is futile. That's not how markers work, I'm afraid.

Adding new nodes to an SVG <use> tag

Just playing the defs and use for the first time. What I would like to do is use defs to build a base template and then when I use it customise it by adding some more inner tags.
Is this possible, as when I try to do it in Firefox it doesn't render any tags which I place as children to the use tag. e.g:
<?xml version="1.0" standalone="no"?>
<svg width="10000px" height="5500px" version="1.1"
baseProfile="full"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="storyCard">
<rect width="800px" height="500px" fill="#ffff00" />
<path d="M 20 120 L 780 120 M 640 20 L 640 120" stroke-width="6px" stroke="black" fill="none" />
</g>
</defs>
<!-- White Board -->
<path d="M 0 0 L 10000 0 L 10000 550 L 0 5500 z M 2000 0 L 2000 5500" stroke-width="20px" stroke="black" fill="none" />
<use xlink:href="#storyCard" transform="translate(100,100)" />
<use xlink:href="#storyCard" transform="translate(1000,200)" >
<text x="20" y="80" font-size="45" font-weight="bold" font-family="Comic Sans MS, cursive">
My Dummy Story
</text>
</use>
</svg>
It isn't directly possible with use. The use element can contain description and animation elements, but it doesn't behave like an XBL container.
You could use XBL, if you're targeting firefox.
To stay within SVG, make a group and use the background:
<g transform="translate(1000,200)" >
<use xlink:href="#storyCard"/>
<text x="20" y="80" font-size="45" font-weight="bold" font-family="Comic Sans MS, cursive">
My Dummy Story
</text>
</g>

Resources