我是d3图表和javascript的新手,这是一场艰苦的战斗。
经过一番研究,我能够用CSV文件填充图表。现在,我正在尝试使用json
数据填充图表。
这是我的代码。它松散地基于this example。但我更喜欢使用我的代码(即d3.v4):
var width = 960,
height = 136,
cellSize = 17;
var color = d3.scaleQuantize()
.domain([9000, 12000])
.range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateParse = d3.timeFormat("%Y-%m-%d");
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(2017, 2018))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");
svg.append("text")
.attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.text(function(d) {
return d;
});
var rect = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#ccc")
.selectAll("rect")
.data(function(d) {
return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
})
.attr("y", function(d) {
return d.getDay() * cellSize;
})
.datum(d3.timeFormat("%Y-%m-%d"));
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(function(d) {
return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("path")
.attr("d", pathMonth);
d3.json("data3.json", function(error, data) {
//populating data since i don't have the file
data = [{
"date": "2017-01-04",
"open": 10430.69
}, {
"date": "2017-01-05",
"open": 10584.56
}];
data.forEach(function(d) {
d.dd = dateParse(new Date(d.date));
console.log(d.dd);
});
var nest = d3.nest()
.key(function(d) {
return d.dd;
})
.map(data);
rect.filter(function(d) {
return d in data;
})
.attr("fill", function(d) {
return color(data[d]);
})
.append("title")
.text(function(d) {
return d + ": " + data[d];
});
});
function pathMonth(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(),
w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
d1 = t1.getDay(),
w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
"H" + w0 * cellSize + "V" + 7 * cellSize +
"H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
"H" + (w1 + 1) * cellSize + "V" + 0 +
"H" + (w0 + 1) * cellSize + "Z";
}
<script src="http://d3js.org/d3.v4.min.js"></script>
答案 0 :(得分:2)
您的代码需要进行一些更改才能正常工作。与d3 v3相比,这些主要与使用data
代替nest
以及d3 v4中的微小更改(我无法找到相关信息)有关。
过滤强>
首先,您没有正确过滤数据:
您不希望像这样过滤:
return d in data;
in
运算符用于对象的属性,data
是一个数组。
您希望通过嵌套进行过滤(如示例中所示):
return d in nest;
其次,至少在我的简短测试中,d3.nest在d3 v4中表现略有不同(这可能取决于版本,我在下面的代码段中使用了4.9.1(min))。当使用以数字开头的键时,d3似乎在使用d3.nest时在每个键的开头附加一个美元符号:
D3v4示例:
data = [{
"date": "2017-01-04", "open": 10430.69
}, {
"date": "2017-01-05", "open": 10584.56
}];
var nest = d3.nest()
.key(function(d) { return d.date; })
.map(data);
console.log(nest);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
与D3v3相比:
data = [{
"date": "2017-01-04", "open": 10430.69
}, {
"date": "2017-01-05", "open": 10584.56
}];
var nest = d3.nest()
.key(function(d) { return d.date; })
.map(data);
console.log(nest);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
&#13;
如果您看到此行为,则需要相应更改过滤器:
return ("$" + d) in nest;
访问Nest属性
第三,由于data
只是一个数组,data[d]
不太可能获得所需的结果,因为d
将是一个日期字符串,您需要访问nest
宾语。记录nest
可能有助于找到合适的属性。而不是:
return color(data[d]);
尝试:
return color(nest[("$" + d)][0].open);
这与问题中的链接示例非常相似(除了美元符号之外)。
<强>优化强>
与您最近的其他question相关,此代码
var date = "2017-01-02";
var dateParse = d3.timeFormat("%Y-%m-%d");
console.log(dateParse(new Date(date)));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
什么都不做。它接受一个表示日期的字符串并将其转换为日期对象,然后将其转换回您开始使用的相同字符串表示形式。您可以删除这部分代码,它在链接示例中使用,因为它是从m / d / Y日期字符串转换为日期对象,然后转换为Y-m-d日期字符串。您的初始日期格式已经是您想要的格式,因此无需对其进行修改。只使用:
var nest = d3.nest()
.key(function(d) {
return d.date;
})
.map(data);
而不是:
data.forEach(function(d) {
d.dd = dateParse(d.date);
});
var nest = d3.nest()
.key(function(d) {
return d.dd;
})
.map(data);
<强>结果强>
这些更改(我删除了文本以使示例更简单,删除了外部文件引用等)导致:
var width = 960,
height = 136,
cellSize = 17;
var color = d3.scaleQuantize()
.domain([9000, 12000])
.range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateFormat = d3.timeFormat("%Y-%m-%d");
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(2017, 2018))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");
var rect = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#ccc")
.selectAll("rect")
.data(function(d) {
return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
})
.attr("y", function(d) {
return d.getDay() * cellSize;
})
.datum(dateFormat);
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(function(d) {
return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("path")
.attr("d", pathMonth);
data = [{
"date": "2017-01-04",
"open": 10430.69
}, {
"date": "2017-01-05",
"open": 10584.56
}];
var nest = d3.nest()
.key(function(d) {
return d.date;
})
.map(data);
rect.filter(function(d) {
return ("$" + d) in nest;
})
.attr("fill", function(d) {
return color(nest[("$" + d)][0].open);
})
function pathMonth(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(),
w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
d1 = t1.getDay(),
w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
"H" + w0 * cellSize + "V" + 7 * cellSize +
"H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
"H" + (w1 + 1) * cellSize + "V" + 0 +
"H" + (w0 + 1) * cellSize + "Z";
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
答案 1 :(得分:1)
看起来你忘了申报dateParse(并且使用它错了)。
var dateParse = d3.timeParse("%Y-%m-%d");
var width = 960,
height = 136,
cellSize = 17;
var color = d3.scaleQuantize()
.domain([9000, 12000])
.range(["Blue", "Red", "Green", "Yellow", "Purple", "Black"]);
var dateParse = d3.timeParse("%Y-%m-%d");
var svg = d3.select("body")
.selectAll("svg")
.data(d3.range(2017, 2018))
.enter().append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + ((width - cellSize * 53) / 2) + "," + (height - cellSize * 7 - 1) + ")");
svg.append("text")
.attr("transform", "translate(-6," + cellSize * 3.5 + ")rotate(-90)")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.text(function(d) {
return d;
});
var rect = svg.append("g")
.attr("fill", "none")
.attr("stroke", "#ccc")
.selectAll("rect")
.data(function(d) {
return d3.timeDays(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
return d3.timeWeek.count(d3.timeYear(d), d) * cellSize;
})
.attr("y", function(d) {
return d.getDay() * cellSize;
})
.datum(d3.timeFormat("%Y-%m-%d"));
svg.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.selectAll("path")
.data(function(d) {
return d3.timeMonths(new Date(d, 0, 1), new Date(d + 1, 0, 1));
})
.enter().append("path")
.attr("d", pathMonth);
d3.json("data3.json", function(error, data) {
//populating data since i don't have the file
data = [{
"date": "2017-01-04",
"open": 10430.69
}, {
"date": "2017-01-05",
"open": 10584.56
}];
data.forEach(function(d) {
d.dd = dateParse(d.date);
console.log(d.dd);
});
var nest = d3.nest()
.key(function(d) {
return d.dd;
})
.map(data);
rect.filter(function(d) {
return d in data;
})
.attr("fill", function(d) {
return color(data[d]);
})
.append("title")
.text(function(d) {
return d + ": " + data[d];
});
});
function pathMonth(t0) {
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0),
d0 = t0.getDay(),
w0 = d3.timeWeek.count(d3.timeYear(t0), t0),
d1 = t1.getDay(),
w1 = d3.timeWeek.count(d3.timeYear(t1), t1);
return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize +
"H" + w0 * cellSize + "V" + 7 * cellSize +
"H" + w1 * cellSize + "V" + (d1 + 1) * cellSize +
"H" + (w1 + 1) * cellSize + "V" + 0 +
"H" + (w0 + 1) * cellSize + "Z";
}
&#13;
<script src="http://d3js.org/d3.v4.min.js"></script>
&#13;