question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Can't Apply SVG Gradients to Chart SVG Elements

See original GitHub issue

I’ve been trying and failing to apply what should be a simple styling of lines, areas, bars, and pie slices using SVG gradients and I can’t figure out why it isn’t working.

Attempting to use either pre-existing SVG gradients or dynamically created SVG gradients through the Chartist API, the chart fills or strokes go transparent. Can anyone tell me what is wrong?

My code is as follows:

CSS

.ct-chart.blue-grad {
    .ct-series-a {
        .ct-point, .ct-line, .ct-bar, .ct-slice-donut   { stroke: url(#gradient); }
        .ct-slice-pie, .ct-area                         { fill: url(#gradient); }
    }
}

Preexisting SVG

<svg>
    <defs>
        <linearGradient id="gradient">
            <stop offset="0" stop-color="red"/>
            <stop offset="1" stop-color="blue"/
        </linearGradient>
    </defs>
</svg>

Create Gradients on Draw

var gradientsAdded;
gradientsAdded = false;
// I've tried doing this listening at the 'created' event, as well
$chart.on('draw', function(data) {
  var _stops, defs, gradient, i, len, stop;
  if (gradientsAdded === false) {
    defs = new Chartist.Svg('defs');
    gradient = defs.elem('linearGradient', {'id': 'gradient'});
    _stops = [
      {offset: 0, stopColor: '#00d5bd'}, 
      {offset: 100, stopColor: '#24c1ed'}
    ];
    for (i = 0, len = _stops.length; i < len; i++) {
      stop = _stops[i];
      stop = gradient.elem('stop', {'offset': stop.offset, 'stop-color': stop.stopColor });
    }
    data.element.append(defs, true);
    gradientsAdded = true;
  }
});

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:1
  • Comments:10

github_iconTop GitHub Comments

4reactions
gionkunzcommented, Aug 5, 2015

Hi @AJeezy9

Actually I’ve found out that it’s not a bug but rather a specification. Still, to me it looks like a design issue in the SVG specification as the behaviour is unexpected for the user.

Check http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox at the bottom. It says:

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.

Which means for us as SVG users, that straight lines won’t have a bounding box and therefor won’t generate bounding box coordinates for the gradient mapping process. If you ask me, there should be a bounding box with one component (height or width) being 0 and mapping processes need to take this into account. But maybe Mr. SVG @longsonr can give some background why the spec is like that 😃

You have a couple of options for your gradients on straight lines like they exist on the bar chart. You could either switch to gradientUnits="userSpaceOnUse" on your gradient and try to achieve a gradient mapping in user space (although you’ll have a hard time with that I guess and probably require one gradient per line). Or, as a very simple workaround, make your straight lines not straight anymore 😃 But just a tiny little bit, just a few ticks above the precision limit within the browser.

In this example, I use the draw event to modify the bars so that they are not 100% straight anymore (you wont notice as its probably an angle ~< 0.001deg) and the created event in order to create the gradient definition. Gradient assignment is in the CSS panel. http://jsbin.com/kedeta/edit?css,js,output

2reactions
hitautodestructcommented, Jul 11, 2018

Pointing out the gist of @gionkunz helpful fix.

For anyone having this issue the basic idea is to offset the bar just a tiny bit so that the browser renders a bounding box thus allowing for a gradient on the line using stroke.

Add the js below and then apply your gradient to the stroke JS

// Offset x1 a tiny amount so that the straight stroke gets a bounding box
// Straight lines don't get a bounding box 
// Last remark on -> http://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
chart.on('draw', function(ctx) {
  if(ctx.type === 'bar') {
    ctx.element.attr({
      x1: ctx.x1 + 0.001
    });
  }
});
Read more comments on GitHub >

github_iconTop Results From Across the Web

SVG gradient not working - Stack Overflow
I've a svg and I need to fill it with a gradient, the css is added by a script, if U work with...
Read more >
Gradients in SVG - SVG: Scalable Vector Graphics | MDN
To use a gradient, we have to reference it from an object's fill or stroke attributes. This is done the same way you...
Read more >
SVG gradients · WebPlatform Docs
This article looks at filling SVG shapes with linear and radial gradients.
Read more >
SVG Linear Gradient - W3Schools
A gradient is a smooth transition from one color to another. In addition, several color transitions can be applied to the same element....
Read more >
Creating a smooth color legend with an SVG gradient
There actually exists a linearGradient element. But this must be nested within a defs element, where defs is short for definitions. It contains ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found