Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG gradient for perfectly horizontal path

Tags:

path

gradient

svg

I'm using svg to draw line charts, and require a gradient to be applied to it. For each line, I use a path element and set the stroke to one of my lineargradient elements.

This works great for everything but purely horizontal lines - in this case, I get no colours on my line at all.

I've made a fiddle showing the problem: http://jsfiddle.net/b6EQT/

<svg>
    <defs>
        <linearGradient id="grad" x1="0%" x2="100%" y1="0%" y2="0%">
            <stop class="" offset="0%" style="stop-color: red;"></stop>
            <stop class="" offset="33%" style="stop-color: yellow;"></stop>
            <stop class="" offset="66%" style="stop-color: pink;"></stop>
            <stop class="" offset="100%" style="stop-color: blue"></stop>
        </linearGradient>
    </defs>
<-- Gradient not applied -->
<path stroke="url(#grad)" d="M20,20L400,20" style="stroke-width: 10px;"></path>

<-- Gradient applied since height of 1px -->
<path stroke="url(#grad)" d="M20,40L400,41" style="stroke-width: 10px;"></path>

<-- Gradient applied because of fake initial "move to" -->
<path stroke="url(#grad)" d="M-1,-1,M20,60L400,60" style="stroke-width: 10px;"></path>
</svg>​

The pure horizontal line (first path) doesn't appear, and the second one (slight change in y) does.

I tried a little hack to get it going - putting a fake M-1,-1 at the start, which seems to work around the issue in IE and Chrome, but not firefox. This makes me think I'm missing something in my understanding of SVG gradients and paths. Is there a way to get this to work?

like image 693
XwipeoutX Avatar asked Nov 04 '12 22:11

XwipeoutX


People also ask

Can you fill an SVG with a gradient?

With SVG, you can fill (i.e., paint the interior) or stroke (i.e., paint the outline) of shapes and text using one of the following: color (using <color>) gradients (linear or radial)

How do I create a gradient in SVG?

To use a gradient, we have to reference it from an object's fill or stroke attributes. This is done the same way you reference elements in CSS, using a url . In this case, the url is just a reference to our gradient, which I've given the creative ID, "Gradient". To attach it, set the fill to url(#Gradient) , and voila!


1 Answers

The default for gradientUnits is objectBoundingBox. The key issue you have is described in the last paragraph of the specification text...

Keyword objectBoundingBox should not be used when the geometry of the applicable element has no width or no height, such as the case of a horizontal or vertical line, even when the line has actual thickness when viewed due to having a non-zero stroke width since stroke width is ignored for bounding box calculations. When the geometry of the applicable element has no width or height and objectBoundingBox is specified, then the given effect (e.g., a gradient or a filter) will be ignored.

Why not use a rect with a fill rather than a path with a stroke if you've got a horizontal line? Or alternatively use userSpaceOnUse units.

like image 116
Robert Longson Avatar answered Sep 20 '22 13:09

Robert Longson