SVG stroke only in one direction - 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>

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>

How to draw circles in SVG like if they were a single shape?

I need to draw an indeterminate number of circles in SVG like if they were a single shape. Making all circles have the same fill color does not work because I need those circles to have a filter applied in them, like in the picture, and as you can see the overlapping areas are in a different color.
<pattern
id="diagonalHatch"
patternUnits="userSpaceOnUse"
width="1"
height="3"
patternTransform="rotate(-45 2 2)">
<path
d="M -1,2 l 6,0"
[attr.stroke]="'#' + color"
stroke-width=".5"
/>
</pattern>
<ng-container *ngFor="let cone of cones, index as i">
<svg:circle
fill="url(#diagonalHatch)"
[attr.cx]="scaleX * (offset + cone.cX)"
[attr.cy]="cone.cY"
[attr.r]="scaleX * radius"
/>
</ng-container>
Result I am getting
Result I need
I suppose that what you have right now is something like this where due to the semitransparency of the pattern you can see the overlapped parts as darker:
<svg viewBox="0 0 100 50" width="400">
<pattern
id="diagonalHatch"
patternUnits="userSpaceOnUse"
width="1"
height="3"
patternTransform="rotate(-45 2 2)">
<path
d="M -1,2 l 6,0"
stroke="rgba(0, 100, 100, .3)"
stroke-width="0.5"
/>
</pattern>
<g>
<circle fill="url(#diagonalHatch)" r="20" cx="25" cy="25"/>
<circle fill="url(#diagonalHatch)" r="20" cx="50" cy="25"/>
<circle fill="url(#diagonalHatch)" r="20" cx="75" cy="25"/>
</g>
</svg>
As a possible solution you could use the circles as a clipping path and clip a rectangle the size of the svg canvas like so:
<svg viewBox="0 0 100 50" width="400">
<pattern
id="diagonalHatch"
patternUnits="userSpaceOnUse"
width="1"
height="3"
patternTransform="rotate(-45 2 2)">
<path
d="M -1,2 l 6,0"
stroke="rgba(0, 100, 100, .3)"
stroke-width="0.5"
/>
</pattern>
<clipPath id="c">
<circle r="20" cx="25" cy="25"/>
<circle r="20" cx="50" cy="25"/>
<circle r="20" cx="75" cy="25"/>
</clipPath>
<rect fill="url(#diagonalHatch)" width="100" height="50" clip-path="url(#c)"/>
</svg>

Make a path get cut off by a circle

