Please consider the following SVG:
<svg xmlns="http://www.w3.org/2000/svg" width=100 height=100 viewBox="0 0 512 512">
<!-- path fill="none" stroke-linecap="round" stroke-width="10" stroke="black" d="M256 256 5 5 V507"/ -->
<path fill="none" stroke-linecap="round" stroke-width="10" stroke="black" d="M256 256 5 5m0 0V507"/>
</svg>
I want the top left corner to be rounded, hence, I am using stroke-linecap="round". I would have expected the remarked path statement to work, but it yields a sharp corner. I did have to move the pointer relative by m0 0 before drawing the vertical line V507 to get the desired result. I don't understand why a relative m0 0 movement makes sense. Is this by design or a bug?
Related
I'm trying to generate an svg icon to use as Leaflet map markers. There's a circle which should be partially filled (vertically) based on a percentage variable between 0 and 1 (0 = no fill, 1 = full circle). I managed to accomplish what I need using a linear gradient, and that was working fine in Google Maps. Now I'm migrating to Leaflet, and apparently Leaflet doesn't support linear gradients in icons, as it doesn't render it properly. Or maybe it just doesn't support referencing elements with url().
This is what I have been using, using 0.4 as the fill percentage:
<svg width="25px" height="25px" viewBox="0 0 100 100" version="1.1">
<linearGradient id="perc" x1="0.4" y1="1" x2="0.4" y2="0">
<stop stop-color="#80C000" offset="0.4"/>
<stop stop-color="#fff" />
</linearGradient>
<ellipse id="outsideCircle" fill="#80C000" cx="50" cy="50" rx="42.8" ry="42.8"/>
<ellipse id="middleCircle" fill="url(#perc)" cx="50" cy="50" rx="41.2" ry="41.2"/>
<ellipse id="insideCircle" stroke="#80C000" fill="#EFFADC" stroke-width="1.6" cx="50" cy="50" rx="32" ry="32"/>
<text text-anchor="middle" font-family="Verdana" font-size="320%" font-weight="bold" dominant-baseline="central" x="50" y="48" fill="#80C000">A</text>
</svg>
Which renders as (enlarged for clarity):
However, using the exact same code in Leaflet always renders the full green circle, and I'm not sure why. So I'm looking for another way to accomplish this, maybe using Arcs? It would be great if I could generate the icons based on the same percentage variable, but I'm also open to just using 11 static icons (0, 0.1, 0.2, ..., 0.9, 1) and selecting one to use based on the percentage, rounding it.
I've found this question with some promising results, but I've been unable to adapt it to my use case.
An alternative solution would be using a line path that you clip with the circle. Now you can use the stroke-dasharray attribute to set the stroke and the gap length of the path.
I'm using an input type range only to show how the result for different values.
let len = line.getTotalLength();
itr.addEventListener("input",()=>{
let dash = itr.value * len/100;
line.setAttribute("stroke-dasharray",`${dash},${100 - dash}`);
console.clear();console.log(itr.value)
})
<P><input type="range" value="25" id="itr"/></p>
<svg width="100" viewBox="0 0 100 100" version="1.1">
<text text-anchor="middle" font-family="Verdana" font-size="320%" font-weight="bold" dominant-baseline="central" x="50" y="48" fill="#80C000">A</text>
<clipPath id="clip">
<path id="circ" d="M92.8,50A42.8, 42.8 0 1 1 7.2,50A42.8,42.8 0 1 1 92.8,50 M82,50A32,32 0 1 0 18,50 A32,32 0 1 0 82,50" />
</clipPath>
<path id="line" stroke="#80C000" stroke-width="86" d="M50,92.8V7.2" clip-path="url(#clip)" stroke-dasharray="25 75" />
<use href="#circ" fill="none" stroke="#80C000" />
</svg>
Observation: I'm rewriting thecircle as a path with a hole in the middle like so:
<svg width="100" viewBox="0 0 100 100" version="1.1">
<path id="circ" d="M92.8,50A42.8, 42.8 0 1 1 7.2,50A42.8,42.8 0 1 1 92.8,50 M82,50A32,32 0 1 0 18,50 A32,32 0 1 0 82,50" />
</svg>
In order to draw a hole into the circle I'm drawing first the outer circle clockwise and nextnthe inner circle counterclockwise. I will use this shape for the clipPath but also for a <use> element to draw the green stroke of the circle.
Is it possible to add more than one or two strokes on a single svg path.
Ex.
This is my code
<svg id="" xmlns="http://www.w3.org/2000/svg" height="576" width="576" style="position: absolute;">
<path d="M 10,10 L 10,20 20,20 20,10 30,10" fill="#ff0000;" stroke="#f000" stroke-width="1px" ></path>
</svg>
and I want stroke color like as a below image:
One path, one stroke.
You may redraw the same path over and over using different settings of stroke-dasharray with different colors, so that three gaps will be followed by one segment in a specifc color. However, the length of such segments would have to coincide with the length of the line segments.
If the line segments (from corner to corner) have a differing length within the path, then this would not work.
And: the length of the line segments has to match exactly the length of th egaps specified by stroke-dasharray.
Edit: For aligning the length, you may explicitly set the path length within the path element using pathLength="100"
and combine that with stroke-dasharray="25, 75" and varying value of
stroke-dashoffset steping through 0, 25, 50, 75
I have split path and give different colors.
<svg id="" xmlns="http://www.w3.org/2000/svg" height="576" width="576" style="position: absolute;">
<path d="M 10,10 L 10,20" fill="#ff0000;" stroke="yellow" stroke-width="1px" ></path>
<path d="M 10,20 L 20,20" fill="#ff0000;" stroke="red" stroke-width="1px" ></path>
<path d="M 20,20 L 20,10" fill="#ff0000;" stroke="blue" stroke-width="1px" ></path>
<path d="M 20,10 L 30,10" fill="#ff0000;" stroke="green" stroke-width="1px" ></path>
</svg>
I have a curved svg line like this
<path d="M70,260 C105,260 126,330 160,330"
style="stroke: #ff4444;stroke-width:2; fill:none;"/>
what I want is to add another svg (like https://www.flaticon.com/free-icon/play-button_149657) in the middle of my line pointing to the end point.
any ideas?
One way to achieve the result is a degenerate animation:
Define the marker shape (obj1 in the example below)
Position the marker at the beginning of the curve (track1 below; this is the path definition from your example).
Specify an animated motion of the marker shape along the curve with some particular settings:
Explicit positioning along the track using keyTimes, keyPoints attributes, limiting the range of positions to exactly one point: the midpoint of the curve
Infinite duration, infinite repeat
Auto-rotation of the shape according to the orientation of the track curve ( rotate attribute )
Effectively there is no animation at all but the shape is positioned at the center of the curve, properly oriented.
Example
<html>
<head>
<title>SVG object centered on path</title>
</head>
<body>
<svg width="200px" height="200px"
viewBox="0 0 500 500"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
>
<defs>
<path
id="obj1"
d="M11.18,0 L-2.5,10 -2.5,-10 Z"
stroke="black" stroke-width="1" fill="green"
>
</path>
<path
id="track1"
d="M70,260 C105,260 126,330 160,330"
stroke="#ff4444" stroke-width="2" fill="none"
/>
</defs>
<use xlink:href="#track1"/>
<use xlink:href="#obj1">
<animateMotion
calcMode="linear"
dur="infinite"
repeatCount="infinite"
rotate="auto"
keyPoints="0.5;0.5"
keyTimes="0.0;1.0"
>
<mpath xlink:href="#track1"/>
</animateMotion>
</use>
</svg>
</body>
</html>
There are a number of ways to do this.
One way is to "cheat" a little and use a <textPath> and an arrow character.
SVG marker-mid on specific point on path
This is a little hacky, and may not work reliably on all browsers, but it may be good enough for your needs.
Another way is split the path in two (using De Casteljau's algorithm), and use a <marker>.
<svg viewBox="0 200 200 200" width="400">
<defs>
<marker id="Triangle"
viewBox="0 0 10 10" refX="0" refY="5"
markerUnits="strokeWidth"
markerWidth="4" markerHeight="3"
orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" />
</marker>
</defs>
<path d="M 70,260
C 87.5,260 101.5,277.5 115.375,295
C 129.25,312.5 143,330 160,330"
style="stroke: #ff4444; stroke-width:2; fill:none; marker-mid:url(#Triangle)"/>
</svg>
There are other ways using Javascript. For example, you could use the SVGPathElement.getPointAtLength() method to find the coordinates of the centre of the path. Then position a triangle at that location.
I have this rather basic SVG with a vertical line going through 4 circles. The mask that I have for the vertical line has the same definition as the line itself, the only difference being the stroke color (#fff in this case) because I want to be able to see through the mask. But, for unknown reasons, the mask still acts as if the color is black, thus hiding the element. If anyone knows why it's behaving like this, please let me know.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">
<defs>
<mask id="education">
<path class="through" fill="none" stroke="#fff" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
</mask>
</defs>
<path class="arrow" fill="#C57773" d="M191.9 41.5l8.1-14 8.1 14"/>
<path style="mask: url(#education);" class="through" fill="none" stroke="#58595B" stroke-width="2" stroke-miterlimit="10" d="M200 325.6v42.5M200 325.6V44.2"/>
<path class="circle2" fill="#C95147" d="M200 234.7c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle1" fill="#C95147" d="M200 317.2c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
<path class="circle3" fill="#C95147" d="M200 152c-4.6 0-8.3 3.7-8.3 8.3 0 4.6 3.7 8.3 8.3 8.3 4.6 0 8.3-3.7 8.3-8.3 0-4.5-3.7-8.3-8.3-8.3z"/>
<path class="circle4" fill="#C95147" d="M200 67.1c-4.6 0-8.3 3.7-8.3 8.3s3.7 8.3 8.3 8.3c4.6 0 8.3-3.7 8.3-8.3s-3.7-8.3-8.3-8.3z"/>
</svg>
P.S. Just started tinkering around with SVG, but this (the element dissapearing) happens no matter what shape I define in the mask or what color I give that shape.
SVG is not like CSS, it doesn't use the stroke-width when calculating dimensions for masks and filters, so you can't mask a shape like a horizontal or vertical line (zero-height/zero-width bounding box) using default mask parameters. Just add "maskUnits="userSpaceOnUse" to your mask element to fix.
<mask id="education" maskUnits="userSpaceOnUse">
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.