d3 SVG Legend

Tired of making legends for your data visualizations? Me too, enjoy.

A library to make legends in svg-land easy as pie.

By Susie Lu

Usage

Client-side

CDN

You can add latest version of d3-legend compatible with d3v3 hosted on cdnjs.

https://cdnjs.com/libraries/d3-legend/1.13.0

Include the file directly

You must include the d3 library before including the legend file. Then you can simply add the compiled js file to your website:

npm

You can add the d3 legend as a node module by running:

npm install --save d3-svg-legend@1.x

Github + feedback

The full source code is available on github. I would love to hear from you about any additional features that would be useful, please say hi on twitter @DataToViz.

Color

Documentation

d3.legend.color()

Constructs a new color legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting.

color.scale(d3.scale)

Creates a new d3 legend based on the scale. The code determines the type of scale and generates the appropriate symbol and label pairs.

color.cells(number or [numbers])

This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the specific steps you want the legend to display.

color.orient(string)

Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical."

color.ascending(boolean)

If you pass this a true, it will reverse the order of the scale.

color.shape(string[, path-string])

Accepts "rect", "circle", "line", or "path". If you choose "path," you must also pass a second parameter as a path string. Defaults to "rect." An example: Color - Ordinal Scale Legend, custom shape.

color.shapeWidth(number)

Only applies to shape of "rect" or "line." Default set to 15px.

color.shapeHeight(number)

Only applies to shape of "rect." Default set to 15px.

color.shapeRadius(number)

Only applies to shape of "circle." Default set to 10px.

color.shapePadding(number)

Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px.

color.useClass(boolean)

The default behavior is for the legend to set the fill of the legend's symbols (except for the "line" shape which uses stroke). If you set useClass to true then it will apply the scale's output as classes to the shapes instead of the fill or stroke. An example: Color - Quantile Scale Legend.

color.classPrefix(string)

Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes.

color.title(string)

Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: Symbol - Ordinal Scale.

color.labels([string])

Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: Size - Linear Scale Legend, Lines.

color.labelAlign(string)

Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: Size - Linear Scale Legend, Lines.

color.labelFormat(d3.format)

Takes a d3.format and applies that styling to the legend labels. Default is set to d3.format(".01f").

color.labelOffset(number)

A value that determines how far the label is from the symbol in each legend item. Default set to 10px.

color.labelDelimiter(string)

Change the default "to" text when working with a quant scale.

color.on(string, function)

There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: Symbol - Ordinal Scale

Examples

Quantile Scale Legend

0.00 to 0.020.02 to 0.030.03 to 0.050.05 to 0.070.07 to 0.080.08 to 0.100.10 to 0.120.12 to 0.130.13 to 0.15
          
var quantize = d3.scale.quantize()
  .domain([ 0, 0.15 ])
  .range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendQuant")
  .attr("transform", "translate(20,20)");

var legend = d3.legend.color()
  .labelFormat(d3.format(".2f"))
  .useClass(true)
  .scale(quantize);

svg.select(".legendQuant")
  .call(legend);
          
        

Log Scale Legend

0.15.010.050.0100.0500.01000.0
          
var log = d3.scale.log()
    .domain([ 0.1, 100, 1000 ])
    .range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendLog")
  .attr("transform", "translate(20,20)");

var logLegend = d3.legend.color()
    .cells([0.1, 5, 10, 50, 100, 500, 1000])
    .scale(log);

svg.select(".legendLog")
  .call(logLegend);

          
        

Linear Scale Legend - Horizontal

0.02.55.07.510.0
          
var linear = d3.scale.linear()
  .domain([0,10])
  .range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendLinear")
  .attr("transform", "translate(20,20)");

var legendLinear = d3.legend.color()
  .shapeWidth(30)
  .orient('horizontal')
  .scale(linear);

svg.select(".legendLinear")
  .call(legendLinear);
          
        

Linear Scale Legend - 10 cells

0.01.12.23.34.45.66.77.88.910.00.01.12.23.34.45.66.77.88.910.0
          
var linear = d3.scale.linear()
  .domain([0,10])
  .range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendLinear")
  .attr("transform", "translate(20,20)");

