I have the following svg code:
<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<defs>
<mask id="mask" x="0" y="0" width="100" height="100">
<rect x="0" y="0" width="100" height="100" fill="rgb(20, 182, 197)" fill-opacity="100%"></rect>
<circle cx="50" cy="50" r="37.5"></circle>
</mask>
</defs>
<rect x="0" y="0" width="100" height="100" mask="url(#mask)" fill="rgb(20, 182, 197)" ></rect>
</svg>
It basically creates a rectangle with a cutout circle, but the part with the non cutout part is partially transparent.
How do i fix this?
With masks, the transparency is determined by the brightness. You are setting the rectangle's color to rgb(20, 182, 197), which has a 43% luminescence value, so you get 43% transparency. If you need the outer rectangle to be opaque, then you have to set its color to have 100% brightness (i.e. white).
So, change
<rect x="0" y="0" width="100" height="100" fill="rgb(20, 182, 197)" fill-opacity="100%">
to
<rect x="0" y="0" width="100" height="100" fill="white">
Related
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
this code
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<ellipse cx="50%" cy="50%" rx="100" ry="150" stroke="red" stroke-width="10"/>
</mask>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
</svg>
return this as a result
I want to have this same result, but with a red border instead of gray in the ellipse and that this is not affected by the opacity of the rect.
I also need the inside of the ellipse to be transparent (not white) and that it is not affected by the opacity of the rect.
Is this possible?
If you are asking whether you can include a red ellipse as part of your mask, then the answer is no. Any colours in a mask are converted to alpha values.
If you want a red ellipse around your "hole", then you need to add it as a separate element on top of the rect.
body {
background-color: linen;
}
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<defs>
<!-- pull ellipse out as a reusable shape. Used by mask and for red border. -->
<ellipse id="one" cx="50%" cy="50%" rx="100" ry="150"/>
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<use xlink:href="#one" fill="black"/>
</mask>
</defs>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
<use xlink:href="#one" fill="none" stroke="red" stroke-width="10"/>
</svg>
for set order you can use tag use with the attribute xlink:href for more detail see this How to use z-index in svg elements?
add fill="#fff" tag and id="one" to ellipse and draw it again with <use xlink:href="#one"/>
<svg viewbox="0 0 100% 100%" width="100%" height="400px">
<mask id="mask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="#fff"/>
<ellipse id="one" cx="50%" cy="50%" rx="100" ry="150" stroke="red" fill="#fff" stroke-width="10"/>
</mask>
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill-opacity="0.7"/>
<use xlink:href="#one"/>
</svg>
I've used this way (you could see the codepen) to display image background in my logo letters. Now, i want to display a video instead of the image.
https://codepen.io/irawachaloco/pen/GJKLzy
<svg class='crop-shapes'>
<defs>
<pattern id="img1" patternUnits="userSpaceOnUse" width="100%" height="650">
<image class='twombly' xlink:href="http://gastv.mx/wp-content/uploads/2014/05/jumex.jpg" x="-30" y="-30"
width="380" height="267" />
</pattern>
</defs>
<circle class='circ' cx="50" cy="50" r="50" fill="url(#img1)" filter="url(#sparklin)" onmouseover="evt.target.setAttribute('opacity', '0.5');"
13
onmouseout="evt.target.setAttribute('opacity','1)');"/>
<rect x="110" y="0" width="100" height="100" stroke="black" fill="url(#img1)" filter="url(#sparklin)"/>
<polygon x="10" points="270,0 220,100 320,100" fill="url(#img1)" filter="url(#sparklin)"/>
</svg>
Any idea or example ? I'm a noob with svg practices..
Thanks a lot !
I've read a bit of the spec for the SVG mask element but the sections on maskUnits and maskContentUnits aren't clear to me, and also how they affect each other isn't clear to me.
From the spec:
maskUnits = 'userSpaceOnUse': x, y, width and height represent values in the current user coordinate system in place at the time when the mask element is referenced.
maskUnits = 'boundingBox': x, y, width and height represent fractions or percentages of the object bounding box of the element to which the mask is applied.
maskContentUnits = 'userSpaceOnUse': The user coordinate system for the contents of the mask element is the current user coordinate system in place at the time when the mask element is referenced.
maskContentUnits = 'boundingBox': The coordinate system has its origin at the top left corner of the bounding box of the element to which the clipping path applies to and the same width and height of this bounding box.
I've tried editing the maskUnits example and maskContentUnits example on MDN but whenever I change anything something unexpected happens, like the whole element disappears or the mask doesn't seem to be applied.
The snippet below is a sandbox with a few examples of the confusing behavior. I'd expect all of the squares to look different but there are 2 pairs each that are identical, and one of the pairs look like no mask was applied at all:
* {
margin: 0;
padding: 0;
}
body {
padding: 20px 0 0 20px;
}
.hidden {
width: 0;
height: 0;
margin: 0;
}
svg {
width: 100px;
height: 100px;
margin: 0 20px 20px 0;
display: block;
}
p {
margin-bottom: 10px;
font-family: monospace;
}
<!-- mask definitions -->
<svg viewBox="0 0 100 100" class="hidden">
<mask
id="usou-usou"
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="usou-obb"
maskUnits="userSpaceOnUse"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="obb-usou"
maskUnits="objectBoundingBox"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="obb-obb"
maskUnits="objectBoundingBox"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-usou)"
/>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-obb)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-usou)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-obb)"
/>
</svg>
We know what units are in ordinary life, there are inches, miles, kilometers etc.
One inch is not the same as one kilometre. If you draw a tiny picture, one inch across and you put a frame round it 2 inches across, the picture itself won't change if we make the frame 2 kilometres across. Equally, changing the picture size doesn't change how much is visible inside the picture frame unless the frame is too small for the picture.
maskUnits affect the units of the picture (mask) frame, maskContentUnits affect the units of the picture (mask).
objectBoundingBox units are defined such that 0 is the left side of the masked shape and 1 is the right side.
userSpaceOnUse units use the same co-ordinate system as the masked shape itself. If you mask a rect which extends from 50-100 then your mask ought to cover that area too if you want to mask the entire rect.
If you draw a circle with a radius of 100 kilometres centred 100 kilometres from the origin in both directions, then look at a square 1 millimetre across that starts at the origin, that square will have nothing drawn on it as everything is drawn outside that area.
We're masking
<rect x="0" y="0" width="100" height="100"/>
So our mask's x, y, width and height i.e.
<mask maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"/>
need to cover the same area (or more) if we want to mask that shape and they do.
If we had maskUnits="objectBoundingBox" we'd need
<mask maskUnits="objectBoundingBox" x="0" y="0" width="1" height="1"/>
Using 100 for the width and height would make the mask 100 times the size it needs to be but other than wasting lots of memory, it has no visible effect.
maskContentUnits work the same for the mask's content i.e.
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
Either they need to be 0..1 for objectBoundingBox or 0..100 for the shape. Since they are far too big for objectBoundingBox the mask is all one colour as the shapes are outside the area you can see i.e. the area over the shape.
<!-- mask definitions -->
<svg viewBox="0 0 100 100" class="hidden">
<mask
id="usou-usou"
maskUnits="userSpaceOnUse"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<mask
id="usou-obb"
maskUnits="userSpaceOnUse"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="100"
height="100"
>
<rect x="0" y="0" width="1" height="1" fill="white" />
<!-- if we wanted the same mask as above it would be r="0.25" -->
<circle cx=".5" cy=".5" r=".1" fill="black" />
</mask>
<!-- have the mask cover only the top left quarter of the shape -->
<mask
id="obb-usou"
maskUnits="objectBoundingBox"
maskContentUnits="userSpaceOnUse"
x="0"
y="0"
width="0.5"
height="0.5"
>
<rect x="0" y="0" width="100" height="100" fill="white" />
<circle cx="50" cy="50" r="25" fill="black" />
</mask>
<!-- have the mask cover only the top left quarter of the shape -->
<mask
id="obb-obb"
maskUnits="objectBoundingBox"
maskContentUnits="objectBoundingBox"
x="0"
y="0"
width="0.5"
height="0.5"
>
<rect x="0" y="0" width="1" height="1" fill="white" />
<!-- if we wanted the same mask as above it would be r="0.25" -->
<circle cx=".5" cy=".5" r=".1" fill="black" />
</mask>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-usou)"
/>
</svg>
<p>maskUnits = userSpaceOnUse &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#usou-obb)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = userSpaceOnUse</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-usou)"
/>
</svg>
<p>maskUnits = objectBoundingBox &<br> maskContentUnits = objectBoundingBox</p>
<svg viewBox="0 0 100 100">
<rect
x="0"
y="0"
width="100"
height="100"
mask="url(#obb-obb)"
/>
</svg>
I'm trying to display an image in an svg circle in the context of an html page with the following lines :
<html>
<head>
</head>
<body>
<svg width="260" height="120">
<defs>
<pattern id="Triangle"
width="10" height="10"
patternUnits="userSpaceOnUse">
<polygon points="5,0 10,10 0,10"/>
</pattern>
<pattern id=Img"
width="100" height="100"
patternUnits="userSpaceOnUse">
<image x="0" y="0"
width="100%" height="100%"
xlink:href="corruscant.jpg"></image>
</pattern>
</defs>
<circle cx="60" cy="60" r="60"
fill="url(#Img)"
stroke="red"/>
<circle cx="200" cy="60" r="60"
fill="url(#Triangle)"
stroke="red"/>
</svg>
</body>
</html>
This 'should' work according to what I read on many documentations/examples/posts such as :
Add a background image (.png) to a SVG circle shape
SVG image inside circle
http://jsfiddle.net/UI_Designer/njr4fdhq/2/
But it doesn't. Triangles appear in the second circle, so svg structure is ok I guess..
I've tried to copy/paste the jsfiddle example but the landscape does not show itself.
I'm looking for elements that my naïve approach has not taken in account.
Thanks
<svg width="260" height="120">
<defs>
<pattern id="Triangle" width="10" height="10" patternUnits="userSpaceOnUse">
<polygon points="5,0 10,10 0,10" />
</pattern>
<pattern id="Img" width="100" height="100" patternUnits="userSpaceOnUse">
<image x="0" y="0" width="100%" height="100%" xlink:href="https://upload.wikimedia.org/wikipedia/commons/4/46/A_Meat_Stall_with_the_Holy_Family_Giving_Alms_-_Pieter_Aertsen_-_Google_Cultural_Institute.jpg"></image>
</pattern>
</defs>
<circle cx="60" cy="60" r="60" fill="url(#Img)" stroke="red" />
<circle cx="200" cy="60" r="60" fill="url(#Triangle)" stroke="red" />
</svg>