Reputation: 467
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>
Upvotes: 1
Views: 2997
Reputation: 109232
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); });
}
Upvotes: 3