【问题标题】:Linking up JSON data to g elements in d3将 JSON 数据链接到 d3 中的 g 元素
【发布时间】:2018-01-08 18:30:13
【问题描述】:

所以我在 d3 中遇到了一个问题。我有这个 JSON 文件

{
  "nodes": [
    {"container": "Container 1", "x" : 0, "y" : 0, "px" : 0, "py": 0, "col" : 1, "row" : 0, "height" : 100, "width" : 100},
    {"container": "Container 2", "x" : 100, "y" : 0, "px" : 0, "py": 0, "col" : 1, "row" : 0, "height" : 100, "width" : 100}]
}

我使元素对应于 JSON 中节点的长度。在每个元素内部,都会有一个元素对应于上面描述的容器 1 的数据,依此类推,另一个元素对应于容器 2。

我想要的文件框架是:

<svg>
    <g>
       <rect>Container 1</rect>
    </g>
    <g>
       <rect>Container 2></rect>
    </g>
</svg>

我迷路的地方就是这个

gCode.append("rect").data(graph.nodes)
            .enter()
            .attr('class', 'blob')
            .style("border", "20px solid")

因为我不知道 JSON 文件的大小,我想知道在生成 g 元素时,第一个元素是否会对应于容器 1,然后以此类推。

我尝试过的事情

我正在实现一个 forEach 函数,但被建议不要这样做,因为它稍后会出现问题,我怀疑这里可能是同样的情况。

【问题讨论】:

    标签: javascript json d3.js svg


    【解决方案1】:

    这里发生了一些事情,我可能误解了这个问题(我查看了您之前的 question 以更好地理解上下文)。

    首先,“我想知道在生成 g 元素时,第一个元素是否对应于容器 1”

    当使用 d3 输入数据时,项目按提供的顺序附加 - 因此创建的第一个元素将数据数组中第一个项目的数据绑定到它。如果您的数据已经有序,那么它们将按顺序附加。

    如果您的&lt;g&gt; 元素已存在于您要附加&lt;rect&gt;s 的选择中,则数据集中的第一项将绑定到选择中第一个&lt;g&gt; 中的&lt;rect&gt;

    其次(如果我正确阅读了您的问题),如果您尝试使用相同的数据在每个 &lt;g&gt; 中创建一个 &lt;rect&gt; - 那么为什么不为数据集中的每个项目附加一个 &lt;g&gt;,然后,使用绑定到每个&lt;g&gt; 的数据,将&lt;rect&gt; 附加到每个&lt;g&gt;。这会给你一个你想要的结构:

    <svg>
      <g>
         <rect class="Container1" x="0" y="0" width="100" height="100"></rect>
      </g>
      <g>
          <rect class="Container2" x="100" y="100" width="100" height="100"></rect>
      </g>
    </svg>
    

    而且可以很容易地完成:

    var data = {
    "nodes": [
      {"container": "Container1", "x" : 0, "y" : 0, "px" : 0, "py": 0, "col" : 1, "row" : 0, "height" : 100, "width" : 100},
      {"container": "Container2", "x" : 100, "y" : 100, "px" : 0, "py": 0, "col" : 1, "row" : 0, "height" : 100, "width" : 100}]
    }
    
    var svg = d3.select("body")
      .append("svg")
      .attr("width",400)
      .attr("height",300);
      
    // Append one <g> for each item in the data array:  
    var g = svg.selectAll("g")
      .data(data.nodes)
      .enter()
      .append("g");
      
    // Append a rectangle to each <g> based on the data bound to that <g>:  
    g.append("rect")
      .attr("x", function(d) { return d.x; })
      .attr("y", function(d) { return d.y; })
      .attr("width",function(d) { return d.width; })
      .attr("height",function(d) { return d.height; })
      .attr("class", function(d) { return d.container; });
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"&gt;&lt;/script&gt;

    这种方法将 json 中的数据链接(绑定)到 g,这很容易用于在每个 g 中创建新的子元素,这基于你的标题和目标,看起来就像你的目标为。

    【讨论】:

    • 啊,这更有意义了,感觉我的前进方式会让事情变得更加复杂。
    • @SulimanSharif 说起来不太好(“我的前进方向会让事情变得更加复杂”)。在我对您的previous question 的解决方案中,我只是展示了如何通过输入选择执行您尝试执行的任何操作。如果你有XY problem,那不是我的错。
    • @GerardoFurtado ?我想你误解了这一点。这意味着我接受了你关于不使用 forEach 函数的建议,我相信这是我在这个问题上再次前进的方式。不反对您之前所说的答案。
    • 好的,我以为您指的是上一个答案。无论如何,上一个答案和这个答案都向您展示了如何进行正确的“输入”选择,坚持这种惯用的方法。
    猜你喜欢
    • 2017-07-10
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    相关资源
    最近更新 更多