Reputation:
I created a heatmap from some data contained in the data.csv file.
Here is the code.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Heatmap</title>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
</head>
<body>
<div id="heatmap"></div>
<script src="./heatmap.js"></script>
</body>
</html>
script.js:
var itemSize = 15;
var cellSize = itemSize - 1;
var margin = {top: 50, right: 20, bottom: 20, left: 150};
var width = 445 - margin.right - margin.left;
var height = 430 - margin.top - margin.bottom;
var svg = d3.select('#heatmap')
.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 + ')');
var colorScale = d3.scaleLinear()
.domain([0, 85, 100])
.range(['white', 'tomato', 'steelblue']);
svg.append('defs')
.append('pattern')
.attr('id', 'pattern-stripes')
.attr('patternUnits', 'userSpaceOnUse')
.attr('patternTransform', 'rotate(45)')
.attr('width', 3)
.attr('height', 3)
.append('rect')
.attr('width', 1)
.attr('height', 3)
.attr('transform', 'translate(0, 0)')
.attr('fill', 'black');
d3.queue()
.defer(d3.csv, './data.csv')
.await(create);
function create(err, data) {
if(err) {
console.log('Error loading files:', err);
throw error;
}
var data = data.map(function(item) {
var newItem = {};
newItem.nuts_id = item.NUTS_ID;
newItem.nuts_name = item.NUTS_NAME;
newItem.year = item.YEAR;
newItem.valuePol = item.POL;
return newItem;
});
var years = data.map(function(d) {
return d.year;
});
var x_elements = d3.set(years).values();
var nuts_names = data.map(function(d) {
return d.nuts_name;
});
var y_elements = d3.set(nuts_names).values();
var xScale = d3.scaleBand()
.domain(x_elements)
.range([0, x_elements.length * itemSize]);
var xAxis = d3.axisTop(xScale)
.tickFormat(function(d) {
return d; // d is the year
});
var yScale = d3.scaleBand()
.domain(y_elements)
.range([0, y_elements.length * itemSize]);
var yAxis = d3.axisLeft(yScale)
.tickFormat(function(d) {
return d; // d is the region
});
var cells = svg.selectAll('rect')
.data(data)
.enter()
.append('g')
.append('rect')
.attr('class', 'cell')
.attr('width', cellSize)
.attr('height', cellSize)
.attr('x', function(d) {
return xScale(d.year);
})
.attr('y', function(d) {
return yScale(d.nuts_name);
})
.attr('fill', function(d) {
var col;
if(d.valuePol == '') {
col = 'url(#pattern-stripes)';
}
else {
col = colorScale(d.valuePol);
}
return col;
});
svg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.selectAll('text')
.attr('font-weight', 'normal');
svg.append('g')
.attr('class', 'x axis')
.call(xAxis)
.selectAll('text')
.attr('font-weight', 'normal')
.style('text-anchor', 'start')
.attr('dx', '.8em')
.attr('dy', '.5em')
.attr('transform', function(d) {
return 'rotate(-65)';
});
}
Working code on PLUNKER.
This is the restult:
The heatmap is created correctly except for the first rect that is not shown.
Yet the data are picked up in the right way, so where is the problem? I don't understand..
Upvotes: 1
Views: 142
Reputation: 108537
I know this is a duplicate but I can't find one that matches so...
Never do a blind selectAll by element name:
svg.selectAll('rect')
There are other rect
elements within your SVG that are being included causing strange behavior. Instead do:
svg.selectAll('.cell')
.data(data)
.enter()
This targets the selection to what you are really binding your data to.
Updated plunker.
Upvotes: 1