SVG: Masking a pattern on a <circle> - html

Trying to get a pinstripe-like effect ontop of a circle with a filled color, so that the pattern is masked on top of the circle. I'm not quite sure what I'm doing wrong, but my code seems close to what would be correct.
<?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" version="1.1" height="200" width="200">
<defs>
<pattern id="stripe" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10">
<g >
<line x1="10" y1="0" x2="0" y2="10" />
</g>
</pattern>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="ObjectBoundingBox">
<rect height="300" width="300" style="fill: url(#pinstripe);" />
</mask>
<style>
g {
mask: url(#mask);
stroke: black;
stroke-width: 1px;
stroke-linecap: butt;
stroke-rendering: crispEdges;
}
circle {
fill: green;
}
</style>
</defs>
<g>
<circle cx="100" cy="100" r="100" />
</g>
</svg>
You can look to this fiddle to effectively see nothing - to actually view the circle, remove the mask: url(#mask); style.
So I'm not quite sure what's wrong - I'm just trying to have a circle with a green fill and white stripes on top. Any help would be seriously appreciated!

I think you need to fix your "white" and "black" color because that's what's used in a mask.
Here's an example that works (of your code). Try switching the "white" and "black" colors in the "fill" and "stroke" attributes.
Here's my first example with a "rect":
<?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" version="1.1" height="200" width="200">
<defs>
<pattern id="pinstripe" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10">
<rect x="0" y="0" width="10" height="10" stroke="black" stroke-width="1" fill="white" />
</pattern>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="ObjectBoundingBox">
<rect x="0.5" y="0.2" height="300" width="300" style="fill: url(#pinstripe)" />
</mask>
<style>
g {
mask: url(#mask);
stroke: black;
stroke-width: 1px;
stroke-linecap: butt;
stroke-rendering: crispEdges;
}
circle {
fill: green;
}
</style>
</defs>
<g>
<circle cx="100" cy="100" r="100" />
</g>
</svg>
EDIT:
Here's another version using line (notice that I'm setting fill and stroke to "#ffffff" or "white" to make this mask:
​
<?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" version="1.1" height="200" width="200">
<defs>
<pattern id="pinstripe" patternUnits="userSpaceOnUse" x="0" y="0" width="10" height="10">
<line x1="10" y1="0" x2="0" y2="10" fill="#ffffff" stroke="#ffffff" />
</pattern>
<mask id="mask" maskUnits="objectBoundingBox" maskContentUnits="ObjectBoundingBox">
<rect x="0.5" y="0.2" height="300" width="300" style="fill: url(#pinstripe)" />
</mask>
<style>
g {
mask: url(#mask);
stroke: black;
stroke-width: 1px;
stroke-linecap: butt;
stroke-rendering: crispEdges;
}
circle {
fill: green;
}
</style>
</defs>
<g>
<circle cx="100" cy="100" r="100" />
</g>
</svg>​

Related

Rectangle SVG Masking over video tag

I am trying to create a Mask over video tag.
I have below svg element which has transparent text but I am looking to have a rectangle shape instead of text.
I have also tried with polygon to create a rectangle but seems its not working.
<polygon points="0 0,0 100,300 100,300 0" fill="orange" />
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 285 80" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%" >
<rect x="0" y="0" width="100%" height="100%" />
<text x="72" y="50">OCEAN</text>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" />
</svg>
svg {
width: 100%;
position:absolute;
top: 0;
left: 0; // needed for FF, Safari, Edge
height: 100%;
}
svg text {
font-family: Biko, sans-serif;
font-weight: 700;
text-transform: uppercase;
font-size: 38px;
}
svg rect {
fill: white;
}
svg > rect {
-webkit-mask: url(#mask);
mask: url(#mask);
-webkit-mask-mode: alpha;
mask-mode: alpha;
fill: black;
fill-opacity:0.8;
}
Was able to achieve using another rect element inside mask.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 285 80" preserveAspectRatio="xMidYMid slice">
<defs>
<mask id="mask" x="0" y="0" width="100%" height="100%" >
<rect id="svg-rect" x="0" y="0" width="100%" height="100%" />
<rect x="100" y="10" rx="5" ry="5" width="60" height="30"/>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" />
</svg>

SVG file mask not being loaded with <use>

Let's say I have an SVG file test.svg
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<symbol id="testsvg">
<mask id="mask3" x="0" y="0" width="100" height="100" >
<rect x="0" y="0" width="100" height="50"
style="stroke:none; fill: #ffffff"/>
<rect x="0" y="50" width="100" height="50"
style="stroke:none; fill: #666666"/>
</mask>
<rect x="1" y="1" width="100" height="100"
style="stroke: none; fill: #0000ff; mask: url(#mask3)"/>
</symbol>
</defs>
</svg>
If i try to use it like this in test.html
<svg>
<use href="test.svg#testsvg"/>
</svg>
The mask is not working I get a blue rectangle only. Doing an inspect element in firefox shows that the mask element is missing inside the shadow root. (Why ?)
The same thing as a direct inline SVG works just fine as expected, (I get two rectangles of different colors)
test2.html
<svg xmlns="http://www.w3.org/2000/svg">
<mask id="mask3" x="0" y="0" width="100" height="100" >
<rect x="0" y="0" width="100" height="50"
style="stroke:none; fill: #ffffff"/>
<rect x="0" y="50" width="100" height="50"
style="stroke:none; fill: #666666"/>
</mask>
<rect x="1" y="1" width="100" height="100"
style="stroke: none; fill: #0000ff; mask: url(#mask3)"/>
</svg>
Why is this happening?
Note To reproduce the above behavior security.fileuri.strict_origin_policy should be set to false in about:config in Firefox so that local files may be loaded

Keep svg pattern scaling when resizing svg-shape

I have a svg-pattern applied to a polygon. It's working fine.
When I set another size on the svg-polygon, I don't want to scale the pattern.
I've tried all combinations I can think of with viewBox, patternUnits and patternContentUnits. The goal is to make the polygon work responsibly e.g. scale with it's parent element. Can anyone point me in the right direction?
<svg width="1000" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
<svg width="500" fill="#ccc" viewBox="0 0 1440 60">
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" viewBox="0 0 900.4 600">
<!-- pattern code -->
</svg>
</pattern>
</defs>
<polygon points="0,0 1440,0 1440,20 0,60" x="0" y="0" stroke="#bbb" fill="url(#pattern)" />
</svg>
full example: https://codepen.io/anderssonola/pen/QqxKjJ
I solved temporarily by applying the pattern to a <rect>and then use css clip-pathto create the polygon and the pattern does not scale. I still would prefer to solve it with pure svg, since IE does not support the css clip-path.
.clip {
background: gray;
clip-path: polygon(0 0, 100% 0, 100% 30%, 0% 100%);
margin-bottom: 1em;
}
.clip.half {
width: 50%;
}
svg {
display: block;
height: 50px;
width: 100%
}
<div >
<svg>
<defs>
<pattern id="pattern" x="0" y="0" width="900" height="600" patternUnits="userSpaceOnUse" patternContentUnits="userSpaceOnUse">
<svg x="0" y="0" width="900.4" height="600" >
<!-- pattern code -->
</svg>
</pattern>
<rect width="100%" height="50" fill="url(#pattern)" id="pattern-md"/>
</defs>
</svg>
</div>
<div class="clip">
<svg>
<use href="#pattern-md"/>
</svg>
</div>
<div class="clip half" >
<svg>
<use href="#pattern-md" />
</svg>
</div>
Working example: https://codepen.io/anderssonola/pen/oGyBMj/
You could always scale the pattern and size the polygon appropriately e.g.
<polygon transform="scale(2)" points="0,0 720,0 720,10 0,30" stroke="#bbb" fill="url(#pattern)" />

Prevent arrow heads from being cropped

I'm trying to compose an arrow in SVG:
svg line {
stroke-width: 10px;
stroke: black;
}
svg polyline {
stroke: orange;
}
<figure>
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="40" height="300">
<defs>
<marker
id="start"
markerWidth="3"
markerHeight="3"
refX="0"
refY="1.5"
orient="auto"
>
<polyline points="1.5,0 0,1.5 1.5,3" fill="none" />
</marker>
<marker
id="end"
markerWidth="3"
markerHeight="3"
refX="1.5"
refY="1.5"
orient="auto"
>
<polyline points="0,0 1.5,1.5 0,3" fill="none" />
</marker>
</defs>
<line
x1="20" y1="50" x2="20" y2="250"
marker-start="url(#start)"
marker-end="url(#end)"
/>
</svg>
</figure>
As you can see in this scaled-up screen-shot, it kind of works:
Yet the looks differ a lot from my expectations:
Is it possible to see the complete arrow head and also get square corners?
From Details on how markers are rendered:
overflow="visible"
svg line {
stroke-width: 10px;
stroke: black;
}
svg polyline {
stroke: orange;
}
<figure>
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" width="40" height="300">
<defs>
<marker
id="start"
markerWidth="3"
markerHeight="3"
refX="0"
refY="1.5"
orient="auto"
overflow="visible"
>
<polyline points="1.5,0 0,1.5 1.5,3" fill="none" />
</marker>
<marker
id="end"
markerWidth="3"
markerHeight="3"
refX="1.5"
refY="1.5"
orient="auto"
overflow="visible"
>
<polyline points="0,0 1.5,1.5 0,3" fill="none" />
</marker>
</defs>
<line
x1="20" y1="50" x2="20" y2="250"
marker-start="url(#start)"
marker-end="url(#end)"
/>
</svg>
</figure>

SVG code efficiency

So, I've been asked to create a static SVG file, and have been told to use <defs> and <use> to make it more efficient.
I understand there is code repetition but I'm not sure how to go about reducing what I have and still being able to have the same output.
Here is the code:
<!DOCTYPE html>
<html>
<body>
<center>
<h1>Static SVG</h1>
<svg width="200" height="200">
<!--transforming the group of shapes so that the origin is at the center of the svg image-->
<g transform="translate(100,100)">
<!--This is effectively the background-->
<rect x="-100" y="-100" width="200" height="200" style="fill:grey" />
<!--Inner rounded rectangle-->
<rect x="-40" y="-40" rx="5" ry="5" width="80" height="80" style="fill:black" />
<!--Four inner-most short arrows-->
<polygon points="0,-60 10,-50 0,-55 -10,-50" style="fill:black;stroke:lime;stroke-width:1" />
<polygon points="60,0 50,-10 55,0 50,10" style="fill:black;stroke:lime;stroke-width:1" />
<polygon points="-60,0 -50,10 -55,0 -50,-10" style="fill:black;stroke:lime;stroke-width:1" />
<polygon points="0,60 10,50 0,55 -10,50" style="fill:black;stroke:lime;stroke-width:1" />
<!--Middle short arrows-->
<polygon points="0,-80 10,-70 0,-75 -10,-70" style="fill:red;stroke:black;stroke-width:1" />
<polygon points="80,0 70,-10 75,0 70,10" style="fill:red;stroke:black;stroke-width:1" />
<polygon points="-80,0 -70,10 -75,0 -70,-10" style="fill:red;stroke:black;stroke-width:1" />
<polygon points="0,80 10,70 0,75 -10,70" style="fill:red;stroke:black;stroke-width:1" />
<!--Outer-most short arrows-->
<polygon points="0,-100 10,-90 0,-95 -10,-90" style="fill:lime;stroke:black;stroke-width:1" />
<polygon points="100,0 90,-10 95,0 90,10" style="fill:lime;stroke:black;stroke-width:1" />
<polygon points="-100,0 -90,10 -95,0 -90,-10" style="fill:lime;stroke:black;stroke-width:1" />
<polygon points="0,100 10,90 0,95 -10,90" style="fill:lime;stroke:black;stroke-width:1" />
<!--Longer Arros positioned diagonally from origin-->
<polygon points="40,50 50,50 50,40 60,60" style="fill:yellow;stroke:black;stroke-width:1" />
<polygon points="-50,-40 -50,-50 -40,-50 -60,-60" style="fill:yellow;stroke:black;stroke-width:1" />
<polygon points="50,-40 50,-50 40,-50 60,-60" style="fill:yellow;stroke:black;stroke-width:1" />
<polygon points="-50,40 -50,50 -40,50 -60,60" style="fill:yellow;stroke:black;stroke-width:1" />
<!--The elliptical shape in the centre of the rounded Square-->
<ellipse cx="0" cy="0" rx="20" ry="40" style="fill:white" />
</g>
</svg>
</center>
</body>
</html>
You're drawing the same polygons for the most part albeit rotated and positioned differently.
Along with moving their styles into a class, you can use defs and use like this:
<defs>
<!-- Define your shape here once -->
<polygon points="0,-60 10,-50 0,-55 -10,-50"
class="inner-arrow" id="inner-arrow" />
</defs>
<!-- Reuse multiple times
with the rotation (and translation if needed) handled by transform -->
<use xlink:href="#inner-arrow" />
<use xlink:href="#inner-arrow" transform="rotate(90)" />
<use xlink:href="#inner-arrow" transform="rotate(180)" />
<use xlink:href="#inner-arrow" transform="rotate(270)" />
Here's a DEMO that has the first inner arrows' code updated.
You can use and reuse symbols, which can have individual viewBoxes and be rotated and scaled like groups. The units in the symbols are proportional to the viewBox.
Here is a JSFiddle with your arrows coded and grouped using symbols:
<svg width="200" height="200" viewBox="0 0 200 200">
<defs>
<symbol id="sm_arrow" viewBox="0 0 20 10">
<polygon points="10,0 20,10 10,5 0,10" />
</symbol>
<symbol id="lg_arrow" viewBox="0 0 200 200">
<polygon points="0,10 10,10 10,0 20,20" />
</symbol>
<symbol id="triple_arrow" viewBox="0 5 200 10">
<use xlink:href="#sm_arrow"/>
<use xlink:href="#sm_arrow" transform="translate(0,20)" />
<use xlink:href="#sm_arrow" transform="translate(0,40)" />
</symbol>
<symbol id="arrows" viewBox="0 0 200 200">
<g id="small_arrows">
<use xlink:href="#triple_arrow" transform="translate(0,-90)" />
<use xlink:href="#triple_arrow" transform="translate(290,0) rotate(90)" />
<use xlink:href="#triple_arrow" transform="translate(200,290) rotate(180)" />
<use xlink:href="#triple_arrow" transform="translate(-90,200) rotate(-90)" />
</g>
<g id="long_arrows" transform="translate(60,60)">
<use xlink:href="#lg_arrow" transform="translate(80,80)" />
<use xlink:href="#lg_arrow" transform="translate(0,80) rotate(90)" />
<use xlink:href="#lg_arrow" transform="rotate(180)" />
<use xlink:href="#lg_arrow" transform="translate(80,0) rotate(-90)" />
</g>
</symbol>
<g id="background">
<rect width="200" height="200"/>
<rect x="60" y="60" rx="5" ry="5" width="80" height="80"/>
<ellipse cx="100" cy="100" rx="20" ry="40"/>
</g>
</defs>
<use xlink:href="#background"/>
<use xlink:href="#arrows"/>
</svg>
The styles were transferred to a CSS block or file:
polygon {
stroke-width: 1;
}
#triple_arrow use:nth-child(1) {
fill:black;
stroke:lime;
}
#triple_arrow use:nth-child(2) {
fill: red;
stroke: black;
}
#triple_arrow use:nth-child(3) {
fill: lime;
stroke: black;
}
#lg_arrow {
fill:yellow;
stroke:black;
}
#background rect:nth-child(1) {
fill:grey;
}
#background rect:nth-child(2) {
fill:black;
}
#background ellipse {
fill:white;
}