D3 v4网格:如何正确绑定数据



我一直在d3中使用方形网格来显示78个单独事件的颜色编码原因。加载时,我只有一个黑色方块显示,似乎d.x和d.y的定位没有通过,我不完全确定为什么。

d3.tsv("platform.tsv", function(data) {
for (var i = 0; i < data.length; i++) {
console.log(data[i].report_num);
console.log(data[i].platform_medium);
}
var platformData = getWords(data);
var squareSize = 20;
var squarePad =5;
var numPerRow = width / (squareSize + squarePad);
var margin = {top: 10, right: 30, bottom: 30, left: 60};
var width = 750 - margin.left - margin.right;
var height = 520 - margin.top - margin.bottom;
function getWords(data) {
return data.map(function (d, i) {
// what category is this report?
d.platform_medium = d.platform_medium;
// sequential of report number
d.report_num = +d.report_num;
// positioning for square visual
// stored here to make it easier
// to keep track of.
d.col = i % numPerRow;
d.x = d.col * (squareSize + squarePad);
d.row = Math.floor(i / numPerRow);
d.y = d.row * (squareSize + squarePad);
return d;
});
}
var gridvis = d3.select("#chart2")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var gridFill7 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill7")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#C4E538");
var gridFill8 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill8")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#EE5A24");

// square grid
// @v4 Using .merge here to ensure
// new and old data have same attrs applied
var squares = gridvis.selectAll('.square').data(platformData, function (d) { return d.report_num; });
var squaresE = squares.enter()
.append('rect')
.classed('square', true);
var squares = squares.merge(squaresE)
.attr('width', squareSize)
.attr('height', squareSize)
.attr('fill', '#fff')
.classed('fill-square', function (d) { return d.platform_medium; })
.attr('x', function (d) { return d.x;})
.attr('y', function (d) { return d.y;})
.attr('opacity', 0);

function highlightGrid() {
gridvis.selectAll('.fill-square')
.transition()
.duration(800)
.attr('opacity', 1.0)
.attr('fill', function (d) { 
if (d.platform_medium===1) {return "#0652DD";}
else if (d.platform_medium===2) {return "#9980FA";}
else if (d.platform_medium===3) {return "#C4E538";}
else if (d.platform_medium===4) {return "#ED4C67";}
else if (d.platform_medium===5) {return "#F79F1F";}
else if (d.platform_medium===6) {return "#EE5A24";}
else if (d.platform_medium===7) {return "url(#gridfill7)";}
else if (d.platform_medium===8) {return "url(#gridfill8)";}
});
}
highlightGrid();
});

