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>
Related
I'm drawing an SVG line with a "marker-end" to make it an arrow. It draws the arrowhead extending beyond the end of the line, making the whole arrow longer, but I would like the whole arrow to be the same length as the original line. That is, the tip of the arrowhead should be at the endpoint of the line. How do I do that?
Making the line shorter to accommodate the size of the arrowhead won't really work. The size of the arrowhead depends on the thickness of the line (which is good), but I don't know the thickness because it can be specified in a style element that's already been written to the SVG document.
In this example, I'd like the the arrowhead entirely inside the square, with its tip at the square's corner, rather than sticking out of the square.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<g><marker id="arrowhead0" viewBox="0 0 60 60" refX="0" refY="30" markerUnits="strokeWidth" markerWidth="8" markerHeight="10" orient="auto">
<path d="M 0 0 L 60 30 L 0 60 z" fill="#800000" /> </marker>
<line marker-end="url(#arrowhead0)" x1="1" y1="1" x2="100" y2="100" stroke="#800000" />
<rect x="1" y="1" width="100" height="100" stroke="green" fill="none"/>
</g></svg>
Setting the refX atribute to 60 (which I think might be the width of the arrowhead when oriented pointing to the right) seems to fix this issue. Scaling the width seems to be fine, not sure about other attributes.
I am no SVG expert, just found this interesting and played with the attributes until I stumbled upon this solution, so take it with a grain of salt.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<g><marker id="arrowhead0" viewBox="0 0 60 60" refX="0" refY="30" markerUnits="strokeWidth" markerWidth="8" markerHeight="10" orient="auto">
<path d="M 0 0 L 60 30 L 0 60 z" fill="#800000" /> </marker>
<marker id="arrowhead1" viewBox="0 0 60 60" refX="60" refY="30" markerUnits="strokeWidth" markerWidth="8" markerHeight="10" orient="auto">
<path d="M 0 0 L 60 30 L 0 60 z" fill="#800000" /> </marker>
<marker id="arrowhead2" viewBox="0 0 60 60" refX="60" refY="30" markerUnits="strokeWidth" markerWidth="16" markerHeight="10" orient="auto">
<path d="M 0 0 L 60 30 L 0 60 z" fill="#800000" /> </marker>
<line marker-end="url(#arrowhead0)" x1="1" y1="1" x2="100" y2="100" stroke="#800000" />
<line marker-end="url(#arrowhead1)" x1="1" y1="100" x2="50" y2="50" stroke="#800000" />
<line marker-end="url(#arrowhead2)" x1="100" y1="1" x2="50" y2="50" stroke="#800000" />
<rect x="1" y="1" width="100" height="100" stroke="green" fill="none"/>
</g></svg>
refX and refY control that so adjust as necessary. E.g.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<g><marker id="arrowhead0" viewBox="0 0 60 60" refX="44" refY="34" markerUnits="strokeWidth" markerWidth="8" markerHeight="10" orient="auto">
<path d="M 0 0 L 60 30 L 0 60 z" fill="#800000" /> </marker>
<line marker-end="url(#arrowhead0)" x1="1" y1="1" x2="100" y2="100" stroke="#800000" />
<rect x="1" y="1" width="100" height="100" stroke="green" fill="none"/>
</g></svg>
Use "marker-start" instead of "marker-end", draw the arrowhead backwards, and swap the line's endpoints.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<g><marker id="arrowhead0" viewBox="0 0 60 60" refX="0" refY="30" markerUnits="strokeWidth" markerWidth="8" markerHeight="10" orient="auto">
<path d="M 60 0 L 0 30 L 60 60 z" fill="#800000" /> </marker>
<line marker-start="url(#arrowhead0)" x1="100" y1="100" x2="1" y2="1" stroke="#800000" />
<rect x="1" y="1" width="100" height="100" stroke="green" fill="none"/>
</g></svg>
Trying a basic example from Mozilla Docs and the top arrow is not oriented correctly (only in Ms Edge browser) : https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/orient
Is there any way to fix it for that browser?
Apparently orient="auto-start-reverse" doesn't work in edge so you will need to use orient="auto". For this instead of a polyline I'm using 2 lines with the origin in 10,90
svg{width:300px}
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="5" refY="5"
markerWidth="6" markerHeight="6"
orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" />
</marker>
<marker id="dataArrow" viewBox="0 0 10 10" refX="5" refY="5"
markerWidth="6" markerHeight="6"
orient="-65deg">
<path d="M 0 0 L 10 5 L 0 10 z" fill="red" />
</marker>
</defs>
<line x1="10" y1="90" x2="90" y2="90" fill="none" stroke="black"
marker-end="url(#arrow)" marker-end="url(#arrow)" />
<line x1="10" y1="90" x2="10" y2="10" fill="none" stroke="black"
marker-end="url(#arrow)" marker-end="url(#arrow)" />
<polyline points="15,80 29,50 43,60 57,30 71,40 85,15" fill="none" stroke="grey"
marker-start="url(#dataArrow)" marker-mid="url(#dataArrow)"
marker-end="url(#dataArrow)" />
</svg>
See this pen: https://codepen.io/AmeliaBR/details/qjXoQd
"auto-start-reverse SVG marker ...... Doesn't work in Edge/IE (and other older browsers) and doesn't fallback nicely (you get a non-rotating marker instead)."
I'm trying to build svg-line (or path - doesn't matter) with repeating markers along it's entire length. What is the best way to implement it?
There is a description of marker-pattern property on w3. It looks perfect but for some reason I can't get the correct result in my code.
Furthermore, I don't see any markers, replicating the w3 example:
https://jsfiddle.net/pLaukq8p/
<svg xmlns="http://www.w3.org/2000/svg" width="600" height="200">
<marker id="DoubleDash" markerWidth="8" markerHeight="12" refX="0" refY="0"
viewBox="-4 -6 8 12" markerUnits="userSpaceOnUse" orient="auto">
<rect x="-3" y="-5" width="2" height="10"/>
<rect x="1" y="-5" width="2" height="10"/>
</marker>
<marker id="SingleDash" markerWidth="4" markerHeight="12" refX="0" refY="0"
viewBox="-2 -6 4 12" markerUnits="userSpaceOnUse" orient="auto">
<rect x="-1" y="-5" width="2" height="10"/>
</marker>
<path d="M 50,100 S 100,132 150,86 200,173 250,76 300,81
350,136 400,87 450,166 500,87 550,96"
stroke="deeppink" stroke-width="2" fill="none"
marker-pattern="40 url(#DoubleDash) 40 url(#SingleDash)"/>
</svg>
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>
Currently, I have the following svg:
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" onclick='dispcoord(evt)' viewBox="0 0 80 80">
<g class="background" stroke-width="3" fill="transparent">
<circle cx="40" cy="40" r="39" stroke="black" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(112.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(202.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(292.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(22.5, 40,40)" />
<circle cx="40" cy="40" r="44" stroke="transparent" stroke-width="7" />
</g>
</svg>
http://jsfiddle.net/r5HYK/1/
As you can see, there is the black circle with some "corners" added (dunno how to call that in English). But these "corners" are both outside and inside the circle, but I want to have them only inside. To see how it should look like, you can add the out-commented circle to the svg.
But this solution does not work for me since this svg should be included into a bigger svg file, where the circle to remove the outer "corners" would be visible itself.
So I am searching for something that removes this outer "corners" (maybe a filter?), but does not have any other effect.
Another solution would be a one-sided stroke, since the stroke is expanded to both sides at the moment, but I currently do not know whether this even exists.
Any suggestions?
A clipPath is what you want. You can just clip away everything outside the circle.
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="80" onclick='dispcoord(evt)' viewBox="0 0 80 80">
<defs>
<clipPath id="clip1">
<circle cx="40" cy="40" r="39" fill="black" />
</clipPath>
</defs>
<g class="background" stroke-width="3" fill="transparent" clip-path="url(#clip1)">
<circle cx="40" cy="40" r="39" stroke="black" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(112.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(202.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(292.5, 40,40)" />
<path d="M 0,40 A 37,37 0 0,1 12,12" stroke-width="11" stroke="black" transform="rotate(22.5, 40,40)" />
<circle cx="40" cy="40" r="44" stroke="transparent" stroke-width="7" />
</g>
</svg>