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

为君一笑 提交于 2020-01-05 05:00:10

问题


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();
});


回答1:


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);


来源:https://stackoverflow.com/questions/39323096/displaying-values-associated-with-each-color-gradient-mapped-from-range-in-d3-le

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!