以下是我的样本数据。如果有比我更有经验的人来看一看,我将不胜感激:(

report_num  covid_related   platform_medium
1   0   1
2   0   1
3   0   1
4   0   1
5   0   1
6   0   3
7   0   1
8   0   3
9   0   1
10  0   3
11  0   1
12  0   3
13  1   2
14  1   1
15  1   3
16  1   1
17  1   1
18  1   1
19  1   1
20  1   1
21  1   1
22  1   1
23  1   1
24  0   1
25  0   7
26  1   1
27  1   1
28  1   1
29  1   1
30  1   1
31  1   1
32  1   1
33  1   1
34  1   1
35  1   1
36  0   1
37  0   1
38  0   2
39  0   7
40  1   1
41  1   1
42  1   1
43  1   1
44  1   1
45  1   1
46  0   5
47  0   5
48  0   1
49  0   1
50  0   1
51  0   1
52  1   1
53  1   1
54  1   1
55  0   1
56  0   5
57  0   1
58  0   1
59  0   1
60  0   1
61  0   7
62  0   1
63  0   1
64  0   1
65  0   1
66  0   1
67  1   5
68  1   1
69  1   1
70  1   3
71  1   3
72  1   1
73  1   1
74  1   7
75  1   8
76  1   1
77  1   4
78  1   2

有几个问题导致了问题。如果你检查页面,你会发现你已经附加了所有的矩形,但x,y属性是NaN。如果我们回溯,我们会发现numPerRow:中有一个未定义的值

var platformData = getWords(data);
...
var numPerRow = width / (squareSize + squarePad);
...
var width = 750 - margin.left - margin.right;

当您调用getWords时,widthnumPerRow都没有定义,而getWords需要两者。此外,定义numPerRow时没有定义width,因此numPerRow也应该是未定义的,这意味着在getWords中,我们将undefined分配给d.x和d.y,这意味着您所有矩形都被附加到相同的位置:[0,0](在父g内(。

为此,我们确保在定义numPerRow之前定义width,在定义其他两个之后调用getWords。现在我们有了一个矩形的排列(我还修改了父g上的平移,这样左上角的矩形就不在屏幕的中间(:

var data = d3.csvParse(d3.select("pre").remove().text());


var squareSize = 20;
var squarePad =5;

var margin = {top: 10, right: 30, bottom: 30, left: 60};
var width = 750 - margin.left - margin.right;
var height = 520 - margin.top - margin.bottom;
var numPerRow = width / (squareSize + squarePad);
function getWords(data) {
return data.map(function (d, i) {
// what category is this report?
d.platform_medium = d.platform_medium;
// sequential of report number
d.report_num = +d.report_num;
// positioning for square visual
// stored here to make it easier
// to keep track of.
d.col = i % numPerRow;
d.x = d.col * (squareSize + squarePad);
d.row = Math.floor(i / numPerRow);
d.y = d.row * (squareSize + squarePad);
return d;
});
}

var platformData = getWords(data);

var gridvis = d3.select("#chart2")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var gridFill7 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill7")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#C4E538");
var gridFill8 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill8")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#EE5A24");

// square grid
// @v4 Using .merge here to ensure
// new and old data have same attrs applied
var squares = gridvis.selectAll('.square').data(platformData, function (d) { return d.report_num; });
var squaresE = squares.enter()
.append('rect')
.classed('square', true);
var squares = squares.merge(squaresE)
.attr('width', squareSize)
.attr('height', squareSize)
.attr('fill', '#fff')
.classed('fill-square', function (d) { return d.platform_medium; })
.attr('x', function (d) { return d.x;})
.attr('y', function (d) { return d.y;})
.attr('opacity', 0);

function highlightGrid() {
gridvis.selectAll('.fill-square')
.transition()
.duration(800)
.attr('opacity', 1.0)
.attr('fill', function (d) { 
if (d.platform_medium===1) {return "#0652DD";}
else if (d.platform_medium===2) {return "#9980FA";}
else if (d.platform_medium===3) {return "#C4E538";}
else if (d.platform_medium===4) {return "#ED4C67";}
else if (d.platform_medium===5) {return "#F79F1F";}
else if (d.platform_medium===6) {return "#EE5A24";}
else if (d.platform_medium===7) {return "url(#gridfill7)";}
else if (d.platform_medium===8) {return "url(#gridfill8)";}
});
}
highlightGrid();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart2"></div>
<pre>report_num,covid_related,platform_medium
1,0,1
2,0,1
3,0,1
4,0,1
5,0,1
6,0,3
7,0,1
8,0,3
9,0,1
10,0,3
11,0,1
12,0,3
13,1,2
14,1,1
15,1,3
16,1,1
17,1,1
18,1,1
19,1,1
20,1,1
21,1,1
22,1,1
23,1,1
24,0,1
25,0,7
26,1,1
27,1,1
28,1,1
29,1,1
30,1,1
31,1,1
32,1,1
33,1,1
34,1,1
35,1,1
36,0,1
37,0,1
38,0,2
39,0,7
40,1,1
41,1,1
42,1,1
43,1,1
44,1,1
45,1,1
46,0,5
47,0,5
48,0,1
49,0,1
50,0,1
51,0,1
52,1,1
53,1,1
54,1,1
55,0,1
56,0,5
57,0,1
58,0,1
59,0,1
60,0,1
61,0,7
62,0,1
63,0,1
64,0,1
65,0,1
66,0,1
67,1,5
68,1,1
69,1,1
70,1,3
71,1,3
72,1,1
73,1,1
74,1,7
75,1,8
76,1,1
77,1,4
78,1,2</pre>

但是,矩形没有任何填充。这是因为当你处理数据时,你会把d.platform_medium作为一个字符串:

d.platform_medium = d.platform_medium;

当填充矩形时,使用===;4〃!==4.我们可以使用==或将字符串转换为数字。我在下面做后者:

var data = d3.csvParse(d3.select("pre").remove().text());


var squareSize = 20;
var squarePad =5;

var margin = {top: 10, right: 50, bottom: 30, left: 60};
var width = 750 - margin.left - margin.right;
var height = 520 - margin.top - margin.bottom;
var numPerRow = width / (squareSize + squarePad);
function getWords(data) {
return data.map(function (d, i) {
// what category is this report?
d.platform_medium = +d.platform_medium;
// sequential of report number
d.report_num = +d.report_num;
// positioning for square visual
// stored here to make it easier
// to keep track of.
d.col = i % numPerRow;
d.x = d.col * (squareSize + squarePad);
d.row = Math.floor(i / numPerRow);
d.y = d.row * (squareSize + squarePad);
return d;
});
}

var platformData = getWords(data);

var gridvis = d3.select("#chart2")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var gridFill7 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill7")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill7.append("stop")
.attr("offset", "50%")
.style("stop-color", "#C4E538");
var gridFill8 = gridvis.append("defs")
.append("linearGradient")
.attr("id", "gridFill8")
.attr("x1", "0%")
.attr("x2", "0%")
.attr("y1", "100%")
.attr("y2", "0%");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#0652DD");
gridFill8.append("stop")
.attr("offset", "50%")
.style("stop-color", "#EE5A24");

// square grid
// @v4 Using .merge here to ensure
// new and old data have same attrs applied
var squares = gridvis.selectAll('.square').data(platformData, function (d) { return d.report_num; });
var squaresE = squares.enter()
.append('rect')
.classed('square', true);
var squares = squares.merge(squaresE)
.attr('width', squareSize)
.attr('height', squareSize)
.attr('fill', '#fff')
.classed('fill-square', function (d) { return d.platform_medium; })
.attr('x', function (d) { return d.x;})
.attr('y', function (d) { return d.y;})
.attr('opacity', 0);

function highlightGrid() {
gridvis.selectAll('.fill-square')
.transition()
.duration(800)
.attr('opacity', 1.0)
.attr('fill', function (d) { 
if (d.platform_medium===1) {return "#0652DD";}
else if (d.platform_medium===2) {return "#9980FA";}
else if (d.platform_medium===3) {return "#C4E538";}
else if (d.platform_medium===4) {return "#ED4C67";}
else if (d.platform_medium===5) {return "#F79F1F";}
else if (d.platform_medium===6) {return "#EE5A24";}
else if (d.platform_medium===7) {return "url(#gridfill7)";}
else if (d.platform_medium===8) {return "url(#gridfill8)";}
});
}
highlightGrid();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart2"></div>
<pre>report_num,covid_related,platform_medium
1,0,1
2,0,1
3,0,1
4,0,1
5,0,1
6,0,3
7,0,1
8,0,3
9,0,1
10,0,3
11,0,1
12,0,3
13,1,2
14,1,1
15,1,3
16,1,1
17,1,1
18,1,1
19,1,1
20,1,1
21,1,1
22,1,1
23,1,1
24,0,1
25,0,7
26,1,1
27,1,1
28,1,1
29,1,1
30,1,1
31,1,1
32,1,1
33,1,1
34,1,1
35,1,1
36,0,1
37,0,1
38,0,2
39,0,7
40,1,1
41,1,1
42,1,1
43,1,1
44,1,1
45,1,1
46,0,5
47,0,5
48,0,1
49,0,1
50,0,1
51,0,1
52,1,1
53,1,1
54,1,1
55,0,1
56,0,5
57,0,1
58,0,1
59,0,1
60,0,1
61,0,7
62,0,1
63,0,1
64,0,1
65,0,1
66,0,1
67,1,5
68,1,1
69,1,1
70,1,3
71,1,3
72,1,1
73,1,1
74,1,7
75,1,8
76,1,1
77,1,4
78,1,2</pre>

我使用了d3.csvParse和一个pre来保存数据(而不是d3.tsv(,这样它就可以放在一个片段中-否则,对问题中代码的所有更改都在上面记录了

最新更新