【问题标题】:Adding Foreign Objects as React Components in a D3 svg node在 D3 svg 节点中添加外部对象作为 React 组件
【发布时间】:2020-08-31 18:21:20
【问题描述】:

我正在处理 D3 React 要求,如果用户单击 svgm 上的矩形,则会为文本提供输入框。我想使用该输入来更新反应应用程序中的另一个组件。我如何使用 svg 中的异物来做到这一点。有没有其他方法可以将文本框与 React 中 d3 中的矩形(绘制在每个矩形上方)链接起来。

我现有的代码sn-p在这里

d3.select('svg#target')
  .append("g")
      .selectAll("whatever")
      .data([1,2,3,4])
      .enter()
      .append("rect")
      .attr("x", function(d, i) {
        var x = 200 * Math.sin(-60 * i * (Math.PI / 180));
        return x - 50;
      })
      .attr("y", function(d, i) {
        var y = 200 * Math.cos(-60 * i * (Math.PI / 180));
        return y - 20;
      })

      .attr("width", 100)
      .attr("height", 40)
      .attr("fill", "gray")
      .on("click", function(d, i) {
        const count = i;
        d3.select(this)
          .append("foreignObject")
          .attr("x", function() {
            return 300 * Math.sin(-60 * i * (Math.PI / 180)) + 50;
          })
          .attr("y", function() {
            return 280 * Math.cos(-60 * i * (Math.PI / 180));
          })
          .attr("width", 140)
          .attr("height", 20)
          .html(function(d, i) {
            return (
              '<input type="text" id="attribute' +
              count +
              'value="Text goes here" />'
            );
          });
      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg viewbox="-250 -250 500 500" width="400" id="target"></svg>

【问题讨论】:

标签: javascript reactjs d3.js svg


【解决方案1】:

你已经很接近了,你只需要改变它,使外来对象不附加在&lt;rect /&gt;中,而是作为兄弟插入,比如:

<g>
  <rect x="-50" y="180" width="100" height="40" fill="gray"> 
  </rect>
  <rect x="-223.20508075688772" y="80.00000000000003" width="100" height="40" fill="gray">
  </rect>
  <rect x="-223.20508075688775" y="-119.99999999999996" width="100" height="40" fill="gray">
  </rect>
  <rect x="-50.0" y="-220" width="100" height="40" fill="gray">
  </rect>

  <foreignObject x="-50.0" y="-220" width="100" height="40">
    <input type="text" id="attribute3" value="text goes here">
  </foreignObject>
</g>

我们可以在第 24 行这样做:d3.select(this.parentNode) 选择父级,所以现在当我们追加时,它成为&lt;rect /&gt; 的兄弟,而不是子级。

d3.select('svg#target')
  .append("g")
      .selectAll("whatever")
      .data([1,2,3,4])
      .enter()
      .append("rect")
      .attr("x", function(d, i) {
        var x = 200 * Math.sin(-60 * i * (Math.PI / 180));
        return x - 50;
      })
      .attr("y", function(d, i) {
        var y = 200 * Math.cos(-60 * i * (Math.PI / 180));
        return y - 20;
      })

      .attr("width", 100)
      .attr("height", 40)
      .attr("fill", "gray")
      .on("click", function(d, i) {
        const count = i;
        if (document.getElementById('attribute' + count)){
          return 0;
        }
        d3.select(this.parentNode)
          .append("foreignObject")
          .attr("x", function() {
             var x = 200 * Math.sin(-60 * i * (Math.PI / 180));
        return x - 50;
          })
          .attr("y", function() {
            var y = 200 * Math.cos(-60 * i * (Math.PI / 180));
        return y - 20;
          })
          .attr("width", 100)
          .attr("height", 40)
          .html(function(d, i) {
            return (
              `<input type="text" id="attribute${count}"
              style="height: 40px;" value="Text goes here" />`
            );
          });
      });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg viewbox="-250 -250 500 500" width="400"  id="target"></svg>

演示:

【讨论】:

  • 这并不能解决我的实际问题。我喜欢你的回答,但我的问题与反应组件更相关。如何将反应组件添加为异物?现在,如果用户在该输入框中更改了值,我如何通知 React App 中的父组件。
  • 好的,请添加您的反应代码(作为一个最小的可重现示例)并尝试在您的问题中解决它,然后我可以尝试更新我的答案。
猜你喜欢
  • 2022-11-02
  • 1970-01-01
  • 2012-06-27
  • 2021-10-19
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多