block by emeeks 8855733967174fe4b1b4

d3.svg.legend example

Full Screen

d3.svg.legend provides for a simple legend that can be displayed horizontally or vertically and accepts a few different d3 scale types.

index.html

<html xmlns="//www.w3.org/1999/xhtml">
<head>
  <title>D3 Legend</title>
  <meta charset="utf-8" />
</head>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/colorbrewer.v1.min.js"></script>
<script src="legend.js"></script>
<style>
  body, html {
    width:100%;
    height:100%;
  }
  #vizcontainer {
    width:100%;
    height:100%;
  }
  svg {
    width: 100%;
    height: 100%;
  }
</style>
<body onload="legendDemo()">

<div id="vizcontainer">
<svg></svg>
</div>
  <footer>
<script>
  function legendDemo() {

  sampleNumerical = [1,2.5,5,10,20];
  sampleThreshold=d3.scale.threshold().domain(sampleNumerical).range(colorbrewer.Reds[5]);
  horizontalLegend = d3.svg.legend().units("Miles").cellWidth(80).cellHeight(25).inputScale(sampleThreshold).cellStepping(100);

  d3.select("svg").append("g").attr("transform", "translate(50,70)").attr("class", "legend").call(horizontalLegend);

  sampleCategoricalData = ["Something","Something Else", "Another", "This", "That", "Etc"]
  sampleOrdinal = d3.scale.category20().domain(sampleCategoricalData);

  verticalLegend = d3.svg.legend().labelFormat("none").cellPadding(5).orientation("vertical").units("Things in a List").cellWidth(25).cellHeight(18).inputScale(sampleOrdinal).cellStepping(10);

  d3.select("svg").append("g").attr("transform", "translate(50,140)").attr("class", "legend").call(verticalLegend);

  }
</script>
  </footer>
</body>
</html>

legend.js

d3.svg.legend = function() {
    
    var legendValues=[{color: "red", stop: [0,1]},{color: "blue", stop: [1,2]},{color: "purple", stop: [2,3]},{color: "yellow", stop: [3,4]},{color: "Aquamarine", stop: [4,5]}];
    var legendScale;
    var cellWidth = 30;
    var cellHeight = 20;
    var adjustable = false;
    var labelFormat = d3.format(".01f");
    var labelUnits = "units";
    var lastValue = 6;
    var changeValue = 1;
    var orientation = "horizontal";
    var cellPadding = 0;
   
    function legend(g) {
    
    function cellRange(valuePosition, changeVal) {
    legendValues[valuePosition].stop[0] += changeVal;
    legendValues[valuePosition - 1].stop[1] += changeVal;
    redraw();
    }

    function redraw() {
        
        g.selectAll("g.legendCells").data(legendValues).exit().remove();
        g.selectAll("g.legendCells").select("rect").style("fill", function(d) {return d.color});
        if (orientation == "vertical") {
            g.selectAll("g.legendCells").select("text.breakLabels").style("display", "block").style("text-anchor", "start").attr("x", cellWidth + cellPadding).attr("y", 5 + (cellHeight / 2)).text(function(d) {return labelFormat(d.stop[0]) + (d.stop[1].length > 0 ? " - " + labelFormat(d.stop[1]) : "")})
            g.selectAll("g.legendCells").attr("transform", function(d,i) {return "translate(0," + (i * (cellHeight + cellPadding)) + ")" });
        }
        else {
            g.selectAll("g.legendCells").attr("transform", function(d,i) {return "translate(" + (i * cellWidth) + ",0)" });
            g.selectAll("text.breakLabels").style("text-anchor", "middle").attr("x", 0).attr("y", -7).style("display", function(d,i) {return i == 0 ? "none" : "block"}).text(function(d) {return labelFormat(d.stop[0])});
        }
    }
    g.selectAll("g.legendCells")
    .data(legendValues)
    .enter()
    .append("g")
    .attr("class", "legendCells")
    .attr("transform", function(d,i) {return "translate(" + (i * (cellWidth + cellPadding)) + ",0)" })
    
    g.selectAll("g.legendCells")
    .append("rect")
    .attr("height", cellHeight)
    .attr("width", cellWidth)
    .style("fill", function(d) {return d.color})
    .style("stroke", "black")
    .style("stroke-width", "2px");

    g.selectAll("g.legendCells")
    .append("text")
    .attr("class", "breakLabels")
    .style("pointer-events", "none");
    
    g.append("text")
    .text(labelUnits)
    .attr("y", -7);
    
    redraw();
    }
    
    legend.inputScale = function(newScale) {
        if (!arguments.length) return scale;
            scale = newScale;
            legendValues = [];
            if (scale.invertExtent) {
                //Is a quantile scale
                scale.range().forEach(function(el) {
                    var cellObject = {color: el, stop: scale.invertExtent(el)}
                    legendValues.push(cellObject)
                })
            }
            else {
                scale.domain().forEach(function (el) {
                    var cellObject = {color: scale(el), stop: [el,""]}
                    legendValues.push(cellObject)
                })
            }
            return this;
    }
    
    legend.scale = function(testValue) {
        var foundColor = legendValues[legendValues.length - 1].color;
        for (el in legendValues) {
            if(testValue < legendValues[el].stop[1]) {
                foundColor = legendValues[el].color;
                break;
            }
        }
        return foundColor;
    }

    legend.cellWidth = function(newCellSize) {
        if (!arguments.length) return cellWidth;
            cellWidth = newCellSize;
            return this;
    }

    legend.cellHeight = function(newCellSize) {
        if (!arguments.length) return cellHeight;
            cellHeight = newCellSize;
            return this;
    }

    legend.cellPadding = function(newCellPadding) {
        if (!arguments.length) return cellPadding;
            cellPadding = newCellPadding;
            return this;
    }
    
    legend.cellExtent = function(incColor,newExtent) {
        var selectedStop = legendValues.filter(function(el) {return el.color == incColor})[0].stop;
        if (arguments.length == 1) return selectedStop;
            legendValues.filter(function(el) {return el.color == incColor})[0].stop = newExtent;
            return this;
    }
    
    legend.cellStepping = function(incStep) {
        if (!arguments.length) return changeValue;
            changeValue = incStep;
            return this;
    }
    
    legend.units = function(incUnits) {
        if (!arguments.length) return labelUnits;
            labelUnits = incUnits;
            return this;
    }
    
    legend.orientation = function(incOrient) {
        if (!arguments.length) return orientation;
            orientation = incOrient;
            return this;
    }

    legend.labelFormat = function(incFormat) {
        if (!arguments.length) return labelFormat;
            labelFormat = incFormat;
            if (incFormat == "none") {
                labelFormat = function(inc) {return inc};
            }
            return this;
    }

return legend;    
    
}