user6020020
user6020020

Reputation:

Heatmap does not show the first rect

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:

enter image description here

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

Answers (1)

Mark
Mark

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

Related Questions