Javascript D3中使用内部JSON变量的堆叠条形图
因此,尝试在D3.js中创建一个堆叠条形图。我已经让轴工作了,但是图形数据没有显示,有什么想法我哪里出错了吗 JS:Javascript D3中使用内部JSON变量的堆叠条形图,javascript,json,d3.js,Javascript,Json,D3.js,因此,尝试在D3.js中创建一个堆叠条形图。我已经让轴工作了,但是图形数据没有显示,有什么想法我哪里出错了吗 JS: var svg = d3.select("#recovery__table"), margin = {top: 20, right: 20, bottom: 30, left: 40}, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height")
var svg = d3.select("#recovery__table"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
aspect = width/height,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleBand()
.rangeRound([0, width])
.padding(0.1)
.align(0.1);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
var z = d3.scaleOrdinal()
.range(["#717C8B", "#7FDDC3", "#39B3CD"]);
var stack = d3.stack();
data.forEach(function(d) {
d.year = d['trades.closed_half_year_year'];
d.loss = d['loss'];
d.recovered = d['recovered'];
d.recovery = d['in_recovery'];
d.total = d.loss + d.recovery + d.recovered;
});
var div = d3.select("body").append("div")
.attr("class", "tooltip3")
.style("opacity", "0");
x.domain(data.map(function(d) { return d.year; }));
y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
z.domain(d3.keys(data[0]).filter(function(key){ return key == 'loss' && key == 'recovered' && key == 'in_recovery' }));
g.selectAll(".serie")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("fill", function(d){ return z(d.keys); })
.attr("x", function(d) { return x(d.year); })
.attr("width", x.bandwidth())
.attr("y", function(d) { return y(d.total); })
.attr("height", function(d) { return y[0] - y[1]; })
.on("mouseover", function(d) {
var value = parseInt($(this).attr('data-value'));
div.transition()
.duration(200)
.style("opacity", .5);
div.html(d.data.year + "<br/>£" + total.formatMoney())
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(500)
.style("opacity", 0);
});
;
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.attr('x', 20)
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).ticks(5, "s"))
.append("text")
.attr("x", 2)
.attr("y", y(y.ticks(10).pop()))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.attr("fill", "#000");
var legend = g.selectAll(".legend")
.data(data)
.enter().append("g")
.attr('width', 100)
.attr("class", "legend")
.attr('transform', function(d, i) {
var horz = 100*i; // NEW
var vert = 0;
if (horz >= width) {
horz = 100 * (i - 3);
vert = 40;
}
return 'translate(' + horz + ',' + vert + ')'; // NEW
})
.style("font", "10px sans-serif");
legend.append("rect")
.attr("x", "33%")
.attr("width", 18)
.attr("height", 18)
.attr("fill", z);
legend.append("text")
.attr("x", "43%")
.attr("y", 9)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return d; });
本质上,需要将丢失、恢复和恢复堆叠在图上,但没有像前面提到的那样将数据加载到图上
有什么想法吗?有一个小问题,您使用的数据是JSON,因此对象将以字符串形式接收值,您必须将它们正确地解析为数字。将字符串解析为数字的简单方法如下:
d.loss = +d['loss'];
d.total = "£456,324.33" + 0 + "£4,324.33" // "£456,324.330£4,324.33"
但即使我们这样做了,我们仍然会有你的数据问题。为什么?因为数据集中的某些数字已格式化:
"loss":"£456,324.33"
因此,如果您正尝试这样做:
d.total = d.loss + d.in_recovery + d.recovered;
您将获得一个无效值,因为我们可能会发出如下操作:
d.loss = +d['loss'];
d.total = "£456,324.33" + 0 + "£4,324.33" // "£456,324.330£4,324.33"
这将改变我们图表中的比例
y.domain([0, d3.max(data, function(d) {
return d.total;
})]).nice(); // spooky domain here :S
让我们来处理您的值的格式(假设值总是按照您提供的JSON中的方式进行格式设置):
现在我们有了一个正确的数据集,我们应该准备好开始使用d3和堆栈
布局:
var keys = ['loss', 'recovered', 'in_recovery']; // Declare the keys we will want in our stack
z.domain(keys); // Set them as our z domain so we can retrieve our fill color
var stackLayout = d3.stack().keys(keys)(data); // Create our stack layout
这将创建以下结构:
[
[
[
0,
0
],
[
0,
0
],
[
0,
456324.33
]
// key: loss
],
[
[
0,
0
],
[
0,
457468.31
],
[
456324.33,
2780558.6750000003
]
// key: recovered
],
[
[
0,
0
],
[
457468.31,
2348035.31
],
[
2780558.6750000003,
3113891.6750000003
]
// key: in_recovery
]
]
通过上面的结构,我们现在可以按键块创建条形图,因为您可以看到每个数组有三个值和一个键。我们需要为每个数组元素创建一个组元素:
g.selectAll(".serie")
.data(stackLayout) // Set stack layout as data
.enter()
.append("g") // Creating group for each key
.attr("fill", function(d) { return z(d.key); }) // Fill inner elements with the color provided by our z Scale
.selectAll("rect")
.data(function(d) { // Use the inner array to create our rects
return d;
})
.enter().append("rect")
.attr("x", function(d) { // Position by our x Scale
return x(d.data.year);
})
.attr("y", function(d) { // Position by our y Scale
return y(d[1]);
})
.attr("height", function(d) { // Find the height value by using the values provided in the inner arrays
return y(d[0]) - y(d[1]);
})
.attr("width", x.bandwidth());
我们还必须对标签做一些更改:
var legend = g.selectAll(".legend")
.data(keys.reverse()) // Use our keys
.enter().append("g")
.attr("class", "legend")
.attr('transform', function(d, i) {
var horz = width - margin.right - (100 * i); // NEW
var vert = 0;
return 'translate(' + horz + ',' + vert + ')'; // NEW
})
.style("font", "10px sans-serif");
legend.append("text")
.attr("x", "-5")
.attr("y", 9)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) {
return d;
});
工作plnkr: