futuraprime
futuraprime

Reputation: 5588

Generating a working svg gradient with d3

I'm trying to generate an SVG gradient (for a stroke) with D3 (the rest of the project uses D3, so using D3 for this seemed to make sense...)

Here is the code that generates the gradient:

function generateBlindGradient(svg, color, side) {
  // can't have a hash mark in the id or bad things will happen
  idColor = color.replace('#', '');
  side = side || 'right';
  // this is a sneaky d3 way to select the element if present
  // or create the element if it isn't
  var defs = svg.selectAll('defs').data([0]);
  defs.enter().append('svg:defs');

  var id = 'gradient-' + idColor + '-' + side;
  var gradient = defs.selectAll('lineargradient#'+id).data([0]);
  gradient.enter().append('svg:lineargradient')
    .attr('id', id);

  var colors = [
    { offset : '50%', color : '#DFE2E6' },
    { offset : side === 'left' ? '100%' : '0%', color : color }
  ];
  var stops = gradient.selectAll('stop').data(colors);
  stops.enter().append('svg:stop');
  stops.attr('stop-color', function(d) { return d.color; })
    .attr('offset', function(d) { return d.offset; });

  return id;
}

This works... almost right. It generates gradients like this:

<lineargradient id="gradient-a8d4a1-left">
  <stop stop-color="#DFE2E6" offset="50%"></stop>
  <stop stop-color="#a8d4a1" offset="100%"></stop>
</lineargradient>

That gradient does not work (as either a fill or a stroke)--the element it's applied to gets no stroke or fill.

If I use the web inspector to "edit the HTML" of the lineargradient element, even if I don't change anything, the gradients suddenly work — so I'm guessing there's something weird going on within Chrome's SVG parsing or d3's element generation.

I think it might be down to a confusion between lineargradient and linearGradient—d3 seems to have some issues with camelCased elements and when I have it create linearGradient elements, it doesn't select them (and I get lots and lots of copies). Also, while in Chrome's inspector, these elements show up as lineargradient; when I edit as HTML, they are linearGradient. I'm not sure what's going on here or how to fix it.

Upvotes: 1

Views: 828

Answers (1)

Robert Longson
Robert Longson

Reputation: 124324

SVG is case sensitive so its linearGradient rather than lineargradient for creation.

I think Chrome has a selector bug that you can't select camel cased elements though.

The common workaround seems to be to assign a class to all your linearGradient elements and select by class rather than by tag name.

Upvotes: 2

Related Questions