Is there a way to cut off a path when it is outside of a circle?
<svg width="100" height="100">
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" />
</svg>
Is it possible to make that line stay inside the circle (and not be visible off of the circle) without changing the d="M200 175 L696 880" in the path?
You can use a clipPath to prevent things drawing outside another shape.
<svg width="100" height="100">
<clipPath id="clip">
<circle cx="50" cy="50" r="50" fill="red" />
</clipPath>
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" clip-path="url(#clip)"/>
</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: fill pattern with overlapping shapes

In SVG, how can I fill portions of overlapping shapes, like this example(not drawn with SVG)? If I omit the fill pattern from a shape, I also want the pattern removed from other shapes that it overlaps. After that, yet more shapes may overlap again and re-draw the pattern. I'm generating this SVG from code, and for each shape, I'll know in the code whether it's supposed to add or subtract the fill pattern.
Here's my SVG so far. It draws the shapes, and defines the fill pattern but doesn't use it.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="640" height="480" viewBox="0 0 640 480">
<defs>
<marker id="endArrowGreen" viewBox="0 0 10 10" refX="1" refY="5" markerUnits="strokeWidth" orient="auto" markerWidth="5" markerHeight="4">
<polyline points="0,0 10,5 0,10 1,5" fill="#00CC00" stroke="#00CC00"/>
</marker>
<marker id="startArrowGreen" viewBox="0 0 10 10" refX="1" refY="5" markerUnits="strokeWidth" orient="auto" markerWidth="5" markerHeight="4">
<polyline points="10,0 0,5 10,10 9,5" fill="#00CC00" stroke="#00CC00"/>
</marker>
<marker id="endArrowBlue" viewBox="0 0 10 10" refX="1" refY="5" markerUnits="strokeWidth" orient="auto" markerWidth="5" markerHeight="4">
<polyline points="0,0 10,5 0,10 1,5" fill="#0000CC" stroke="#0000CC"/>
</marker>
<marker id="startArrowBlue" viewBox="0 0 10 10" refX="1" refY="5" markerUnits="strokeWidth" orient="auto" markerWidth="5" markerHeight="4">
<polyline points="10,0 0,5 10,10 9,5" fill="#0000CC" stroke="#0000CC"/>
</marker>
<pattern id="Crosshatch" patternUnits="userSpaceOnUse"
x="0" y="0" width="10" height="10"
viewBox="0 0 10 10" >
<path d="M 0 10 L 10 0" stroke-width="1" stroke="blue" />
</pattern>
</defs>
<g>
<line x1="7.78888" y1="6.08366" x2="319.087" y2="6.08366" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(319.087 6.08366) rotate(0)"/>
<line x1="319.087" y1="6.08366" x2="630.385" y2="6.08366" stroke-width="1" stroke="#0000CC" />
<line x1="630.385" y1="6.08366" x2="630.385" y2="469.354" stroke-width="1" stroke="#0000CC" />
<line x1="630.385" y1="469.354" x2="7.78888" y2="469.354" stroke-width="1" stroke="#0000CC" />
<line x1="7.78888" y1="469.354" x2="7.78888" y2="237.719" stroke-width="1" stroke="#0000CC" />
<line x1="7.78888" y1="6.08366" x2="7.78888" y2="237.719" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(7.78888 237.719) rotate(90)"/>
</g>
<circle cx="298.914" cy="237.087" r="218.732" stroke-width="1" stroke="#0000CC" fill="none"/>
<circle cx="262.395" cy="238.913" r="100" stroke-width="1" stroke="#0000CC" fill="none"/>
<circle cx="438.601" cy="236.175" r="129.523" stroke-width="1" stroke="#0000CC" fill="none"/>
<g>
<line x1="99.913" y1="248.646" x2="302.566" y2="248.646" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(302.566 248.646) rotate(0)"/>
<line x1="302.566" y1="248.646" x2="505.22" y2="248.646" stroke-width="1" stroke="#0000CC" />
<line x1="505.22" y1="248.646" x2="505.22" y2="291.232" stroke-width="1" stroke="#0000CC" />
<line x1="505.22" y1="291.232" x2="99.913" y2="291.232" stroke-width="1" stroke="#0000CC" />
<line x1="99.913" y1="291.232" x2="99.913" y2="269.939" stroke-width="1" stroke="#0000CC" />
<line x1="99.913" y1="248.646" x2="99.913" y2="269.939" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(99.913 269.939) rotate(90)"/>
</g>
<g>
<line x1="114.521" y1="181.118" x2="303.023" y2="181.118" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(303.023 181.118) rotate(0)"/>
<line x1="303.023" y1="181.118" x2="491.525" y2="181.118" stroke-width="1" stroke="#0000CC" />
<line x1="491.525" y1="181.118" x2="491.525" y2="212.753" stroke-width="1" stroke="#0000CC" />
<line x1="491.525" y1="212.753" x2="114.521" y2="212.753" stroke-width="1" stroke="#0000CC" />
<line x1="114.521" y1="212.753" x2="114.521" y2="196.935" stroke-width="1" stroke="#0000CC" />
<line x1="114.521" y1="181.118" x2="114.521" y2="196.935" stroke-width="1" stroke="#0000CC" />
<polyline points="0,0 -6,-3 -5,0 -6,3" fill="#0000CC" stroke="#0000CC" transform="translate(114.521 196.935) rotate(90)"/>
</g>
</svg>
You might want to try the "fill-rule" attribute see http://www.w3.org/TR/SVG/painting.html

Resources