var legendLinear = d3.legend.color()
  .shapeWidth(30)
  .cells(10)
  .orient('horizontal')
  .scale(linear);

svg.select(".legendLinear")
  .call(legendLinear);
          
        

Linear Scale Legend - Custom cells

1.02.03.06.08.0
          
var linear = d3.scale.linear()
  .domain([0,10])
  .range(["rgb(46, 73, 123)", "rgb(71, 187, 94)"]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendLinear")
  .attr("transform", "translate(20,20)");

var legendLinear = d3.legend.color()
  .shapeWidth(30)
  .cells([1, 2, 3, 6, 8])
  .orient('horizontal')
  .scale(linear);

svg.select(".legendLinear")
  .call(legendLinear);
          
        

Ordinal Scale Legend - Custom shape

abcde
          
var ordinal = d3.scale.ordinal()
  .domain(["a", "b", "c", "d", "e"])
  .range([ "rgb(153, 107, 195)", "rgb(56, 106, 197)", "rgb(93, 199, 76)", "rgb(223, 199, 31)", "rgb(234, 118, 47)"]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendOrdinal")
  .attr("transform", "translate(20,20)");

var legendOrdinal = d3.legend.color()
  //d3 symbol creates a path-string, for example
  //"M0,-8.059274488676564L9.306048591020996,
  //8.059274488676564 -9.306048591020996,8.059274488676564Z"
  .shape("path", d3.svg.symbol().type("triangle-up").size(150)())
  .shapePadding(10)
  .scale(ordinal);

svg.select(".legendOrdinal")
  .call(legendOrdinal);
          
        

Size

Documentation

d3.legend.size()

Constructs a new size legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting.

size.scale(d3.scale)

Creates a new d3 legend based on the scale. The code determines the type of scale and generates the different symbol and label pairs. Expects a scale that has a numerical range.

size.cells(number or [numbers])

This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the specific steps you want the legend to display.

size.orient(string)

Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical."

size.ascending(boolean)

If you pass this a true, it will reverse the order of the scale.

size.shape(string)

Accepts "rect", "circle", or "line". Defaults to "rect." The assumption is that the scale's output will be used for the width and height if you select "rect," the radius if you select "circle," and the stroke-width if you select "line." If you want to have a custom shape of different sizes in your legend, use the symbol legend and make each path string for the sizes you want as the range array.

size.shapeWidth(number)

Only applies to shape "line." Default set to 15px.

size.shapePadding(number)

Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px.

size.classPrefix(string)

Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes.

size.title(string)

Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: Symbol - Ordinal Scale.

size.labels([string])

Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: Size - Linear Scale Legend, Lines

size.labelAlign(string)

Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: Size - Linear Scale Legend, Lines.

size.labelFormat(d3.format)

Takes a d3.format and applies that styling to the legend labels. Default is set to d3.format(".01f").

size.labelOffset(number)

A value that determines how far the label is from the symbol in each legend item. Default set to 10px.

size.labelDelimiter(string)

Change the default "to" text when working with a quant scale.

size.on(string, function)

There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: Symbol - Ordinal Scale

Examples

Linear Scale Legend - Circles

0.02.55.07.510.0
         
var linearSize = d3.scale.linear().domain([0,10]).range([10, 30]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendSize")
  .attr("transform", "translate(20, 40)");

var legendSize = d3.legend.size()
  .scale(linearSize)
  .shape('circle')
  .shapePadding(15)
  .labelOffset(20)
  .orient('horizontal');

svg.select(".legendSize")
  .call(legendSize);
         
       

Linear Scale Legend - Lines

tinysmallmediumlargegrand
         
var lineSize = d3.scale.linear().domain([0,10]).range([2, 10]);

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendSizeLine")
  .attr("transform", "translate(0, 20)");

var legendSizeLine = d3.legend.size()
      .scale(lineSize)
      .shape("line")
      .orient("horizontal")
      //otherwise labels would have displayed:
      // 0, 2.5, 5, 10
      .labels(["tiny", "small", "medium", "large", "grand"])
      .shapeWidth(40)
      .labelAlign("start")
      .shapePadding(10);

svg.select(".legendSizeLine")
  .call(legendSizeLine);
         
       

Symbol

Documentation

d3.legend.symbol()

Constructs a new symbol legend. The legend component expects a d3 scale as the basic input, but also has a number of optional parameters for changing the default display such as vertical or horizontal orientation, shape of the symbol next to the label, symbol sizing, and label formatting.

symbol.scale()

Creates a new d3 legend based on the scale. The code determines the type of scale and generates the different symbol and label pairs. The scale's range will be used as the d-attribute in an svg path for each symbol in the legend.

symbol.cells()

This parameter is only valid for continuous scales (like linear and log). When there is no indication from the domain or range for the number of steps in the legend you may want to display, it defaults to five steps in equal increments. You can pass the cells function a single number which will create equal increments for that number of steps, or an array of the specific steps you want the legend to display.

symbol.orient(string)

Accepts "vertical" or "horizontal" for legend orientation. Default set to "vertical."

symbol.ascending(boolean)

If you pass this a true, it will reverse the order of the scale.

symbol.shapePadding()

Applies to all shapes. Determines vertical or horizontal spacing between shapes depending on the respective orient setting. Default set to 2px.

symbol.classPrefix(string)

Adds this string to the beginning of all of the components of the legend that have a class. This allows for namespacing of the classes.

symbol.title(string)

Sets the legend's title to the string. Automatically moves the legend cells down based on the size of the title. An example: Symbol - Ordinal Scale.

symbol.labels([string])

Sets the legend labels to the array of strings passed to the legend. If the array is not the same length as the array the legend calculates, it merges the values and gives the calculated labels for the remaining items. An example: Size - Linear Scale Legend, Lines.

symbol.labelAlign(string)

Only used if the legend's orient is set to "horizontal." Accepts "start", "middle", or "end" as inputs to determine if the labels are aligned on the left, middle or right under the symbol in a horizontal legend. An example: Size - Linear Scale Legend, Lines.

symbol.labelFormat(d3.format)

Takes a d3.format and applies that styling to the legend labels. Default is set to d3.format(".01f").

symbol.labelOffset(number)

A value that determines how far the label is from the symbol in each legend item. Default set to 10px.

symbol.labelDelimiter(string)

Change the default "to" text when working with a quant scale.

symbol.on(string, function)

There are three custom event types you can bind to the legend: "cellover", "cellout", and "cellclick" An exampe: Symbol - Ordinal Scale

Examples

Ordinal Scale Legend - Custom symbols

abcdeSymbol Legend Title
         
var triangleU = d3.svg.symbol().type('triangle-up')(),
  circle = d3.svg.symbol().type('circle')(),
  cross = d3.svg.symbol().type('cross')(),
  diamond = d3.svg.symbol().type('diamond')(),
  triangleD = d3.svg.symbol().type('triangle-down')();

//example output of d3.svg.symbol().type('circle')();
//"M0,4.51351666838205A4.51351666838205,4.51351666838205 0 1,1 0,
//-4.51351666838205A4.51351666838205,4.51351666838205 0 1,1 0,4.51351666838205Z"

var symbolScale =  d3.scale.ordinal()
  .domain(['a','b','c', 'd', 'e'])
  .range([ triangleU, circle, cross, diamond, triangleD] );

var svg = d3.select("svg");

svg.append("g")
  .attr("class", "legendSymbol")
  .attr("transform", "translate(20, 20)");

var legendPath = d3.legend.symbol()
  .scale(symbolScale)
  .orient("horizontal")
  .title("Symbol Legend Title")
  .on("cellclick", function(d){alert("clicked " + d);});

svg.select(".legendSymbol")
  .call(legendPath);
         
       

Summary of Functions

Function Color Size Symbol
scale
cells
orient
ascending
shape
shapeWidth
shapeHeight
shapeRadius
shapePadding
useClass
classPrefix
title
labels
labelAlign
labelFormat
labelOffset
labelDelimiter
on
 

NOTES

Huge thanks to Elijah Meeks for discussing ideas and encouraging me to complete this project.

The styling and layout of this page is made with another project of mine, minimal-ui.

The fonts on this page are provided by Google Fonts, and created by Julieta Ulanovsky and David Perry.

Using Prism for syntax highlighting.

And of course, thanks d3.js for creating such a lovely project and Mike Bostock for providing examples on how to make your own components.