1

In my nvd3 bubble chart, each group of points has a different symbol but the legend has all as circles. The code is here. I have only come across this

.showLegend(false)

which enables to hide or show the legend. I am unable to understand how to change the symbols in the legend.

Dinesh
  • 2,194
  • 3
  • 30
  • 52

1 Answers1

6

nvd3 does not give you direct access to the internals of the legend. However, you can alter it fairly easily using d3 selections to manipulate its various parts.

Start by creating a selection of all elements with class nv-series. This class represents a single group in the legend, holding both the circle symbol and the text (in your case 'Group0', 'Group1' etc). This returns an array, and the first element (index 0) is an array of all the elements:

// all `g` elements with class nv-series
d3.selectAll('.nv-series')[0]

Next, use the Array.forEach() function to iterate over this array, and for each element, replace the circle element with the appropriate symbol, matching the fill color to the circle that was removed.

In order to do this you also need to reuse the list of symbols that you made earlier, and iterate through them as well so that the correct symbol is assigned to each group. Here is one way to accomplish that, though perhaps you can think of an easier way:

// reuse the order of shapes
var shapes = ['circle', 'cross', 'triangle-up', 'triangle-down', 'diamond', 'square'];
// loop through the legend groups
d3.selectAll('.nv-series')[0].forEach(function(d,i) {
  // select the individual group element
  var group = d3.select(d);
  // create another selection for the circle within the group
  var circle = group.select('circle');
  // grab the color used for the circle
  var color = circle.style('fill');
  // remove the circle
  circle.remove();
  // replace the circle with a path
  group.append('path')
    // match the path data to the appropriate symbol
    .attr('d', d3.svg.symbol().type(shapes[i]))
    // make sure the fill color matches the original circle
    .style('fill', color);
});

Here is the updated JSFiddle.


===== EDIT =====

I've been going through the nvd3 codebase a bit, and there's a much simpler way to trigger the legend symbol to unfill when it is deactivated. It can simply be targeted in your css, since the series is given a class of disabled when it is disabled.

If you add the following css...

.nv-series.disabled path {
    fill-opacity: 0;
}

...then you can remove all of the hacky JavaScript click handling. It's much cleaner, and it's actually the way they handle it when using the default circle element.

Here's the updated JSFiddle.

jshanley
  • 9,048
  • 2
  • 37
  • 44
  • But the legend symbol does not empty on clicking it. How can I do so? – Dinesh Jun 25 '14 at 20:00
  • Since the `.on('click')` handler is already being used to trigger the graph to change, you can use the `.on('mouseup')` to check if the group is active and remove the fill of the symbol. I realize that's a bit hacky but there's no way around that at this point... You should submit an issue to their github page and let them know that you'd like to be able to customize the legend using a sensible API. Here's an updated [**JSFiddle**](http://jsfiddle.net/dyMx5/) for now. – jshanley Jun 25 '14 at 21:15
  • Thanks! One last doubt. I tried to make the legend symbol larger by using `.attr('r', 10)` but the size is not changing. – Dinesh Jun 25 '14 at 21:37
  • Those symbols are `path` elements, so they don't have a radius attribute, but you can adjust their size and position using a transform. If you set `.attr('transform', 'scale(1.5)')` the symbols would be 1.5 times larger. Play around with it until you get something that looks right to you. Here's the updated [**JSFiddle**](http://jsfiddle.net/yzm7P/). – jshanley Jun 25 '14 at 22:33
  • Thanks for the edit. The Edit is the correct solution. The JavaScript click handling has some issues when we disable all the symbols in the legend. – Dinesh Jun 27 '14 at 19:07