首页 > 解决方案 > 追加时访问父数据

问题描述

我基本上有一些像这样的嵌套数据:

const shapeGroups = [
      {
        title: 'shapeGroup_01',
        color: 'blue',
        shapes: [
          {
            shape:'rect',
            width: 30,
            height: 100,
            x: 250,
            y: 450
          }
        ]
      },
      {
        title: 'shapeGroup_01',
        color: 'blue',
        shapes: [
          {
            shape:'rect',
            width: 10,
            height: 40,
            x: 350,
            y:50
          }
        ]
      }
    ]

我感兴趣的是在每个中设置颜色,rect因为它在 shapeGroup 的color属性中定义。

const shapeGroups = [{
    title: 'shapeGroup_01',
    color: 'blue',
    shapes: [{
      shape: 'rect',
      width: 30,
      height: 100,
      x: 250,
      y: 450
    }]
  },
  {
    title: 'shapeGroup_01',
    color: 'blue',
    shapes: [{
      shape: 'rect',
      width: 10,
      height: 40,
      x: 350,
      y: 50
    }]
  }
]

const stage = d3.select('#stageContainer')
  .append('svg')
  .attr('id', '#stage')
  .attr('width', 1000)
  .attr('height', 1000)


const groups = stage
  .selectAll('.group')
  .data(shapeGroups)

const groupEnter = groups
  .enter()
  .append('g')
  .attr('class', 'group');

const getGroup = group => group.shapes;
const createShape = shape => document.createElementNS(d3.namespaces.svg, shape.shape)

groupEnter
  .selectAll('.shape')
  .data(getGroup)
  .enter()
  .append(createShape)
  .attr('fill', 'red') // I want the color as defined in the current group
  .attr('width', d => d.width)
  .attr('height', d => d.height)
  .attr('x', d => d.x)
  .attr('y', d => d.y)
<script src="https://d3js.org/d3.v5.min.js"></script>
<div id="stageContainer"></div>

换句话说,我需要一种方法来color在组级别设置,或者datum在我附加单个.shapes 时以某种方式访问​​父对象。

标签: javascriptd3.jssvg

解决方案


正如您在我的回答中所读到的,您无法从 D3 v4/v5 的选择中访问父数据或其索引。

这里的一个解决方案是获取 的数据parentNode

.attr('fill', (_, i, n) => d3.select(n[i].parentNode).datum().color)

这是您进行更改的代码(我正在制作具有不同颜色的两个矩形和更小的 SVG,以便更好地可视化它):

const shapeGroups = [{
    title: 'shapeGroup_01',
    color: 'blue',
    shapes: [{
      shape: 'rect',
      width: 30,
      height: 100,
      x: 250,
      y: 50
    }]
  },
  {
    title: 'shapeGroup_01',
    color: 'green',
    shapes: [{
      shape: 'rect',
      width: 10,
      height: 40,
      x: 350,
      y: 20
    }]
  }
];

const stage = d3.select('body')
  .append('svg')
  .attr('width', 400)
  .attr('height', 400)


const groups = stage
  .selectAll('.group')
  .data(shapeGroups)

const groupEnter = groups
  .enter()
  .append('g')
  .attr('class', 'group');

const getGroup = group => group.shapes;
const createShape = shape => document.createElementNS(d3.namespaces.svg, shape.shape)

groupEnter
  .selectAll('.shape')
  .data(getGroup)
  .enter()
  .append(createShape)
  .attr('fill', (_, i, n) => d3.select(n[i].parentNode).datum().color)
  .attr('width', d => d.width)
  .attr('height', d => d.height)
  .attr('x', d => d.x)
  .attr('y', d => d.y)
<script src="https://d3js.org/d3.v5.min.js"></script>

但是,到目前为止,最简单的解决方案是将 设置fill为父选择本身:

const groupEnter = groups
    .enter()
    .append('g')
    .attr('class', 'group')
    .attr('fill', d => d.color);

这是演示:

const shapeGroups = [{
    title: 'shapeGroup_01',
    color: 'blue',
    shapes: [{
      shape: 'rect',
      width: 30,
      height: 100,
      x: 250,
      y: 50
    }]
  },
  {
    title: 'shapeGroup_01',
    color: 'green',
    shapes: [{
      shape: 'rect',
      width: 10,
      height: 40,
      x: 350,
      y: 20
    }]
  }
];

const stage = d3.select('body')
  .append('svg')
  .attr('width', 400)
  .attr('height', 400)


const groups = stage
  .selectAll('.group')
  .data(shapeGroups)

const groupEnter = groups
  .enter()
  .append('g')
  .attr('class', 'group')
  .attr('fill', d=>d.color);

const getGroup = group => group.shapes;
const createShape = shape => document.createElementNS(d3.namespaces.svg, shape.shape)

groupEnter
  .selectAll('.shape')
  .data(getGroup)
  .enter()
  .append(createShape)
  .attr('width', d => d.width)
  .attr('height', d => d.height)
  .attr('x', d => d.x)
  .attr('y', d => d.y)
<script src="https://d3js.org/d3.v5.min.js"></script>


推荐阅读