如何链接两个SVG元素,使得在一个上面鼠标悬停也可以引用另一个元素?

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

How to link two SVG elements so that mouseover on one can reference also the other?

问题

在我的代码中,我创建了一个文本标签和一个透明的矩形,以便用户可以轻松选择它。由于鼠标悬停事件被定义在矩形上,所以我无法对文本做任何操作(显然)。我应该如何最好地将文本与矩形“链接”起来?我需要每个矩形与相应的文本关联起来,但我找不到这样做的方法:

  1. // 对于每个数据点,创建一个标签和一个矩形
  2. settings.g.selectAll(".labels")
  3. .data(data)
  4. .join(
  5. enter => {
  6. let g = enter.append("g");
  7. let text = g.append("text");
  8. let rect = g.append("rect");
  9. text
  10. .text(d => d.name);
  11. rect
  12. .attr("width", d => d.bbox.width)
  13. .attr("height", d => d.bbox.height)
  14. .attr("fill", "transparent")
  15. .on('mouseover', function (d) {
  16. // TODO: 使相应的文本加粗
  17. });
  18. }
  19. );

我知道我可以使用 selectAll("text") 并找到正确的文本,但这并不高效,因为有许多 "texts" 元素。

英文:

In my code, I create a text label and a transparent rect behind it so that user can easily select it. As the mouseover is defined on the rect, I cannot do anything with the text (obviously). How should I best "link" the text to the rectangle? I would need every rect to be linked to a respective text, but I could not find a way of doing in this way:

  1. //for every data point, one label and one rect are created
  2. settings.g.selectAll(".labels")
  3. .data(data)
  4. .join(
  5. enter => {
  6. let g = enter.append("g");
  7. let text = g.append("text")
  8. let rect = g.append("rect");
  9. text
  10. .text(d => d.name)
  11. rect
  12. .attr("width", (d) => d.bbox.width)
  13. .attr("height", (d) => d.bbox.height)
  14. .attr("fill", "transparent")
  15. .on('mouseover', function (d) {
  16. //TODO: make the respective text BOLD
  17. })

I know I could selectAll("text") and find the right one but that would not be efficient as there are many "texts".

答案1

得分: 1

以下是您要翻译的内容:

"不确定这是否是“最佳”方式,但这里有一个演示。
这起作用是因为 rect.nodes()[0] 匹配 text.nodes()[0] 等等,并且 e.target 是相关的 SVGRectElement。"

  1. let data = [
  2. { name: "A", bbox: { x: 20, y: 20, width: 20, height: 40 } },
  3. { name: "B", bbox: { x: 60, y: 20, width: 20, height: 40 } },
  4. { name: "C", bbox: { x: 100, y: 20, width: 20, height: 40 } },
  5. { name: "D", bbox: { x: 140, y: 20, width: 20, height: 40 } },
  6. ]
  7. document.addEventListener("DOMContentLoaded", () => {
  8. d3.select('#focus').selectAll(null).enter()
  9. .data(data)
  10. .join(enter => {
  11. let g = enter.append("g");
  12. let text = g.append("text")
  13. let rect = g.append("rect");
  14. text.text(d => d.name).attr('x', d => d.bbox.x + d.bbox.width / 2).attr('y', d => d.bbox.y + d.bbox.height / 2)
  15. rect.attr("width", (d) => d.bbox.width)
  16. .attr("height", (d) => d.bbox.height)
  17. .attr('x', d => d.bbox.x).attr('y', d => d.bbox.y)
  18. .attr("fill", "transparent")
  19. .on('mouseover', function (e, d) {
  20. let idx = rect.nodes().indexOf(e.target);
  21. let textElement = text.nodes()[idx]
  22. d3.select(textElement).attr('font-weight', 'bold');
  23. }).on('mouseout', function (e, d) {
  24. let idx = rect.nodes().indexOf(e.target);
  25. let textElement = text.nodes()[idx]
  26. d3.select(textElement).attr('font-weight', null);
  27. })
  28. return g;
  29. })
  30. });
  1. svg{
  2. width: 200px;
  3. height: 200px;
  4. }
  5. svg text{
  6. dominant-baseline: central;
  7. text-anchor: middle;
  8. }
  9. svg rect{
  10. cursor: pointer;
  11. }
  1. <script src="https://d3js.org/d3.v7.min.js"></script>
  2. <body>
  3. <svg id='focus'>
  4. </svg>
  5. </body>
英文:

Not sure if this is the "best" way, but here is a demo.<br>
This works because rect.nodes()[0] matches text.nodes()[0] and so on, and e.target is the relevant SVGRectElement.

<!-- begin snippet: js hide: false console: false babel: false -->

<!-- language: lang-js -->

  1. let data = [
  2. { name: &quot;A&quot;, bbox: { x: 20, y: 20, width: 20, height: 40 } },
  3. { name: &quot;B&quot;, bbox: { x: 60, y: 20, width: 20, height: 40 } },
  4. { name: &quot;C&quot;, bbox: { x: 100, y: 20, width: 20, height: 40 } },
  5. { name: &quot;D&quot;, bbox: { x: 140, y: 20, width: 20, height: 40 } },
  6. ]
  7. document.addEventListener(&quot;DOMContentLoaded&quot;, () =&gt; {
  8. d3.select(&#39;#focus&#39;).selectAll(null).enter()
  9. .data(data)
  10. .join(enter =&gt; {
  11. let g = enter.append(&quot;g&quot;);
  12. let text = g.append(&quot;text&quot;)
  13. let rect = g.append(&quot;rect&quot;);
  14. text.text(d =&gt; d.name).attr(&#39;x&#39;, d =&gt; d.bbox.x + d.bbox.width / 2).attr(&#39;y&#39;, d =&gt; d.bbox.y + d.bbox.height / 2)
  15. rect.attr(&quot;width&quot;, (d) =&gt; d.bbox.width)
  16. .attr(&quot;height&quot;, (d) =&gt; d.bbox.height)
  17. .attr(&#39;x&#39;, d =&gt; d.bbox.x).attr(&#39;y&#39;, d =&gt; d.bbox.y)
  18. .attr(&quot;fill&quot;, &quot;transparent&quot;)
  19. .on(&#39;mouseover&#39;, function (e, d) {
  20. let idx = rect.nodes().indexOf(e.target);
  21. let textElement = text.nodes()[idx]
  22. d3.select(textElement).attr(&#39;font-weight&#39;, &#39;bold&#39;);
  23. }).on(&#39;mouseout&#39;, function (e, d) {
  24. let idx = rect.nodes().indexOf(e.target);
  25. let textElement = text.nodes()[idx]
  26. d3.select(textElement).attr(&#39;font-weight&#39;, null);
  27. })
  28. return g;
  29. })
  30. });

<!-- language: lang-css -->

  1. svg{
  2. width: 200px;
  3. height: 200px;
  4. }
  5. svg text{
  6. dominant-baseline: central;
  7. text-anchor: middle;
  8. }
  9. svg rect{
  10. cursor: pointer;
  11. }

<!-- language: lang-html -->

  1. &lt;script src=&quot;https://d3js.org/d3.v7.min.js&quot;&gt;&lt;/script&gt;
  2. &lt;body&gt;
  3. &lt;svg id=&#39;focus&#39;&gt;
  4. &lt;/svg&gt;
  5. &lt;/body&gt;

<!-- end snippet -->

答案2

得分: 0

你可以将鼠标悬停在包含 "rect" 和 "text" 的 g 元素上。
事件在悬停在 rect 或 text 上触发。然后,你可以获取文本元素并进行任何你想要的操作。

  1. g.on('mouseover',function (){
  2. d3.select(this).select('text').style('font-weight','bold')
  3. })
英文:

You can put the mouseover on the g element containing "rect" and "text".
Event is triggered on either rect or text hovering. You can then retrieve the text element and do whatever you want.

  1. g.on(&#39;mouseover&#39;,function (){
  2. d3.select(this).select(&#39;text&#39;).style(&#39;font-weight&#39;,&#39;bold&#39;)
  3. })

huangapple
  • 本文由 发表于 2023年6月29日 14:29:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/76578531.html
匿名

发表评论

匿名网友

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

确定