我尝试在web (https://github.com/PacktPublishing/Learn-D3.js/blob/master/Chapter07/Stacks/9-bar-na.html)上更新堆叠条形图,因为它仅限于三行数据,我想添加一些更多的行。
这是我完整的d3.js源代码:
<script>
const width = 600;
const height = 400;
const margin = 50;
// some extra rows than the three original rows
const populations = [
{year: 1960, "Mexico": 38174, "Canada": 17917, "USA": 186808},
{year: 1980, "Mexico": 69361, "Canada": 24537, "USA": 229763},
{year: 2000, "Mexico": 101720, "Canada": 30736, "USA": 281983},
{year: 2010, "Mexico": 110000, "Canada": 35000, "USA": 350000},
{year: 2020, "Mexico": 130000, "Canada": 50000, "USA": 500000}
];
console.log("populations : "+JSON.stringify(populations));
const keys = ['USA', 'Mexico', 'Canada'];
console.log("keys : "+keys);
const stack = d3.stack()
.keys(keys)
.order(d3.stackOrderReverse);
const stackedData = stack(populations);
console.log("stackedData : "+JSON.stringify(stackedData));
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain([0,populations.length]);
const scale = d3.scaleLinear()
.domain([0, d3.max(d3.merge(d3.merge(stackedData)))])
.range([margin,width - margin]);
const svg = d3.select("body")
.append("svg")
.attr("height",400)
.attr("width",width);
svg.selectAll(".year")
.data(stackedData)
.enter()
.append("g").attr("class", "year")
.style("fill", (d,i) => colorScale(i))
.each(function(d) {
d3.select(this)
.selectAll(".country")
.data(d)
.enter()
.append("rect").attr("class", "country")
.attr('width', d => scale(d[1] - d[0]))
.attr('height', 20)
.attr('x', d => scale(d[0]))
.attr('y', (d,i) => i * 22)
})
.append("text")
.text((d,i) => populations[i].year)
.style("font-family", "sans-serif")
.style("fill", "black")
.attr("y", (d,i) => i * 22)
.attr("x", 10);
</script>
问题是在错误的地方添加了图例。js在每个"g"加价,而不是在第一个";g"只有,在每一次"正确"之后
我试过了:
coun=svg.select(".year").selectAll("rect").each(function(d,i) {
d3.select(this)
.append("text")
.text((d,i) => populations[i].year)
.style("font-family", "sans-serif")
.style("fill", "black")
.attr("y", (d,i) => i * 22)
.attr("x", 10)
});
但是文本被添加到每个rect标记中。
你能帮我吗?
谢谢你。
Jena-michel、法国
您可以在自己的组中独立添加标签:
const width = 600;
const height = 400;
const margin = 50;
const populations = [
{year: 1960, "Mexico": 38174, "Canada": 17917, "USA": 186808},
{year: 1980, "Mexico": 69361, "Canada": 24537, "USA": 229763},
{year: 2000, "Mexico": 101720, "Canada": 30736, "USA": 281983},
{year: 2010, "Mexico": 110000, "Canada": 35000, "USA": 350000},
{year: 2020, "Mexico": 130000, "Canada": 50000, "USA": 500000}
];
const keys = ['USA', 'Mexico', 'Canada'];
const stack = d3.stack()
.keys(keys)
.order(d3.stackOrderReverse);
const stackedData = stack(populations);
const colorScale = d3.scaleOrdinal(d3.schemeCategory10)
.domain([0, populations.length]);
const scale = d3.scaleLinear()
.domain([0, d3.max(d3.merge(d3.merge(stackedData)))])
.range([margin, width - margin]);
const svg = d3.select("body")
.append("svg")
.attr("height", 800)
.attr("width", width);
svg.selectAll(".year")
.data(stackedData)
.enter()
.append("g")
.attr("class", "year")
.style("fill", (d, i) => colorScale(i))
.each(function(d) {
d3.select(this)
.selectAll(".country")
.data(d)
.enter()
.append("rect")
.attr("class", "country")
.attr('width', d => scale(d[1] - d[0]))
.attr('height', 20)
.attr('x', d => scale(d[0]))
.attr('y', (d, i) => i * 22);
});
const yearLabels = svg.append("g")
.attr("class", "yearLabels")
.attr("transform", "translate(0, -6)");
yearLabels.selectAll(".yearLabel")
.data(populations)
.enter()
.append("text")
.attr("class", "yearLabel")
.text((d, i) => d.year)
.style("fill", "black")
.attr("y", (d, i) => (i + 1) * 22)
.attr("x", 0);
const legend = svg.append("g")
.attr("class", "legend")
.attr("transform", `translate(${margin}, ${height - margin})`);
const legendItemHeight = 20;
const legendTextSize = 14;
legend.selectAll("rect")
.data(keys)
.enter()
.append("rect")
.attr("width", legendItemHeight)
.attr("height", legendItemHeight)
.attr("x", (d, i) => i * 100)
.style("fill", (d, i) => colorScale(i));
legend.selectAll("text")
.data(keys)
.enter()
.append("text")
.attr("y", legendItemHeight / 2 + legendTextSize / 2)
.attr("x", (d, i) => i * 100 + legendItemHeight + 5)
.text(d => d)
.style("font-size", `${legendTextSize}px`);
const totalBarHeight = stackedData[0].length * 22;
const legendY = totalBarHeight + 20;
legend.attr("transform", `translate(${margin}, ${legendY})`);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.4/d3.min.js"></script>