【问题标题】:I would like to know how to create etc groups in d3.js donut chart我想知道如何在 d3.js 圆环图中创建等组
【发布时间】:2025-12-18 02:00:02
【问题描述】:

我想知道如何在 d3.js 圆环图中创建 etc 组。

data = {{result|safe}}

      var text = "";

      var width = 1450;
      var height = 500;
      var thickness = 40;
      var duration = 750;

      var radius = Math.min(width, height) / 2;
      var color = d3.scaleOrdinal(d3.schemeCategory20);

      var svg = d3.select("#donutchart")
      .append('svg')
      .attr('class', 'pie')
      .attr('width', width)
      .attr('height', height);

      var g = svg.append('g')
      .attr('transform', 'translate(' + (width/2) + ',' + (height/2) + ')');

      var arc = d3.arc()
      .innerRadius(radius - thickness)
      .outerRadius(radius);

      var pie = d3.pie()
      .value(function(d) { return d.count; })
      .sort(null);

      var path = g.selectAll('path')
      .data(pie(data))
      .enter()
      .append("g")
      .on("mouseover", function(d) {
            let g = d3.select(this)
              .style("cursor", "pointer")
              .style("fill", "black")
              .append("g")
              .attr("class", "text-group");
       
            g.append("text")
              .attr("class", "name-text")
              .text(`${d.data.word}`)
              .attr('text-anchor', 'middle')
              .attr('dy', '-1.2em');
        
            g.append("text")
              .attr("class", "value-text")
              .text(`${d.data.count}`)
              .attr('text-anchor', 'middle')
              .attr('dy', '.6em');
          })
        .on("mouseout", function(d) {
            d3.select(this)
              .style("cursor", "none")  
              .style("fill", color(this._current))
              .select(".text-group").remove();
          })
        .append('path')
        .attr('d', arc)
        .attr('fill', (d,i) => color(i))
        .on("mouseover", function(d) {
            d3.select(this)     
              .style("cursor", "pointer")
              .style("fill", "black");
          })
        .on("mouseout", function(d) {
            d3.select(this)
              .style("cursor", "none")  
              .style("fill", color(this._current));
          })
        .each(function(d, i) { this._current = i; });


      g.append('text')
        .attr('text-anchor', 'middle')
        .attr('dy', '.35em')
        .text(text);

当数据字数小于100时,有没有办法把图表做成一个etc组来展示呢?是否必须由服务器处理?

或者有没有办法只显示前 8 个数据并将其放入 etc 组?

【问题讨论】:

    标签: javascript d3.js charts grouping


    【解决方案1】:

    让我们假设数据是一个包含“名称”和“值”的对象数组:

    [
      {
        "name": "a",
        "value": 198
      },
      {
        "name": "b",
        "value": 100
      },
      {
        "name": "c",
        "value": 50
      },
      // ...
    ]
    

    我们还假设它已排序(您可以这样做):

    var data = data.sort((a, b) => d3.descending(a.value, b.value))
    

    让我们取 8 个最大的值,其余的都放在一个“etc”标签中:

    let newData = data.slice(0, 8)
    const etcSliceAmount = data.slice(8, data.length-1)
      .map(d => d.value)
      .reduce((acc, x) => acc + x)
    newData.push({
      name: "etc",
      value: etcSliceAmount,
    })
    

    etcSliceAmount 中,我们首先获取除前八项之外的所有项目。我们使用reduce 将它们加起来。最后,我们可以将这个新分区附加到数据的末尾。由于没有排序,在您的代码中使用sort(null) 禁用,d3 将按顺序放置切片。

    // random array of 100 values from [0-200], sorted
    const data = d3.range(100).map(() => ({
      name: "a", 
      value: Math.floor(d3.randomUniform(0, 200)())
    })).sort((a, b) => d3.descending(a.value, b.value))
    
    let newData = data.slice(0, 8)
    const etcSliceAmount = data.slice(8, data.length-1).map(d => d.value).reduce((acc, x) => acc + x)
    newData.push({
      name: "etc",
      value: etcSliceAmount,
    })
    
    console.log(newData)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

    【讨论】: