简体   繁体   中英

D3 heatmap color range updating with slider

I am using D3 and the JQuery Slider to produce an heatmap whose colors are automatically refreshed when I change the position of the cursor of the slider (which represents the color scale range). Although it works fine when i first click on the slider, it doesn't seem to refresh afterwards. I post the source in case you would like to point out my mistake:

<HEAD>
<TITLE>Heatmap</TITLE>
</HEAD>
<BODY BGCOLOR="WHITE">

<CENTER>
<H1>Heatmap</H1>

<H5>Heatmap should instantly display bidimensional data (adjustable thresholds)</H5>




<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.9.2/themes/base/jquery-ui.css" />
<script src="http://code.jquery.com/jquery-1.8.3.js"></script>
<script src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css" />

<div id="slider"></div>
<p>
 <div id="heatmap"></div>

<script>

var minval= 0;
var maxval= 1000;


$( "#slider" ).slider({
    range: true,
    min: 0,
    max: 1000,
    values: [0, 1000],
    slide: function( event, ui ) {
      var minval = ui.values[0];
      var maxval = ui.values[1];
      console.log("begin:", minval, "end:", maxval);
      draw(minval, maxval); 
    }
});


var margin = {top: 0, right: 20, bottom: 20, left: 20},
    width = 300 - margin.left - margin.right,
    height = 300 - margin.top - margin.bottom;

var svg = d3.select("#heatmap").append("svg:svg");

var data = [[1000,500,1],[500,1,1000],[1000,54,800]];

var x = d3.scale.linear()
    .range([0, width])
    .domain([0,data[0].length]);

var y = d3.scale.linear()
    .range([0, height])
    .domain([0,data.length]);

svg.attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var colorLow = 'white', colorMed = 'green', colorHigh = 'red';


function draw(minval,maxval){

    var colorScale = d3.scale.linear()
         .domain([minval, maxval])
         .range([colorLow, colorHigh]);

    var row = svg.selectAll(".row")
            .data(data)
            .enter().append("svg:g")
            .attr("class", "row");

    var col = row.selectAll(".cell")
               .data(function (d,i) { return d.map(function(a) { return {value: a, row: i}; } ) })
               .enter().append("svg:rect")
                 .attr("class", "cell")
                 .attr("x", function(d, i) { return x(i); })
                 .attr("y", function(d, i) { return y(d.row); })
                 .attr("width", x(1))
                 .attr("height", y(1))
                 .style("fill", function(d) { return colorScale(d.value); });

}



</script>
</head>
<body>

</CENTER>
</body>

It doesn't work the second time because you are operating on the .enter() selection, which will be empty the second time draw() is called because the elements exist already.

To fix this, move the declaration of row and col outside the draw() function. Inside the draw() function, only keep the code that actually changes. Something like

function draw(minval,maxval){
    var colorScale = d3.scale.linear()
         .domain([minval, maxval])
         .range([colorLow, colorHigh]);
    col.style("fill", function(d) { return colorScale(d.value); });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM