How to apply a gradient to a marker? - svg

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.

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 can I rewrite a gradient with userSpaceOnUse to objectBoundingBox?

I have this gradient that uses userSpaceOnUse.
<svg height="400px" width="800px" viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" x1="0" y1="0" x2="800" y2="400" gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color:green;stop-opacity:1" />
<stop offset="50%" style="stop-color:black;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:1" />
</linearGradient>
</defs>
<rect x="0" y="0" width="800" height="400" fill="url(#grad1)"/>
</svg>
I want to rewrite it to use objectBoundingBox but be rendered the same. How can I do this?
I imagine the rewritten SVG would be close to:
<svg height="400px" width="800px" viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" x1="0" y1="0" x2="1" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0%" style="stop-color:green;stop-opacity:1" />
<stop offset="50%" style="stop-color:black;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:1" />
</linearGradient>
</defs>
<rect x="0" y="0" width="800" height="400" fill="url(#grad1)"/>
</svg>
This answer (https://stackoverflow.com/a/50624704/1283776) indicates that I need to use a transform, but I haven't been successful in found a solution.
<!-- https://stackoverflow.com/questions/22214999/svg-linear-gradient-independent-of-the-shape-coordinates -->
<svg height="400px" width="800px" viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad1" x1="0" y1="0" x2="1" y2="0.5" gradientUnits="objectBoundingBox" gradientTransform="scale(1, 2)">
<stop offset="0%" style="stop-color:green;stop-opacity:1" />
<stop offset="50%" style="stop-color:black;stop-opacity:1" />
<stop offset="100%" style="stop-color:red;stop-opacity:1" />
</linearGradient>
</defs>
<rect x="0" y="0" width="800" height="400" fill="url(#grad1)"/>
</svg>

SVG fill figure and its negative in different colours

I'm having trouble creating a gardient in a svg image. I need to fill the figure as its progress increase (0~100% or 0~1) but also the negative of the figure path.
Let me show what I need with some images to be more clear.
This is what I can achieve:
Already Done
And this is what I need:
Hope to achieve
Is there a simple way to achieve this?
EDIT: Sorry, this is my SVG code:
<svg id="Capa_1" enable-background="new 0 0 503.353 503.353" height="512" viewBox="0 0 503.353 503.353" width="512" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop stop-color="#aaa" offset="0" />
<stop stop-color="#aaa" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="green" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="green" offset="1" />
</linearGradient>
</defs>
<path class="kiwi" d="m483.142 269.401-1.281-12.05-12.05-1.281c-1.145-.121-9.029-.899-21.262-.838-.005-.412-.001-.824-.009-1.236-1.83-95.103-83.035-161.783-86.491-164.575l-9.426-7.616-9.426 7.616c-.768.621-5.382 4.403-12.108 10.948-24.406-55.352-67.489-90.736-69.986-92.753l-9.426-7.616-9.426 7.616c-2.49 2.011-45.318 37.183-69.764 92.245-6.44-6.232-10.835-9.835-11.583-10.439l-9.426-7.616-9.426 7.616c-3.456 2.792-84.661 69.472-86.491 164.575-.008.414-.004.826-.009 1.24-12.662-.098-20.841.71-22.01.834l-12.05 1.281-1.281 12.05c-.47 4.418-10.74 108.988 55.213 177.53 36.076 37.492 87.354 56.422 152.663 56.422 7.668 0 15.537-.269 23.59-.791 8.057.523 15.917.791 23.59.791 65.303 0 116.589-18.932 152.663-56.422 65.952-68.543 55.682-173.113 55.212-177.531zm-130.519-148.024c19.981 19.489 64.799 70.155 65.927 133.393.013.733.002 1.465.004 2.198-23.708 2.614-52.747 8.816-80.739 22.639-10.149-29.958-26.595-55.141-41.675-73.83 14.488-39.789 42.01-70.284 56.483-84.4zm-100.946 345.907c-44.573-42.071-66.743-86.537-65.926-132.316 1.127-63.242 45.954-113.913 65.926-133.392 19.981 19.489 64.799 70.155 65.927 133.392.815 45.779-21.354 90.244-65.927 132.316zm-.001-427.713c14.614 14.254 42.507 45.186 56.882 85.514-12.001 14.807-24.912 33.756-34.854 55.966-6.991-6.838-11.814-10.794-12.601-11.43l-9.426-7.616-9.426 7.616c-.767.62-5.371 4.395-12.082 10.923-10.056-22.312-23.091-41.309-35.146-56.097 14.441-40.021 42.123-70.704 56.653-84.876zm-166.124 215.199c1.127-63.242 45.954-113.913 65.926-133.393 14.402 14.047 41.701 44.292 56.249 83.765-15.218 18.751-31.923 44.168-42.187 74.464-27.697-13.677-56.423-19.896-79.991-22.557 0-.76-.011-1.519.003-2.279zm11.625 171.501c-43.922-45.516-48.054-113.042-47.706-140.938 21.81-.277 67.78 2.211 108.551 24.244-1.303 7.968-2.101 16.179-2.264 24.619-.936 48.66 19.036 95.238 59.414 138.849-50.56-2.269-90.153-17.923-117.995-46.774zm308.999 0c-27.843 28.855-67.441 44.526-118.002 46.781 40.382-43.613 60.357-90.193 59.42-138.856-.162-8.44-.961-16.651-2.263-24.619 40.783-22.038 86.768-24.519 108.55-24.245.348 27.909-3.787 95.426-47.705 140.939z"/>
</svg>
And the CSS class:
.kiwi {
fill: url(#gradient);
position: absolute;
height: auto;
}
Thanks!
Well the easy way based on what your path looks like is just to copy part of the shape that draws the outline, put it underneath your existing shape and animate it using a different gradient.
(A slightly better way would have been to draw the shape using a fat stroke rather than a fill and put a different gradient on the stroke and the fill using gradientUnits= userSpaceOnUse.)
.kiwi {
fill: url(#gradient1);
position: absolute;
height: auto;
}
.anzac {
fill: url(#gradient2);
position: absolute;
height: auto;
}
<svg id="Capa_1" enable-background="new 0 0 503.353 503.353" height="512" viewBox="0 0 503.353 503.353" width="512" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="gradient1" x1="0%" y1="0%" x2="0%" y2="100%">
<stop stop-color="#aaa" offset="0" />
<stop stop-color="#aaa" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="green" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="green" offset="1" />
</linearGradient>
<linearGradient id="gradient2" x1="0%" y1="0%" x2="0%" y2="100%">
<stop stop-color="#aaa" offset="0" />
<stop stop-color="#aaa" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="blue" offset="1">
<animate dur="2s" by="-0.5" attributeName="offset" fill="freeze" calcMode="spline" keyTimes="0;1" keySplines="0.4, 0, 0.2, 1" />
</stop>
<stop stop-color="blue" offset="1" />
</linearGradient>
</defs>
<path class="anzac" d="m483.142 269.401-1.281-12.05-12.05-1.281c-1.145-.121-9.029-.899-21.262-.838-.005-.412-.001-.824-.009-1.236-1.83-95.103-83.035-161.783-86.491-164.575l-9.426-7.616-9.426 7.616c-.768.621-5.382 4.403-12.108 10.948-24.406-55.352-67.489-90.736-69.986-92.753l-9.426-7.616-9.426 7.616c-2.49 2.011-45.318 37.183-69.764 92.245-6.44-6.232-10.835-9.835-11.583-10.439l-9.426-7.616-9.426 7.616c-3.456 2.792-84.661 69.472-86.491 164.575-.008.414-.004.826-.009 1.24-12.662-.098-20.841.71-22.01.834l-12.05 1.281-1.281 12.05c-.47 4.418-10.74 108.988 55.213 177.53 36.076 37.492 87.354 56.422 152.663 56.422 7.668 0 15.537-.269 23.59-.791 8.057.523 15.917.791 23.59.791 65.303 0 116.589-18.932 152.663-56.422 65.952-68.543 55.682-173.113 55.212-177.531z"/>
<path class="kiwi" d="m483.142 269.401-1.281-12.05-12.05-1.281c-1.145-.121-9.029-.899-21.262-.838-.005-.412-.001-.824-.009-1.236-1.83-95.103-83.035-161.783-86.491-164.575l-9.426-7.616-9.426 7.616c-.768.621-5.382 4.403-12.108 10.948-24.406-55.352-67.489-90.736-69.986-92.753l-9.426-7.616-9.426 7.616c-2.49 2.011-45.318 37.183-69.764 92.245-6.44-6.232-10.835-9.835-11.583-10.439l-9.426-7.616-9.426 7.616c-3.456 2.792-84.661 69.472-86.491 164.575-.008.414-.004.826-.009 1.24-12.662-.098-20.841.71-22.01.834l-12.05 1.281-1.281 12.05c-.47 4.418-10.74 108.988 55.213 177.53 36.076 37.492 87.354 56.422 152.663 56.422 7.668 0 15.537-.269 23.59-.791 8.057.523 15.917.791 23.59.791 65.303 0 116.589-18.932 152.663-56.422 65.952-68.543 55.682-173.113 55.212-177.531zm-130.519-148.024c19.981 19.489 64.799 70.155 65.927 133.393.013.733.002 1.465.004 2.198-23.708 2.614-52.747 8.816-80.739 22.639-10.149-29.958-26.595-55.141-41.675-73.83 14.488-39.789 42.01-70.284 56.483-84.4zm-100.946 345.907c-44.573-42.071-66.743-86.537-65.926-132.316 1.127-63.242 45.954-113.913 65.926-133.392 19.981 19.489 64.799 70.155 65.927 133.392.815 45.779-21.354 90.244-65.927 132.316zm-.001-427.713c14.614 14.254 42.507 45.186 56.882 85.514-12.001 14.807-24.912 33.756-34.854 55.966-6.991-6.838-11.814-10.794-12.601-11.43l-9.426-7.616-9.426 7.616c-.767.62-5.371 4.395-12.082 10.923-10.056-22.312-23.091-41.309-35.146-56.097 14.441-40.021 42.123-70.704 56.653-84.876zm-166.124 215.199c1.127-63.242 45.954-113.913 65.926-133.393 14.402 14.047 41.701 44.292 56.249 83.765-15.218 18.751-31.923 44.168-42.187 74.464-27.697-13.677-56.423-19.896-79.991-22.557 0-.76-.011-1.519.003-2.279zm11.625 171.501c-43.922-45.516-48.054-113.042-47.706-140.938 21.81-.277 67.78 2.211 108.551 24.244-1.303 7.968-2.101 16.179-2.264 24.619-.936 48.66 19.036 95.238 59.414 138.849-50.56-2.269-90.153-17.923-117.995-46.774zm308.999 0c-27.843 28.855-67.441 44.526-118.002 46.781 40.382-43.613 60.357-90.193 59.42-138.856-.162-8.44-.961-16.651-2.263-24.619 40.783-22.038 86.768-24.519 108.55-24.245.348 27.909-3.787 95.426-47.705 140.939z"/>
</svg>

Why is my rotated SVG shifted?

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>

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%">

Resources