You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3.js使用二级嵌套数据绘制图形符号并将所有圆点置于同一g组

问题核心原因

  • d3.selection.data()的第二个参数是数据匹配键函数,仅用于数据更新时关联已有DOM和对应数据,不会改变绑定到元素的原始数据结构。你当前直接传入games数组作为第一个参数,所以每个circle绑定的自然是games数组的顶级元素(即带name和values的整条折线数据对象),和你预期的子级数据完全不符。
  • 要把所有折线的圆点放在同一个<g>下,需要先把嵌套的二维数据扁平化为一维数组,数组的每个元素对应单个圆点的完整信息(包含自身数值、所属折线的名称等),总长度等于折线数量 × 40。

解决方案代码

var symbolsb = d3.select("#plot-b") // plot-b是svg内的绘图区域组
  .append("g")
  .attr("id", "symbols-b");

// 第一步:扁平化嵌套数据,同时保留父级折线的信息
const flatCircleData = games.flatMap(function(game) {
  // 给每个数值项追加所属折线的name,方便后续逻辑调用
  return game.values.map(function(valueItem) {
    return {
      ...valueItem, // 保留原values里的date、count等字段
      seriesName: game.name
    }
  })
})

// 第二步:将扁平化后的一维数组直接绑定到circle元素
symbolsb.selectAll("circle")
  .data(flatCircleData)
  .enter()
  .append("circle")
  .attr("class", "symbolsb")
  .attr("cx", function(d) {
    return x(d.date);
  })
  .attr("cy", function(d) {
    return y_count(d.count);
  })
  .attr("r", function(d, i) {
    return included_names.includes(d.seriesName) && (i % 3 === 1) ? 8 : 0;
  })
  .style("fill", function(d) {
    return color(d.seriesName);
  });

补充说明

  • 如果需要兼容不支持flatMap的旧运行环境,可以把扁平化逻辑替换为games.map(...).flat()或者用循环手动拼接数组。
  • 扁平化后每个圆点的独立数据都直接绑定到对应DOM元素上,不需要再通过父节点反向获取数据,逻辑更简洁,渲染性能也更高。

内容的提问来源于stack exchange,提问作者supvato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 00:36:04