简体   繁体   English

D3.js多维数组

[英]D3.js multi-dimension array

I'm just getting started with D3.js and it's great, but a steep learning curve. 我刚刚开始使用D3.js,这很棒,但学习曲线陡峭。 I've got the following code. 我有以下代码。

var local = d3.local();

var data2 = [
  {
    id: 1,
    name: "reg1",
    movements: [
      {
        id: 1,
        text: "mov1",
        start: new Date(2017, 1, 1, 17, 0, 0, 0),
        end: new Date(2017, 1, 1, 17, 30, 0, 0)
      },
      {
        id: 2,
        text: "mov2",
        start: new Date(2017, 1, 1, 16, 0, 0, 0),
        end: new Date(2017, 1, 1, 16, 30, 0, 0)
      },
      {
        id: 3,
        text: "mov3",
        start: new Date(2017, 1, 1, 15, 0, 0, 0),
        end: new Date(2017, 1, 1, 15, 30, 0, 0)
      }
    ]
  },
  {
    id: 2,
    name: "reg2",
    movements: [
      {
        id: 5,
        text: "mov4",
        start: new Date(2017, 1, 1, 15, 0, 0, 0),
        end: new Date(2017, 1, 1, 15, 45, 0, 0)
      },
      {
        id: 6,
        text: "mov5",
        start: new Date(2017, 1, 1, 18, 0, 0, 0),
        end: new Date(2017, 1, 1, 18, 45, 0, 0)
      },
      {
        id: 7,
        text: "mov6",
        start: new Date(2017, 1, 1, 22, 0, 0, 0),
        end: new Date(2017, 1, 1, 23, 45, 0, 0)
      }
    ]
  }
];

var svg = d3
  .select("body")
  .append("svg")
  .attr("width", 1500)
  .attr("height", 500);

svg
  .append("g")
  .selectAll("g")
  .data(data2)
  .enter()

  .append("text")
  .text(function(d, i, j) {
    return d.name;
  })
  .attr("x", function(d, i, j) {
    return  40;
  })
  .attr("y", function(d, i, j) {
    return i* 20 + 40;
  })
  .attr("font-family", "sans-serif")
  .attr("font-size", "20px")
  .append("g") //removing
  .selectAll("text") // these
  .data(function(d, i, j) {
    local.set(this, i);
    return d.movements;
  }) //lines
  .enter() //text displays normally
  .append("text")
  .text(function(d, i, j) {
    return d.start.getHours();
  })
  .attr("x", function(d, i, j) {
    return i * 300 + 40;
  })
  .attr("y", function(d, i, j) {
    return local.get(this) * 20 + 40;
  })
  .attr("font-family", "sans-serif")
  .attr("font-size", "20px");

What I don't understand is why the hours aren't being shown correctly. 我不明白为什么时间没有正确显示。 This is what's getting generated 这就是生成的东西

 <svg width="1500" height="500">
    <g>
        <text x="40" y="40" font-family="sans-serif" font-size="20px">reg1
            <g>
                <text x="40" y="40" font-family="sans-serif" font-size="20px">17</text>
                <text x="340" y="40" font-family="sans-serif" font-size="20px">16</text>
                <text x="640" y="40" font-family="sans-serif" font-size="20px">15</text>
            </g>
        </text>
        <text x="40" y="60" font-family="sans-serif" font-size="20px">reg2
            <g>
                <text x="40" y="60" font-family="sans-serif" font-size="20px">15</text>
                <text x="340" y="60" font-family="sans-serif" font-size="20px">18</text>
                <text x="640" y="60" font-family="sans-serif" font-size="20px">22</text>
            </g>
        </text>
    </g>
</svg>

Obviously I want the </text> to come before the <g> tag but I can't see what I've done wrong. 显然我希望</text>出现在<g>标签之前,但我看不出我做错了什么。 Any ideas? 有任何想法吗?

