TheEmperor
TheEmperor

Reputation: 355

Displaying values associated with each color gradient mapped from range in D3 legend

I'm trying to draw a heatmap using D3. So far I was able to draw one by modifying the code from http://bl.ocks.org/tjdecke/5558084. At the moment, my legend is only showing two colors; yellow (for value 0) and red (for value 1). I would like to display the legend showing all the color gradient from yellow to red and the value associated with each color. Can someone help me with this? Part of the code is shown below. Thank you

// X-axis labels
// This has to be generated dynamically
loop_ids1 = ["HL_1S72_010", "HL_1S72_039", "HL_1S72_005", "HL_1VX6_037", "HL_2A64_002", "HL_2GDI_002", "HL_2GDI_004", "HL_2HOJ_002", "HL_2QBG_011", "HL_3DHS_002", "HL_3J7A_004", "HL_3U5F_006", "HL_3U5H_005", "HL_4A1B_005", "HL_4A1B_037", "HL_4BPP_006", "HL_4CUV_005", "HL_4CUX_006", "HL_4IOA_009", "HL_4QCN_009", "HL_4W21_039"];

// Y-axis labels
// This has to be generated dynamically
loop_ids2 = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21" ];
// Open and load the csv file
d3.csv("disc_parsed.csv", function(error, data) {
  data.forEach(function(d) {
    loop_id1 = d.loop_id1;
    loop_id2 = d.loop_id2;
    coordx = +d.coordx
    coordy = +d.coordy
    discrepancy = +d.discrepancy;
    //console.log(d.discrepancy);
  });

  //var colorScale = d3.scale.quantile()
          //.domain([0, buckets - 1, d3.max(data, function (d) { return d.discrepancy; })])
          //.range(colors);
  var colorScale = d3.scale.linear()
    .domain([0,1])
    .range(['yellow', 'red'])
  // Set the svg container
  var svg = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  // Draw the x-axis label
  var dayLabels = svg.selectAll(".dayLabel")
    .data(loop_ids1)
    .enter().append("text")
    .text(function(d) {
      return d;
    })
    .attr("x", 0)
    .attr("y", function(d, i) {
      return i * gridSize;
    })
    .style("text-anchor", "end")
    .attr("transform", "translate(-5," + gridSize / 1.5 + ")")
    .attr("class", function(d, i) { console.log(i);
      return ((i >= 0) 
        ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis");
    });
  // Draw the y-axis label
  var timeLabels = svg.selectAll(".timeLabel")
    .data(loop_ids2)
    .enter().append("text")
    //.attr("font-size", 12)
    //.attr("glyph-orientation-vertical: 180")
    .text(function(d) {
      return d;
    })
    .attr("x", function(d, i) {
      return  (i * gridSize);
    })
    .attr("y", 0)
    .style("text-anchor", "middle")
    .attr("transform", "translate(" + gridSize / 2 + '-5' + ")")
    .attr("class", function(d, i) {
      return ((i >= 0) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis");
    });
  // Create the paired elements
  var heatMap = svg.selectAll(".coordy")
    .data(data, function(d) { return d.coordx+':'+d.coordy;});

  // Draw the grid to make the heatmap
  heatMap.enter().append("rect")
    .attr("x", function(d) { return d.coordy * gridSize; })
    .attr("y", function(d) { return d.coordx * gridSize; })
    .attr("rx", 4)
    .attr("ry", 4)
    .attr("class", "bordered")
    .attr("width", gridSize)
    .attr("height", gridSize)
    .style("fill", function(d) {
        return colorScale(d.discrepancy);
    });
  // Show the value of discrepancy between two motifs when the user hovers over a heatmap grid
  heatMap.append("title").text(function(d) {
    return d.loop_id1 + ':' + d.loop_id2 + ' = ' + d.discrepancy;
  });
  heatMap.exit().remove();
  var legend = svg.selectAll(".legend")
    .data(colorScale.domain())
  legend.enter().append("g")
    .attr("class", "legend");
  // Draw the legend 
  legend.append("rect")
    .attr("x", function(d, i) {
      return legendElementWidth * i;
    })
    .attr("y", height)
    .attr("width", legendElementWidth)
    .attr("height", gridSize / 2)
    .style("fill", function(d) {
      return colorScale(d);
    });
  // Add text to the legend
  legend.append("text")
    .attr("class", "mono")
    .text(function(d) {
      return (d);
    })
    .attr("x", function(d, i) {
      return legendElementWidth * i;
    })
    .attr("y", height + gridSize);
  legend.exit().remove();
});

Upvotes: 1

Views: 1710

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

The problem is the data used for the legends:

var legend = svg.selectAll(".legend")
    .data(colorScale.domain());

Right now, your data is an array containing only 2 values, 0 and 1, because of this snippet:

var colorScale = d3.scale.linear()
    .domain([0,1])

What happened in the original code? In the original code, the author created an array with several values, using the quantiles() function:

var legend = svg.selectAll(".legend")
    .data([0].concat(colorScale.quantiles()), function(d) { return d; });

Solution:

You have several different solutions here, the easier and uglier one being simply hardcoding your data. So, if you want a legend with 6 rectangles:

var dataLegend = [0, 0.2, 0.4, 0.6, 0.8, 1];
var legend = svg.selectAll(".legend")
    .data(dataLegend);

Upvotes: 2

Related Questions