如何在React中为D3元素添加点击处理程序

huangapple go评论82阅读模式
英文:

How to add click handler to D3 element in React

问题

下面是你提供的代码,其中我只翻译了注释部分:

import { useEffect } from "react";
import * as d3 from "d3";

export default function App() {
  useEffect(() => {
    const svg = d3.select("#svg");

    svg
      .append("rect")
      .attr("x", 0)
      .attr("y", 0)
      .attr("width", 300)
      .attr("height", 300)
      .attr("fill", "red")
      .attr("id", "red-rect");

    const redRect = d3.select("#red-rect");

    redRect.on("mouseenter", () => {
      console.log("working");
    });
  }, []);

  return <svg id="svg" />;
}

上述的代码无法正常工作,可以为整个svg注册事件,但无法为rect注册事件。以下代码是有效的:

   svg.on("mouseenter", () => {
      console.log("working");
    });

这是一个简化的示例。在实际项目中,你可能会在同一个svg内创建多个rect

奇怪的是,如果我在return语句内创建rect,我可以注册鼠标监听器。但是我不想使用React的return来创建元素,我想专门使用D3来创建元素。

export default function App() {
  useEffect(() => {
    const greenRect = d3.select("#green-rect");

    greenRect.on("mouseenter", () => {
      console.log("working");
    });

  }, []);

  return (
    <svg id="svg">
      <rect x={0} y={0} width={300} height={300} fill="green" id="green-rect" />
    </svg>
  );
}

如何在我的svg上附加rect(或其他元素)并在它们上使用鼠标事件呢?

英文:

I have the below code that appends a rect into an svg. I need that rect to handle click events such as click and mouseenter.

import { useEffect } from &quot;react&quot;;
import * as d3 from &quot;d3&quot;;

export default function App() {
  useEffect(() =&gt; {
    const svg = d3.select(&quot;#svg&quot;);

    svg
      .append(&quot;rect&quot;)
      .attr(&quot;x&quot;, 0)
      .attr(&quot;y&quot;, 0)
      .attr(&quot;width&quot;, 300)
      .attr(&quot;height&quot;, 300)
      .attr(&quot;fill&quot;, &quot;red&quot;)
      .attr(&quot;id&quot;, &quot;red-rect&quot;);

    const redRect = d3.select(&quot;#red-rect&quot;);

    redRect.on(&quot;mouseenter&quot;, () =&gt; {
      console.log(&quot;working&quot;);
    });
  }, []);

  

  return &lt;svg id=&quot;svg&quot; /&gt;;
}

The above does not work. I can register the entire svg but not the rect. The below works:

   svg.on(&quot;mouseenter&quot;, () =&gt; {
      console.log(&quot;working&quot;);
    });

This is a minimalistic example. In the real project I'll be creating several rects inside the same svg.

The strange thing is that if I create a rect inside the return statement, I can register the mouse listener. But I don't want to use React return to create elements. I want to create elements exclusively with D3.

export default function App() {
  useEffect(() =&gt; {
    const greenRect = d3.select(&quot;#green-rect&quot;);

    greenRect.on(&quot;mouseenter&quot;, () =&gt; {
      console.log(&quot;working&quot;);
    });

  }, []);

  return (
    &lt;svg id=&quot;svg&quot;&gt;
      &lt;rect x={0} y={0} width={300} height={300} fill=&quot;green&quot; id=&quot;green-rect&quot; /&gt;
    &lt;/svg&gt;
  );
}

How can I append rects (or other elements) on my svg and use mouse events on them?

Here's a fiddle

Thanks

答案1

得分: 1

在附加元素时,请为选择指定一个名称:

useEffect(() => {
  const svg = d3.select("#svg");

  const redRect = svg.append("rect")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", 300)
    .attr("height", 300)
    .attr("fill", "red")
    .attr("id", "red-rect");

  redRect.on("mouseenter", () => {
    console.log("working");
  });
}, []);

这是分叉的代码沙箱

英文:

When appending your elements, give the selection a name:

useEffect(() =&gt; {
  const svg = d3.select(&quot;#svg&quot;);

  const redRect = svg.append(&quot;rect&quot;)
    .attr(&quot;x&quot;, 0)
    .attr(&quot;y&quot;, 0)
    .attr(&quot;width&quot;, 300)
    .attr(&quot;height&quot;, 300)
    .attr(&quot;fill&quot;, &quot;red&quot;)
    .attr(&quot;id&quot;, &quot;red-rect&quot;);

  redRect.on(&quot;mouseenter&quot;, () =&gt; {
    console.log(&quot;working&quot;);
  });
}, []);

Here's the forked sandbox.

huangapple
  • 本文由 发表于 2023年3月7日 17:48:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75660317.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定