The problem is that you are appending a <g> element to a <text> element. 问题是您要将<g>元素附加到<text>元素。 Appending element A to element B places element A as a child in element B. This is why the text close tag comes where it does. 将元素A附加到元素B将元素A作为子元素放在元素B中。这就是文本关闭标记到达它的位置的原因。

Why does your code do this? 为什么你的代码会这样做?

You need to keep track of what object is returned by each method when chaining, especially when selecting, entering, appending multiple times in a row. 链接时,您需要跟踪每个方法返回的对象,尤其是在连续多次选择,输入和追加时。 The following code block uses your code, but I've stripped out all the .attr and .text methods as these methods just return the same selection they modify. 下面的代码块使用了你的代码,但我已经删除了所有.attr.text方法,因为这些方法只返回他们修改的相同选择。 Remember that each line (other than the first) invokes a method of the object returned by the line above it: 请记住,每一行(除了第一行)都会调用上面一行返回的对象的方法:

svg.append("g")     // returns the new <g> in a selection
  .selectAll("g")   // returns a null selection with the 1st <g> as the parent element
   .data(data2)              
  .enter()          // returns a selection of elements to create in the 1st <g> based on the data  
  .append("text")   // returns a selection of text elements in the 1st <g>
  .append("g")      // returns a selection of <g> elements appended to the <text> elements 
  .selectAll("text")// returns a null selection of <text> elements in those <g> elements in the <text> elements
  .data(function(d, i, j) {  }) 
  .enter()         // returns a selection of elements to create in those <g> elements in the <text> elements in the 1st <g>
  .append("text")  // ....

You can see that you have a selection of text elements to which you append child g tags (and to those more text). 您可以看到您有一些文本元素可以附加到子g标签(以及更多文本)。

Instead, break the chain up. 相反,打破链条。 Append parent g elements right away to separate your different datums and store these in a selection. 立即附加父g元素以分隔不同的基准并将其存储在选择中。 Then append text and child g elements to this selection based on the bound data: 然后根据绑定数据将text和child g元素附加到此选择:

 var data2 = [ { id: 1, name: "reg1", movements: [ { id: 1, text: "mov1", start: new Date(2017, 1, 1, 17, 0, 0, 0), end: new Date(2017, 1, 1, 17, 30, 0, 0) }, { id: 2, text: "mov2", start: new Date(2017, 1, 1, 16, 0, 0, 0), end: new Date(2017, 1, 1, 16, 30, 0, 0) }, { id: 3, text: "mov3", start: new Date(2017, 1, 1, 15, 0, 0, 0), end: new Date(2017, 1, 1, 15, 30, 0, 0) } ] }, { id: 2, name: "reg2", movements: [ { id: 5, text: "mov4", start: new Date(2017, 1, 1, 15, 0, 0, 0), end: new Date(2017, 1, 1, 15, 45, 0, 0) }, { id: 6, text: "mov5", start: new Date(2017, 1, 1, 18, 0, 0, 0), end: new Date(2017, 1, 1, 18, 45, 0, 0) }, { id: 7, text: "mov6", start: new Date(2017, 1, 1, 22, 0, 0, 0), end: new Date(2017, 1, 1, 23, 45, 0, 0) } ] } ]; var svg = d3 .select("body") .append("svg") .attr("width", 1500) .attr("height", 500); // a group for each data array item var g = svg.selectAll("g") .data(data2) .enter() .append("g") .attr("transform", function(d,i) { return "translate("+[40,i*20+40]+ ")" }) // some text for each group array item g.append("text") .text(function(d) { return d.name; }) .attr("font-family", "sans-serif") .attr("font-size", "20px"); // a sub group with text for each item in the nested data array g.append("g") .selectAll("text") .data(function(d) { return d.movements; }) .enter() .append("text") .text(function(d) { return d.start.getHours(); }) .attr("x", function(d, i, j) { return i * 150 + 60; }) .attr("font-family", "sans-serif") .attr("font-size", "20px"); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM