Alpha Transparent Gradient in Inline SVG Defs Element - svg

I have this CODEPEN and here are my issues:
I am not understanding why the gradient I applied and referenced as my mask fill like so, doesn't render as it should. It should go from fully opaque to fully transparent. For the gradient I am using: http://angrytools.com/gradient/?0_800080,100_450045&0_0,100_100&l_180:
<mask id="myMask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="url(#grad1)" />
</mask>
In addition I don't understand why if I remove the fill="blue" attribute from my use element like so:
<use xlink:href="#myText" mask="url(#myMask)" />
The text appears black as if no gradient was applied. The gradient I defined is purple..
Thanks!

if you just want to apply your gradient to your text, there is no need to use masks, because gradients support the stop-opacity property.
<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px">
<defs>
<linearGradient id="lgrad" x1="100%" y1="50%" x2="0%" y2="50%">
<stop offset="0%" style="stop-color:rgb(128,0,128);stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(69,0,69);stop-opacity:1" />
</linearGradient>
<text x="100" y="120" text-anchor="middle" id="myText" font-size="50">Hello</text>
</defs>
<use xlink:href="#myText" fill="url(#lgrad)" />
</svg>
you only need masks if you want to seperate the opacity from your fills:
<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px">
<defs>
<linearGradient id="lgrad" x1="100%" y1="50%" x2="0%" y2="50%">
<stop offset="0" stop-color="black" />
<stop offset="1" stop-color="white" />
</linearGradient>
<mask id="myMask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="100%" height="100%" fill="url(#lgrad)" />
</mask>
<text x="100" y="120" text-anchor="middle" id="myText" font-size="50">Hello</text>
</defs>
<g mask="url(#myMask)">
<use xlink:href=" #myText" transform="translate(0,-50) " fill="red " />
<use xlink:href="#myText" transform="translate(0,0)" fill="green" />
<use xlink:href="#myText" transform="translate(0,50)" fill="blue" />
</g>
</svg>
masks turn colors into opacity information. going from black(totally transparent) to white (totally opaque)
<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="200px">
<defs>
<mask id="myMask" x="0" y="0" width="100%" height="100%">
<rect x="0" y="0" width="50%" height="50%" fill="white" />
<rect x="50%" y="0" width="50%" height="50%" fill="#333" />
<rect x="0%" y="50%" width="50%" height="50%" fill="#aaa" />
<rect x="50%" y="50%" width="50%" height="50%" fill="white" />
<circle cx="50%" cy="50%" r="15%" fill="black" />
</mask>
<text x="100" y="120" text-anchor="middle" id="myText" font-size="50">Hello</text>
</defs>
<rect x="0" y="0" width="100%" height="100%" fill="beige" />
<g mask="url(#myMask)">
<use xlink:href="#myText" transform="translate(0,-50)" fill="red" />
<use xlink:href="#myText" transform="translate(0,0)" fill="green" />
<use xlink:href="#myText" transform="translate(0,50)" fill="blue" />
</g>
</svg>

Related

Is it possible to center align <rect>'s inside a <g> for SVG?

Is it possible to vertically center align all the rects inside a tag without having to adjust the y attributes on <rect>? (see snippet for example)
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" preserveAspectRatio="none" width="100%" height="100%">
<g fill="black">
<rect x="10" y="1" width="6" height="5" />
<rect x="20" y="1" width="6" height="10" />
<rect x="30" y="1" width="6" height="20" />
<rect x="40" y="1" width="6" height="5" />
<rect x="50" y="1" width="6" height="15" />
</g>
</svg>
<h3>desired result</h3>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" preserveAspectRatio="none" width="100%" height="100%">
<g fill="black">
<rect x="10" y="8" width="6" height="5" />
<rect x="20" y="6" width="6" height="10" />
<rect x="30" y="1" width="6" height="20" />
<rect x="40" y="8" width="6" height="5" />
<rect x="50" y="4" width="6" height="15" />
</g>
</svg>
No, it's not possible to center align <rect> elements.
But it is possible to center-align <line> elements and give them a stroke-width (note the viewBox is vertically centered around 0):
<svg viewBox="0 -19 225 38" width="100%" height="100%">
<g stroke="black">
<line x1="10" x2="16" stroke-width="5" />
<line x1="20" x2="26" stroke-width="10" />
<line x1="30" x2="36" stroke-width="20" />
<line x1="40" x2="46" stroke-width="5" />
<line x1="50" x2="56" stroke-width="15" />
</g>
</svg>
You could also achieve vertically centered <rect> elements by setting a transform: translate(0, -50%) css rule.
This approach also requires a transform-box: fill-box; (or content-box) property.
All <rect>elements get a y="50%" attribute to start at the vertical center of the svg viewBox.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3/org/1999/xlink" viewBox="0 0 225 38" width="100%" height="100%" style="border:1px solid #ccc">
<style>
rect {
transform: translate(0, -50%);
transform-origin: center;
transform-box: fill-box;
}
</style>
<g fill="black" >
<rect x="10" y="50%" width="6" height="5" />
<rect x="20" y="50%" width="6" height="10" />
<rect x="30" y="50%" width="6" height="20" />
<rect x="40" y="50%" width="6" height="5" />
<rect x="50" y="50%" width="6" height="15" />
</g>
</svg>
Browser support for transform-box is decent. (See caniuse).
However, if you need legacy browser (e.g. ie11) support, #ccprog's answer is a more robust solution.

How to graph a political coordinates graph

I'm trying to program a graph like this one:
I tried with SVG, but it's not very good since I had to use 2 different rectangles and didn't manage to get only the 4 edges to be rounded.
Here's my code:
<svg width="400" height="250">
<defs>
<linearGradient id="solids" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
<stop offset="50%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
<stop offset="50%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,255,0);stop-opacity:1" />
</linearGradient>
<linearGradient id="solids2" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="50%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
<stop offset="50%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</linearGradient>
</defs>
<text x="135" y="12" style="fill:black;">Conservadorismo
<tspan x="150" y="240">Liberalismo</tspan>
<tspan x="20" y="125">Esquerda</tspan>
<tspan x="305" y="125">Direita</tspan>
</text>
<rect x="100" y="20" rx="20" ry="20" width="200" height="100" style="fill:url(#solids); opacity:0.76" />
<rect x="100" y="120" rx="20" ry="20" width="200" height="100" style="fill:url(#solids2); opacity:0.76" />
<line x1="100" y1="120" x2="300" y2="120" style="stroke:black;stroke-width:2" />
<line x1="200" y1="20" x2="200" y2="220" style="stroke:black;stroke-width:2" />
</svg>
What should I do to fix it or do it better?
I would use ordinary <rect> objects without rounded corners, and apply a clipPath to the whole drawing to round off the corners.
Here's a simple example:
<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<clipPath id="roundRect">
<rect x="10" y="10" rx="20" ry="20" width="380" height="380"/>
</clipPath>
</defs>
<g clip-path="url(#roundRect)">
<rect fill="#0a0" stroke="none" x="10" y="10" width="190" height="190"/>
<rect fill="#f00" stroke="none" x="200" y="10" width="190" height="190"/>
<rect fill="#0bf" stroke="none" x="10" y="200" width="190" height="190"/>
<rect fill="#fd0" stroke="none" x="200" y="200" width="190" height="190"/>
</g>
</svg>

svg groups and fill inheritance

My goal is to have the first group of 3 squares be blue and the next group of 3 squares be red. To minimize code, I want to take advantage of grouping in SVG. All the rectangles remain blue. I have tried inline styling on the second group element and on the use element, but that doesn't solve the problem. Thank you for your assistance.. Here's the code:
<svg width="1000" height="800"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
.blue {fill:blue;}
.red {fill:red;}
</style>
<g id="g1" class="blue">
<rect x="0" y="0" width="100" height="100" />
<rect x="0" y="105" width="100" height="100" />
<rect x="0" y="210" width="100" height="100" />
</g>
<g class="red">
<use xlink:href="#g1" transform="translate(0,315)" />
</g>
Here are changes from above that now have it working:
<g class="blue">
<g id="g1">
<rect x="0" y="0" width="100" height="100" />
<rect x="0" y="105" width="100" height="100" />
<rect x="0" y="210" width="100" height="100" />
</g>
</g>
<g class="red" transform="translate(0,315)">
<use xlink:href="#g1" />
<!-- <g id="g1">
<rect x="0" y="0" width="100" height="100" />
<rect x="0" y="105" width="100" height="100" />
<rect x="0" y="210" width="100" height="100" />
</g> -->
</g>
... I commented out some of the old svg as well.
Here's the solution in a clearer form (some of the commented code above, actually came from further experimenting).
<svg width="1000" height="800"
xmlns="http://www.w3.org/2000/svg" version="1.1"
xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
.blue {fill:blue;}
.red {fill:red;}
</style>
<g class="blue">
<g id="g1">
<rect x="0" y="0" width="100" height="100" />
<rect x="0" y="105" width="100" height="100" />
<rect x="0" y="210" width="100" height="100" />
</g>
</g>
<g class="red" transform="translate(0,315)">
<use xlink:href="#g1" />
</g>
Looks like styling needs to be done at a level above a group in my case and that the as Robert pointed out will retrieve the previous group as written.

How to create a symbol from another symbol using viewBox properly?

The following SVG does not display as I expect it to.
The brief description/ intent is:
I create a symbol which is a large square comprised of smaller rectangles
I then create "slices" of this large square in smaller symbols using viewBox and preserveAspectRatio
I then display some of these symbols with <use>
The problem is that the "sliced" symbols which touch the right or bottom edge are not full sized, and instead appear as small slivers.
How can I fix this?
What it looks like (click for full image):
Interestingly, if I change the main <symbol> to a <g> instead, I get a very different looking result, which suffers from the same problem
What it should look like (click for full image):
Files available at this gist,
also copied below for your convenience.
This illustrates the problem:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="box">
<!--top left-->
<rect x="0" y="0" height="100" width="100"
style="fill:#0000ff" />
<!--top middle-->
<rect x="100" y="0" height="100" width="300"
style="fill:#008888" />
<!--top right-->
<rect x="400" y="0" height="100" width="100"
style="fill:#00ff00" />
<!--middle left-->
<rect x="0" y="100" height="300" width="100"
style="fill:#888800" />
<!--middle middle-->
<rect x="100" y="100" height="300" width="300"
style="fill:#2a2a2a" />
<!--middle right-->
<rect x="400" y="100" height="300" width="100"
style="fill:#ff0000" />
<!--bottom left-->
<rect x="0" y="400" height="100" width="100"
style="fill:#000000" />
<!--bottom middle-->
<rect x="100" y="400" height="100" width="300"
style="fill:#ff0088" />
<!--bottom right-->
<rect x="400" y="400" height="100" width="100"
style="fill:#8800ff" />
</symbol>
<symbol id="box-top-left" viewBox="0 0 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-middle" viewBox="100 0 400 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-right" viewBox="400 0 500 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-left" viewBox="0 100 100 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-middle" viewBox="100 100 400 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-right" viewBox="400 100 500 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-left" viewBox="0 400 100 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-middle" viewBox="100 400 400 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-right" viewBox="400 400 500 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
</defs>
<use xlink:href="#box-top-right" x="0" y="0" height="100" width="100" />
<use xlink:href="#box-top-middle" x="100" y="0" height="100" width="300" />
<use xlink:href="#box-top-middle" x="400" y="0" height="100" width="100" />
<use xlink:href="#box-middle-right" x="0" y="100" height="300" width="100" />
<use xlink:href="#box-middle-middle" x="100" y="100" height="300" width="300" />
<use xlink:href="#box-middle-middle" x="400" y="100" height="300" width="100" />
<use xlink:href="#box-bottom-right" x="0" y="400" height="100" width="100" />
<use xlink:href="#box-bottom-middle" x="100" y="400" height="100" width="300" />
<use xlink:href="#box-bottom-middle" x="400" y="400" height="100" width="100" />
</svg>
This is what it should look like:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<symbol id="box">
<!--top left-->
<rect x="0" y="0" height="100" width="100"
style="fill:#0000ff" />
<!--top middle-->
<rect x="100" y="0" height="100" width="300"
style="fill:#008888" />
<!--top right-->
<rect x="400" y="0" height="100" width="100"
style="fill:#00ff00" />
<!--middle left-->
<rect x="0" y="100" height="300" width="100"
style="fill:#888800" />
<!--middle middle-->
<rect x="100" y="100" height="300" width="300"
style="fill:#2a2a2a" />
<!--middle right-->
<rect x="400" y="100" height="300" width="100"
style="fill:#ff0000" />
<!--bottom left-->
<rect x="0" y="400" height="100" width="100"
style="fill:#000000" />
<!--bottom middle-->
<rect x="100" y="400" height="100" width="300"
style="fill:#ff0088" />
<!--bottom right-->
<rect x="400" y="400" height="100" width="100"
style="fill:#8800ff" />
</symbol>
<symbol id="box-top-left" viewBox="0 0 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-middle" viewBox="100 0 400 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-right" viewBox="400 0 500 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-left" viewBox="0 100 100 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-middle" viewBox="100 100 400 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-right" viewBox="400 100 500 400" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-left" viewBox="0 400 100 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-middle" viewBox="100 400 400 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-right" viewBox="400 400 500 500" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
</defs>
<use xlink:href="#box" x="0" y="0" height="500" width="500" />
</svg>
Solution found. My error was in not using the viewBox attribute in a <symbol> correctly.
It should be viewBox="minX minY width height"
Instead of viewBox="minx minY maxX maxY"
The working SVG is (click for full size):
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="box">
<!--top left-->
<rect x="0" y="0" height="100" width="100"
style="fill:#0000ff" />
<!--top middle-->
<rect x="100" y="0" height="100" width="300"
style="fill:#008888" />
<!--top right-->
<rect x="400" y="0" height="100" width="100"
style="fill:#00ff00" />
<!--middle left-->
<rect x="0" y="100" height="300" width="100"
style="fill:#888800" />
<!--middle middle-->
<rect x="100" y="100" height="300" width="300"
style="fill:#2a2a2a" />
<!--middle right-->
<rect x="400" y="100" height="300" width="100"
style="fill:#ff0000" />
<!--bottom left-->
<rect x="0" y="400" height="100" width="100"
style="fill:#000000" />
<!--bottom middle-->
<rect x="100" y="400" height="100" width="300"
style="fill:#ff0088" />
<!--bottom right-->
<rect x="400" y="400" height="100" width="100"
style="fill:#8800ff" />
</g>
<symbol id="box-top-left" viewBox="0 0 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-middle" viewBox="100 0 300 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-top-right" viewBox="400 0 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-left" viewBox="0 100 100 300" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-middle" viewBox="100 100 300 300" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-middle-right" viewBox="400 100 100 300" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-left" viewBox="0 400 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-middle" viewBox="100 400 300 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
<symbol id="box-bottom-right" viewBox="400 400 100 100" preserveAspectRatio="none">
<use xlink:href="#box" style="overflow:none;" />
</symbol>
</defs>
<use xlink:href="#box-top-left" x="0" y="0" height="100" width="100" />
<use xlink:href="#box-top-middle" x="100" y="0" height="100" width="300" />
<use xlink:href="#box-top-right" x="400" y="0" height="100" width="100" />
<use xlink:href="#box-middle-left" x="0" y="100" height="300" width="100" />
<use xlink:href="#box-middle-middle" x="100" y="100" height="300" width="300" />
<use xlink:href="#box-middle-right" x="400" y="100" height="300" width="100" />
<use xlink:href="#box-bottom-left" x="0" y="400" height="100" width="100" />
<use xlink:href="#box-bottom-middle" x="100" y="400" height="100" width="300" />
<use xlink:href="#box-bottom-right" x="400" y="400" height="100" width="100" />
</svg>

svg: filtering background image, google chrome

I am struggling with an svg to blur background under text on Google Chrome 36.0.1985.125 linux. The svg is like
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="myfilter" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<feGaussianBlur result="blurOut" in="BackgroundImage" stdDeviation="2" />
<feBlend in2="blurOut" in="SourceGraphic" mode="normal" />
</filter>
</defs>
<g enable-background="new">
<text x="10" y="100" stroke="none" fill="red" fill-opacity="1" font-size="24">BACKGROUND</text>
<text x="20" y="100" stroke="none" fill="black" fill-opacity="1" font-size="26" filter="url(#myfilter)">text</text>
</g>
</svg>
Fiddle: http://jsfiddle.net/2o2trpc1/
Thus I would like to blur "BACKGROUND" behind "text", but "text" does not appear at all. Can someone please look at this what I am doing wrong? Where can I check that the browser version supports filtering background image?
thanks a lot,
Balazs
You will have to work around the lack of BackgroundImage. There are multiple ways to do that, if your code is as simple as the fiddle you posted something like this could work:
<body>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="blur" filterUnits="objectBoundingBox" x="0" y="0" width="100%" height="100%">
<feGaussianBlur result="blurOut" stdDeviation="2" />
</filter>
</defs>
<g>
<text x="10" y="100" stroke="none" fill="red" fill-opacity="1" font-size="24" filter="url(#blur)">BACKGROUND</text>
<text x="20" y="100" stroke="none" fill="black" fill-opacity="1" font-size="26">text</text>
</g>
</svg>
</body>
See fiddle.
Another option is to use <feImage xlink:href="#background"/> in the filter, instead of using BackgroundImage. This can bring in whatever element you want.
<body>
<svg width="500px" height="500px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<filter id="myfilter" filterUnits="userSpaceOnUse" x="0" y="0" width="100%" height="100%">
<feImage xlink:href="#background"/>
<feGaussianBlur stdDeviation="3" />
<feBlend in="SourceGraphic" mode="normal" />
</filter>
<text id="background" x="10" y="100" stroke="none" fill="red" fill-opacity="1" font-size="24">BACKGROUND</text>
</defs>
<g>
<text x="20" y="100" stroke="none" fill="black" fill-opacity="1" font-size="26" filter="url(#myfilter)">text</text>
</g>
</svg>
</body>
See fiddle.

Resources