使用 React 在 D3 中复制元素而不是移动元素

Elements are duplicated instead of moved in D3 with React

我正在尝试在您单击按钮时移动 D3 中的元素。此代码复制元素而不是移动它们。

import React, { useRef, useEffect, useState } from "react";
import { select } from "d3";

const svgSize = 500;

const initData = [
  { value: 3, x: 60, y: 60 },
  { value: 2, x: 40, y: 40 },
  { value: 1, x: 20, y: 20 },
];

export default function Home() {
  const [data, setData] = useState(initData);
  const svgRef = useRef();

  const animate = () => {
    setData(
      data.map((item) => {
        return {
          value: item.value,
          x: item.x + 20,
          y: item.y + 20,
        };
      })
    );
  };

  useEffect(() => {
    const svg = select(svgRef.current);
    svg
      .selectAll("circle")
      .data(data)
      .join("text")
      .text((value) => value.value)
      .attr("x", (value) => value.x)
      .attr("y", (value) => value.y);
  }, [data]);

  return (
    <div>
      <button onClick={animate}>Animate</button>
      <div>
        <svg width={svgSize} height={svgSize} ref={svgRef} />
      </div>
    </div>
  );
}

页面加载时:

点击按钮后:

我认为您的 svg select 个节点有问题,您正在尝试 selectAll('circle') 但您需要 select selectAll('text')。因此,您绘制一个新的 text 节点而不是移动它们。 尝试将 useEffect 更改为:

  useEffect(() => {
    const svg = select(svgRef.current);
    svg.selectAll('text')
      .data(data)
      .join('text')
      .text(({ value }) => value)
      .attr('x', ({ x }) => x)
      .attr('y', ({ y }) => y);
  }, [data]);

如果要为动作添加动画,请添加:

  useEffect(() => {
    const svg = select(svgRef.current);
    svg.selectAll('text')
      .data(data)
      .join('text')
      .text(({ value }) => value)
      .transition()
      .duration(1000)
      .attr('x', ({ x }) => x)
      .attr('y', ({ y }) => y);
  }, [data]);