代码之家  ›  专栏  ›  技术社区  ›  Jay Jeong

对d3的selectall方法的好奇

  •  3
  • Jay Jeong  · 技术社区  · 7 年前

    HTML格式:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
      </head>
      <body>
         <svg></svg>
      </body>
    </html>
    

    JS公司:

        dummyData = [
             {
               name: 'A',
               age: 50
             },
             {
               name: 'B',
               age: 20
             }
           ]
    
        svg = d3.select('svg')
                .attr('width','500')
                .attr('height', '300')
              .append('g')
                .attr('transform','translate(40, 40)');
    
    
    function example_1() {
    
        svg.selectAll('circle')
          .data(dummyData)
          .enter()
        .append('circle')
          .attr('transform', d => `translate(${d.age}, 20)`)
          .attr('cx',32).attr('cy',53)
          .attr('r',15);
    
     }
    
    
    function example_2() {
    
        svg.selectAll('g')
          .data(dummyData)
          .enter()
        .append('circle')
          .attr('transform', d => `translate(${d.age}, 20)`)
          .attr('cx',32)
          .attr('cy',53)
          .attr('r',15);
    }
    
    function example_3() {
    
        svg.selectAll('div')  // This div is an arbitrary value. It can be any html tag to output the same result 
          .data(dummyData)
          .enter()
        .append('circle')
          .attr('transform', d => `translate(${d.age}, 20)`)
          .attr('cx',32)
          .attr('cy',53)
          .attr('r',15);
    
     }
    
    function example_4() {
    
       svg.selectAll('g')
          .data(dummyData)
          .enter()
        .append('circle')
          .attr('transform', d => `translate(${d.age}, 20)`)
          .attr('cx',32)
          .attr('cy',53)
          .attr('r',15);
    
        svg.selectAll('g')
          .data(dummyData)
          .enter()
        .append('path')
          .attr('stroke','#000')
          .attr('d',`M5,5H500`)
    }
    
    function example_5() {
    
       svg.selectAll('g')
          .data(dummyData)
          .enter()
        .append('circle')
          .attr('transform', d => `translate(${d.age}, 20)`)
          .attr('cx',32)
          .attr('cy',53)
          .attr('r',15);
    
        svg.selectAll('g')
          .data(dummyData)
          .enter()
        .append('g')
        .append('path')
          .attr('stroke','#000')
          .attr('d',`M5,5H500`)
    }
    
    
    example_1(); // This one creates DOM as: 
    
    <svg>
      <g>
        <circle></circle>
        <circle></circle>
      </g>
    </svg>
    
    example_2(); // This one creates DOM as:
    
    <svg>
      <g>
        <circle></circle>
        <circle></circle>
        <circle></circle>
        <circle></circle>
      </g>
    </svg>
    
    example_3(); // This one creates DOM as:
    
    <svg>
      <g>
        <circle></circle>
        <circle></circle>
        <circle></circle>
        <circle></circle>
      </g>
    </svg>
    
    example_4(); // This one creates DOM as:
    
    <svg>
      <g>
        <circle></circle>
        <circle></circle>
        <path></path>
        <path></path>
        <circle></circle>
        <circle></circle>
        <path></path>
        <path></path>
      </g>
    </svg>
    
    example_5(); // This one creates DOM as:
    
    <svg>
      <g>
        <circle></circle>
        <circle></circle>
        <g>
          <path></path>
        </g>
        <g>
          <path></path>
        </g>
      </g>
    </svg>
    

    在我的示例中,变量svg是作为svg的子级的dom节点g。这意味着它没有一个圆,也没有G或div作为它的孩子。那么selectAll方法用于什么?为什么我们不能写

    svg.data(dummyData)
      .enter()
    .append('circle')
      .attr('transform', d => `translate(${d.age}, 20)`)
      .attr('cx',32).attr('cy',53)
      .attr('r',15);
    

    虽然我尝试了更多不同的例子,但它们的表现都不同,但我真的看不到幕后发生了什么。 请至少帮助我理解一点。我很困惑。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Mark    7 年前

    我们先回答你最后一个问题。为什么你不能:

    svg.data(dummyData).enter()
    

    d3 .selectAll 为我找到与选择器匹配的所有元素。 .data 将数据绑定到它们。 .enter 告诉我所有的数据元素 不是 在我的 .全选 是的。所以,你的问题的答案是,没有 .全选 ,没有办法 D3号 计算哪些数据是 套房 没有附加任何内容。在经典用法中,在初始渲染时, .全选 返回空(它们都不存在),因此它们都在输入。

    现在,让我们以基本知识为基础,按照您的示例5:

    svg.selectAll('g') //<-- no gs exist in svg
      .data(dummyData)
      .enter() //<-- so, since data is two elements
    .append('circle') //<-- you get two circles
      .attr('transform', d => `translate(${d.age}, 20)`)
      .attr('cx',32)
      .attr('cy',53)
      .attr('r',15);
    
    svg.selectAll('g') //<-- no gs still exist in svg
      .data(dummyData)
      .enter() //<-- so since data is two elements
    .append('g') //<-- you get two gs
    .append('path') //<-- each with a path under them
      .attr('stroke','#000')
      .attr('d',`M5,5H500`)
    

    现在,你所做的在这里没有意义。为什么选择 g 圆代表我的每一个数据 ,我会这样做:

    svg.selectAll('.my_cool_circle')
      .data(dummyData)
      .enter()
    .append('circle')
    .attr('class', 'my_cool_circle')
    ...
    

    通过使用一个类,我知道那些圆代表我的 dummyData 是的。另外,如果我以后需要回来 更新 我的圆圈(因为我的数据现在是:

    dummyData = [
         {
           name: 'A',
           age: 50
         },
         {
           name: 'B',
           age: 20
         },
         {
           name: 'C',
           age: 30
         }          
       ]
    

    )

    然后:

     svg.selectAll('.my_cool_circle')
      .data(dummyData)
      .enter()
    

    只返回“C”基准,我只追加一个新圆。