我创建了一个水平条形图。
每个条形的宽度基于对象变量体积。后来我意识到我需要让每个条形成一个堆栈条,2类对象变量是 vol1 & vol2 ,其中 vol1 + vol2 = 音量。
我想知道是否有一种直接的方法可以根据 vol1 &和分配 2种颜色到每个条 vol2 值而不是通常的堆叠条形方法,您需要(a)根据类别在数组中排列数据,(b)定义 x,y,y0 (c )为每个阵列条指定不同的颜色。
数据结构:
var data = [
{ "merchant": "A",
"volume": 100,
"vol1": 48,
"vol2": 52
},
{...},
{...}
];
绘制图表的具体代码是:
var bar = d3.select(".mainGroup").selectAll(".bar")
.data(data_merchantTop100Vol);
bar.attr("x", 0)
.attr("y", d => y(d.merchant))
.attr("height", y.rangeBand())
.transition().duration(50)
.attr("width", d => x(d.volume));
bar.enter().append("rect")
.attr("class", "bar")
.attr("x", 0)
.attr("y", d => y(d.merchant))
.attr("height", y.rangeBand())
.transition().duration(50)
.attr("width", d => x(d.volume))
// THIS PART IS TO FILL 2 COLORS TO THE 2 SECTIONS OF EACH BAR
// .style("fill", function(d) {
// if(d.Vol1) { return "blue"}
// else if (d.vol2) { return "red"};
// })
简而言之,我想使用if-condition着色方法而不是典型的堆叠条形法创建水平堆叠条。想法灵感:http://www.d3noob.org/2013/01/select-items-with-if-statement-in-d3js.html
答案 0 :(得分:2)
您可以尝试使用正确的百分比填充gradients的矩形,但这会使解决方案复杂化。最简单的方法是为每种颜色使用一个矩形。您无需重新排列数据:
// Vol1 bars
bar.enter().append("rect")
.attr("class", "bar")
.attr("x", 0)
.attr("y", d => y(d.merchant))
.attr("height", y.bandwidth())
.transition().duration(50)
.attr("width", d => x(d.vol1))
.style("fill", "blue")
// Vol2 bars
bar.enter().append("rect")
.attr("class", "bar")
.attr("x", d => x(d.vol1))
.attr("y", d => y(d.merchant))
.attr("height", y.bandwidth())
.transition().duration(50)
.attr("width", d => x(d.vol2))
.style("fill", "red")
答案 1 :(得分:1)
如果你真的,真的想用一个条形图做这个,你必须设置自定义渐变,可以按百分比分割颜色:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var data = [{
volume: Math.random() * 400,
vol1: Math.random() * 400,
vol2: Math.random() * 400
}, {
volume: Math.random() * 400,
vol1: Math.random() * 400,
vol2: Math.random() * 400
}, {
volume: Math.random() * 400,
vol1: Math.random() * 400,
vol2: Math.random() * 400
}, {
volume: Math.random() * 400,
vol1: Math.random() * 400,
vol2: Math.random() * 400
}];
var height = 400,
width = 600,
color1 = "orange",
color2 = "steelblue",
barHeight = 20;
var svg = d3.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);
var defs = svg.append("defs");
var g = svg.selectAll("g")
.data(data)
.enter()
.append("g")
g.append("rect")
.attr("width", function(d) {
return d.volume
})
.attr("height", barHeight)
.attr("x", 10)
.attr("y", function(d, i) {
return i * (barHeight + 5);
})
.style("fill", function(d, i) {
var p = (d.vol1 / (d.vol1 + d.vol2)) * 100,
grad = defs.append("linearGradient")
.attr("id", "grad_" + i);
grad.append("stop")
.attr("offset", "0%")
.attr("stop-color", color1);
grad.append("stop")
.attr("offset", (p) + "%")
.attr("stop-color", color1);
grad.append("stop")
.attr("offset", (p) + "%")
.attr("stop-color", color2);
grad.append("stop")
.attr("offset", "100%")
.attr("stop-color", color2);
return "url(#grad_" + i + ")";
});
g.append("text")
.attr("x", function(d) {
return d.volume + 12
})
.attr("y", function(d, i) {
return (i * (barHeight + 5)) + 13;
})
.text(function(d){
var p1 = (d.vol1 / (d.vol1 + d.vol2)) * 100,
p2 = (d.vol2 / (d.vol1 + d.vol2)) * 100;
return Math.round(p1) + "% and " + Math.round(p2) + "%";
})
.style("stroke", "none")
.style("fill", "black")
.style("font-family", "arial")
.style("font-size", "12px");
</script>
</body>
</html>