在 d3.js v6+ 中将元素标记为已单击

Mark element as clicked in d3.js v6+

我的问题: 我有一些数据点绑定到圆形元素。现在,每次用户点击一个圆圈时,我都想将其颜色更改为红色。为此,我想使用一个更新函数,每次用户点击一个圆圈时都会调用该函数。由于我不仅要更改单击的圆圈,还要更改基于单击哪个圆圈的其他元素,因此我需要以某种方式记住单击的是哪个圆圈。我在 d3.js v3 中看到这是通过简单地将数据保存到事件侦听器中的变量 (clickedCircle) 并在稍后调用它来完成的。但是,这似乎不再适用于 d3.js v6+。在 v6+ 中执行此操作的最佳方法是什么?

快速 d3.js v3 示例改编自 this chart 的基本思想):

var data = [
    {x: 10, y: 20},
    {x: 30, y: 10},
    {x: 20, y: 55},
];

svg = d3.select(#div1)
    .append("svg")
    .attr("width", 100)
    .attr("height", 100)
;

var circles;
var clickedCircle;

function update() {
    circles = svg.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
        .attr("cx", function(d) { return d.position.x } )
        .attr("cy", function(d) { return d.position.y } )
        .attr("r", 10)
        .on("click", function(e, d) { clickedCircle = d; update(); } )
    ;
  
    circles
        .style("fill", function(d) {
            if (d === clickedCircle) {
                return "red"
            } else {
                return "black"
            }
        })
    ;
}

这是 D3 v7 的示例。如果您单击一个圆圈,该圆圈将变为红色并且其数据显示在文本标签中。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script src="https://d3js.org/d3.v7.js"></script>
</head>

<body>
    <div id="chart"></div>

    <script>
      // margin convention set up

      const margin = { top: 10, bottom: 10, left: 10, right: 10 };

      const width = 110 - margin.left - margin.right;
      const height = 110 - margin.top - margin.bottom;

      const svg = d3.select('#chart')
        .append('svg')
          .attr('width', width + margin.left + margin.right)
          .attr('height', height + margin.top + margin.bottom);

      const g = svg.append('g')
          .attr('transform', `translate(${margin.left},${margin.top})`);

      // data

      const data = [
        { x: 10, y: 20 },
        { x: 30, y: 10 },
        { x: 20, y: 55 },
      ];

      // draw cirlces

      const circles = g.selectAll('circle')
        .data(data)
        .join('circle')
          .attr('cx', d => d.x)
          .attr('cy', d => d.y)
          .attr('r', 10)
          .attr('fill', 'black')
          .on('click', update);

      // text label

      const label = g.append('text')
         .attr('y', height);


      // update when circle is clicked

      function update(event, d) {
        // reset all circles to black
        circles.attr('fill', 'black');
        // color the clicked circle red
        d3.select(this).attr('fill', 'red');
        // update the label
        label.text(`x: ${d.x}, y: ${d.y}`);
      }
    </script>
</body>
</html>