请参阅此示例:http://bl.ocks.org/tjdecke/5558084
我想创建一个52行和7列的热图。 52行代表一年中的52周,7列代表一周中的7天。
使用这样的数据集:(在下面发布缩写版本)。 “天”表示一周中的7天,里面的数字表示一天内的活动数量。 “总数”表示一周内的活动总数。 “周”似乎是各种各样的时间戳。
但是,我很难弄清楚如何创建网格,因为示例数据集使用带有7个值的d.day和带有24个值的d.hour来创建网格。具体来说,我应该如何处理days数组?
我不知道如何处理json值,例如,如何定义我的变量以使用此数据集。
[
{
"days": [
0,
0,
0,
0,
0,
1,
0
],
"total": 1,
"week": 1457827200
},
{
"days": [
0,
0,
0,
1,
0,
3,
1
],
"total": 5,
"week": 1458432000
},
{
"days": [
1,
0,
0,
1,
5,
0,
1
],
"total": 8,
"week": 1459036800
},
{
"days": [
0,
0,
0,
2,
0,
1,
1
],
"total": 4,
"week": 1459641600
},
{
"days": [
0,
1,
3,
0,
2,
0,
0
],
"total": 6,
"week": 1460246400
},
{
"days": [
0,
1,
1,
2,
2,
0,
0
],
"total": 6,
"week": 1460851200
},
{
"days": [
1,
0,
3,
0,
2,
1,
0
],
"total": 7,
"week": 1461456000
},
{
"days": [
0,
0,
0,
0,
0,
0,
0
],
"total": 0,
"week": 1462060800
}
]
d3.json("/data/frequency.json", function (error, data) {
// NOT SURE, PROBABLY WRONG
data.forEach(function(d) {
ddays = +d.days;
total = +d.total;
week = +d.week;
});
// define range!!!
var x = d3.scaleLinear().domain([0, data.length]).range([0, width]);
//52 weeks
var y = d3.scaleLinear()
.domain([0, 52])
.rangeRound([height, 0]);
// Generate rectangle for each json object
var rectangles = svg.selectAll('rect')
.data(data)
.enter()
.append('rect')
.attr("x", function(d, index) {
return x(index); }) //WRONG!!
.attr("y", function(d, index) {
return y; }) // WRONG!!
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", 'black')
.attr("class", "bordered");
答案 0 :(得分:1)
使用嵌套数据,您可以先为每个对象附加组元素,以便每周在网格中创建一个“行”,根据其索引得到y坐标。
然后对于每一行,根据对象中的days数组追加rects。
诀窍是做两个data()连接,第二个连接从已经连接的数据中访问days数组。
例如:
let data = [
{
"days": [
0,
0,
0,
0,
0,
1,
0
],
"total": 1,
"week": 1457827200
},
{
"days": [
0,
0,
0,
1,
0,
3,
1
],
"total": 5,
"week": 1458432000
},
{
"days": [
1,
0,
0,
1,
5,
0,
1
],
"total": 8,
"week": 1459036800
},
{
"days": [
0,
0,
0,
2,
0,
1,
1
],
"total": 4,
"week": 1459641600
},
{
"days": [
0,
1,
3,
0,
2,
0,
0
],
"total": 6,
"week": 1460246400
},
{
"days": [
0,
1,
1,
2,
2,
0,
0
],
"total": 6,
"week": 1460851200
},
{
"days": [
1,
0,
3,
0,
2,
1,
0
],
"total": 7,
"week": 1461456000
},
{
"days": [
0,
0,
0,
0,
0,
0,
0
],
"total": 0,
"week": 1462060800
}
]
let gridSize = 20;
let width = (gridSize + 1) * 7;
let height = (gridSize + 1) * data.length;
// define range!!!
var x = d3.scaleLinear()
.domain([0, 7])
.range([0, width]);
//52 weeks
var y = d3.scaleLinear()
.domain([0, data.length])
.rangeRound([height, 0]);
let svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
// Generate rows for each json object
var rows = svg.selectAll('.row')
.data(data)
.enter()
.append('g')
.attr("transform", function(d, i){
return "translate(0," + y(i) + ")"
})
// Generate rects for the array of days per object
let box = rows.selectAll("rect")
.data(function(d){ return d.days })
.enter()
.append("rect")
.attr("x", function(d, i) { return x(i); })
.attr("width", gridSize)
.attr("height", gridSize)
.style("fill", 'black')
.attr("class", "bordered");
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<body>
</body>