d3.js 如何在堆叠条形矩形上添加文本图例

plupiseo  于 5个月前  发布在  其他
关注(0)|答案(1)|浏览(38)

我尝试更新网络上的堆叠条形图(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>

字符串
问题是图例被添加到了错误的地方。D3.js在每个“g”标记中添加文本,而不是像我希望的那样只在第一个“g”之后,在每个“rect”标记之后。
我试过这个:

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,法国

nx7onnlm

nx7onnlm1#

您可以在自己的组中独立添加标签:

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})`);

个字符

相关问题