Why is my rotated SVG shifted? - svg

I try to build a reflection of my text with gradient. But the reflection (the second text) has an off set and by applying the rotation the letters are shifting.
body {
background-color: black;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="140" viewBox="0 0 1000 140">
<text x="260" y="70" font-size="60" fill=" #888888" style="text-anchor: right">Multimediale Kunst</text>
<defs>
<linearGradient id="linearGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#000000" />
<stop offset="10%" stop-color="#666666" />
</linearGradient>
</defs>
<text rotate="180" x="310" y="80" font-size="60" fill="url(#linearGradient)" style="text-anchor: right">Multimediale Kunst</text>
</svg>

This is happening because the rotate attribute rotates individual start points. So wider characters end up further away from narrow characters and vice-versa.
The rotate attribute is the wrong approach anyway. If you want to vertically flip the text, then you should use a transform that scales the object on the y axis by -1.
body {
background-color: black;
}
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1000" height="140" viewBox="0 0 1000 140">
<text x="260" y="70" font-size="60" fill=" #888888" style="text-anchor: right">Multimediale Kunst</text>
<defs>
<linearGradient id="linearGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="50%" stop-color="#000000" />
<stop offset="100%" stop-color="#666666" />
</linearGradient>
</defs>
<text x="260" y="-80" font-size="60" fill="url(#linearGradient)" style="text-anchor: right" transform="scale(1,-1)">Multimediale Kunst</text>
</svg>

Related

SVG pattern size relative to container shape

I am trying to create a svg pattern where size of it is relative to shape to which is applied. Pattern should consist of rect with linearGradient and text elements which repeats in x-axis n-times or every n pixels and is vertically aligned in middle of rect.
The results should look like this.
I have tried following approaches.
<svg width="100%" height="100">
<defs>
<linearGradient id="gradient" x1="0%" x2="0%" y1="0%" y2="100%">
<stop offset="0%" stop-color="#fff" />
<stop offset="100%" stop-color="#c6c6c6" />
</linearGradient>
<pattern id="pattern" width="25%" height="100%">
<rect width="100%" height="100%" fill="url(#gradient)"></rect>
<text x="10" y="50%" dx=50 fill="red">test</text>
</pattern>
</defs>
<rect width="1000" height="100" fill="url(#pattern)"></rect>
</svg>
This approach gives the result I want but the size of pattern is not relatve to shape to which is applied and fails when shape is resized, to solve this issue I have tried to create a pattern with patternContentUnits="objectBoundingBox" but then I am having problems positioning the text.
<svg width="100%" height="100%">
<defs>
<linearGradient id="gradient" x1="0%" x2="0%" y1="0%" y2="100%">
<stop offset="0%" stop-color="#fff" />
<stop offset="100%" stop-color="#c6c6c6" />
</linearGradient>
<pattern id="pattern" patternContentUnits="objectBoundingBox" width="25%" height="100%">
<rect width="1" height="1" fill="url(#gradient)"></rect>
<text x="0.1" y="0.5">test</text>
</pattern>
</defs>
<rect width="1000" height="100" fill="url(#pattern)"></rect>
</svg>
objectBoundingBox units are in the range [0, 1] so 10 is too big.
You'll need to use a suitable font-size too.
<svg width="100%" height="100%">
<defs>
<linearGradient id="gradient" x1="0%" x2="0%" y1="0%" y2="100%">
<stop offset="0%" stop-color="#fff" />
<stop offset="100%" stop-color="#c6c6c6" />
</linearGradient>
<pattern id="pattern" patternContentUnits="objectBoundingBox" width="25%" height="100%">
<rect width="1" height="1" fill="url(#gradient)"></rect>
<text transform="scale(0.2, 1)" x="0.1" y="0.5" font-size="0.1">test</text>
</pattern>
</defs>
<rect width="1000" height="100" fill="url(#pattern)"></rect>
</svg>

How to apply a gradient to a marker?

In SVG, how to apply the gradient applied to a line to its marker-end ?
<?xml version='1.0' encoding='UTF-8' standalone="yes"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="820px"
height="500px"
viewBox="0 0 820 500"
version="1.1" >
<style>
.axis3 {
stroke-width: 40px;
marker-end:url(#arrow);
stroke: url('#gradient_3');
fill: url('#gradient_3');
height: 30px;
}
.axis4 {
stroke-width: 40px;
marker-end:url(#arrow);
stroke: url('#gradient_4');
fill: url('#gradient_4'); /* corrected */
height: 30px;
}
</style>
<defs>
<marker
id="arrow"
markerWidth="20"
markerHeight="40"
refX="0"
refY="20"
orient="auto"
markerUnits="userSpaceOnUse"
style="fill:inherit;">
<path style="stroke:none;fill:inherit;overflow:visible;" d="M0 0 L20 20 L0 40 Z" />
</marker>
<linearGradient id="gradient_3" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse" >
<stop offset="0%" stop-color="yellow" />
<stop offset="20%" stop-color="red" />
</linearGradient>
<linearGradient id="gradient_4" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse" >
<stop offset="0%" stop-color="blue" />
<stop offset="20%" stop-color="green" />
</linearGradient>
</defs>
<line class="axis3" x1="50" x2="400" y1="50" y2="50" />
<line class="axis4" x1="50" x2="400" y1="100" y2="100" />
</svg>
With the code above, marker is always black.
As there are several elements line with different gradients, gradient can not be applied directly on the path.
I tried to add style="fill:inherit" - with no success.
This is how I would do it:
Instead of fill:inherit; I'm setting two css variables for the svg element: style="--fill:url(#gradient_3); --stroke:url(#gradient_4)". Both the line and the marker are using those variables for the fill and the stroke.
Alternatively you may choose to use the gradients directly in the code <path style="overflow:visible;fill:url(#gradient_3);"...
To your code I've added a #gradient_3 since you are using it.
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="820px"
height="500px"
viewBox="0 0 820 500"
version="1.1"
style="--fill:url(#gradient_3); --stroke:url(#gradient_4)">
<style>
.axis {
stroke-width: 40px;
marker-end:url(#arrow);
height: 30px;
stroke:var(--stroke);
}
</style>
<defs>
<marker
id="arrow"
markerWidth="20"
markerHeight="40"
refX="0"
refY="20"
orient="auto"
markerUnits="userSpaceOnUse">
<path style="overflow:visible;fill:var(--fill);" d="M0 0 L20 20 L0 40 Z" />
</marker>
<linearGradient id="gradient_3" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse" >
<stop offset="0%" stop-color="green" />
<stop offset="20%" stop-color="blue" />
</linearGradient>
<linearGradient id="gradient_4" x1="0%" y1="0%" x2="100%" y2="0%" gradientUnits="userSpaceOnUse" >
<stop offset="0%" stop-color="blue" />
<stop offset="20%" stop-color="green" />
</linearGradient>
</defs>
<line class="axis" x1="50" x2="400" y1="50" y2="50" />
</svg>
Answer to "Make marker-end same color as path?" mentions that there is no inheritance of colors from related path.
Situation has not evolve since this answer.

SVG linear gradients objectBoundingBox vs userSpaceOnUse

I am making two gradients: one in objectBoundingBox units and another in userSpaceOnUse. The idea is to make them look the same. But somehow they are different. Here is the svg file.
<svg width="500" height="500" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="user-grad" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="200" y2="100">
<stop stop-color="orange" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
<linearGradient id="box-grad" x1="0" y1="0" x2="1" y2="1">
<stop stop-color="orange" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="200" height="100" fill="url(#user-grad)"/>
<rect x="250" y="0" width="200" height="100" fill="url(#box-grad)"/>
</svg>
Here is what it looks like
Shouldn't they look the same?
Shouldn't they look the same?
No. When using object bounding box coordinates, you are basically transforming a 1x1 square onto your rectangle. So the 0 to 1 coordinates are stretched to fit the rectangle. Thus causing the gradient to stretch also.
If you want them to look the same, you would need to apply a gradientTransform, to your userSpaceOnUse one, that applies the equivalent stretch.
<svg width="500" height="500" viewBox="0 0 500 500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="user-grad" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="100" y2="100" gradientTransform="scale(2, 1)">
<stop stop-color="orange" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
<linearGradient id="box-grad" x1="0" y1="0" x2="1" y2="1">
<stop stop-color="orange" offset="0"/>
<stop stop-color="blue" offset="1"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="200" height="100" fill="url(#user-grad)"/>
<rect x="250" y="0" width="200" height="100" fill="url(#box-grad)"/>
</svg>

SVG background not applied

I've made a simple SVG image but the background isn't applied whereas it should.
I got the following code so far:
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" id="content" width="100%" height="100%" viewbox="0 0 800 1000" preserveaspectratio="xMidYMid meet" version="1.1">
<defs>
<lineargradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#ffffff" stop-opacity="0"/>
<stop offset="100%" stop-color="orange" stop-opacity="0.8"/>
</lineargradient>
<lineargradient id="gradientLine" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="orange" stop-opacity="0"/>
<stop offset="100%" stop-color="orange" stop-opacity="0.6"/>
</lineargradient>
</defs>
<g id="vis" transform="translate(330,670)">
<path fill="url(#gradient)" d="M-112.87131548350527,-640.1250394579351A650,650 0 0,1 222.31309316168483,-610.8002035108404L0,0Z"/>
<circle r="35" stroke="orange" fill="orange" opacity="1"/>
<circle r="3" stroke="black" fill="black" opacity="1"/>
<line x1="0" x2="-85" y1="0" y2="0" fill="black" stroke="black"/>
</g>
</svg>
The path is black but it should be a gradient going from white to orange.
Apparently, when I run my code in jsfiddle, it displays the good result. But when I try to display the SVG in an img tag or directly in my browser, I got a black background. Any idea ?
Did I make something wrong or is this a common issue ?
Thanks for your help.
I think the problem is here:
<lineargradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
Fixed:
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">

Linear gradients in SVG without defs

I can use linear gradient in SVG with defs-section like:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="myLinearGradient1"
x1="0%" y1="0%"
x2="0%" y2="100%"
spreadMethod="pad">
<stop offset="0%" stop-color="#00cc00" stop-opacity="1"/>
<stop offset="100%" stop-color="#006600" stop-opacity="1"/>
</linearGradient>
</defs>
<rect x="0" y="0" width="100" height="100"
style="fill:url(#myLinearGradient1)" />
</svg>
Can I use linear gradient without defs-section? I find something like this:
<rect style="fill:lineargradient(foo)">
<defs> is only needed for structuring purposes, the elements in it are not displayed, but since a gradient can only be visible when applied to a shape or another element, you can define it in any place of the document.
But you still have to stick to the correct syntax:
<rect style="fill:url(#myLinearGradient1)" ... />
Yes you can indeed have a gradient without needing to have a defs element; you simply put the gradient element anywhere else in the code instead, for example like this:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<linearGradient id="myLinearGradient1"
x1="0%" y1="0%"
x2="0%" y2="100%"
spreadMethod="pad">
<stop offset="0%" stop-color="#00cc00" stop-opacity="1"/>
<stop offset="100%" stop-color="#006600" stop-opacity="1"/>
</linearGradient>
<rect x="0" y="0" width="100" height="100"
style="fill:url(#myLinearGradient1)" />
</svg>

Resources