Appending multiple non-nested elements for each data member with D3.js

后端 未结 6 1847
无人及你
无人及你 2020-12-04 19:14

I would like to create multiple non-nested elements using d3 to create a structure like this:

    

from data[0] &l

相关标签:
6条回答
  • 2020-12-04 19:31

    Similar to the above but in a different idiom. This is truer to the nested selections approach and eliminates the need for sorting or insertion:

    var divs = d3.select('#parent');
    
    var ps = divs.selectAll('#parent > div')
        .data(d3.range(3)).enter().append('div');
    
    ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; });
    ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; });
    

    More elegantly (and probably faster):

    var divs = d3.select('#parent');
    
      var ps = divs.selectAll('#parent > div')
        .data(d3.range(3)).enter().append('div');
    
        ps.append('p').html(function(d,i) { return 'from data[' + i + ']'; })
        .select(function() { return this.parentNode.appendChild(this.cloneNode(true)); });
    
    0 讨论(0)
  • 2020-12-04 19:33

    Use append() for the first item and insert() for the second. This eliminates any need to sort afterwards (thanks to @scuerda's comment for pointing this out) (JSFiddle):

    data = [{}, {}, {}];
    var enterSelection = d3.select('#parent').selectAll('p').data(data).enter()
    
    enterSelection.append('p').text(function(d, i) {return 'from data[' + i + ']'})
    enterSelection.insert('p').text(function(d, i) {return 'from data[' + i + ']'})
    

    This will give you the exact structure requested:

    <p>from data[0]</p>
    
    <p>from data[0]</p>
    
    <p>from data[1]</p>
    
    <p>from data[1]</p>
    
    <p>from data[2]</p>
    
    <p>from data[2]</p>
    
    0 讨论(0)
  • 2020-12-04 19:42

    1. Duplicate each element

    Create a new list, which contains all element twice (like this):

    doubleData = data.reduce(function (res, current, index, array) {
        return res.concat([current, current]);
    }, []);
    
    d3.select('#parent').selectAll('p').data(doubleData).enter().append('p')
    

    2. Enter twice

    Sometimes you want to do further manipulation on the appended elements. In this case, you maybe want to know if you are accessing the first or the secondly added element. Add a first-paragraph and second-paragraph class to these elements.

    d3.select('#parent').selectAll('.first-paragraph')
      .data(data)
      .enter()
      .append('p')
      .attr('class', 'first-paragraph');
    
    d3.select('#parent').selectAll('.second-paragraph')
      .data(data)
      .enter()
      .append('p')
      .attr('class', 'second-paragraph');
    

    In this case you maybe have to sort the elements based on Adam Pearce's answer.

    0 讨论(0)
  • 2020-12-04 19:48

    The idomatic way of doing is with nesting:

    var divs = d3.select('#parent').selectAll('p').data(data).enter().append('div');
    
    divs.append('p')
    divs.append('p')
    

    Which creates:

    <div id="parent">
      <div>
        <p> from data[0] </p>
        <p> from data[0] </p>
      </div>
    
      <div>
        <p> from data[1] </p>
        <p> from data[1] </p>
      </div>
    
      <div>
        <p> from data[2] </p>
        <p> from data[2] </p>
      </div>
    </div>
    

    If that won't work, save your selection and repeatedly append:

    var enterSelection = d3.select('#parent').selectAll('p').data(data).enter();
    
    enterSelection.append('p')
    enterSelection.append('p')
    

    then sort what you've added:

    d3.select('#parent').selectAll('p').sort(function(a, b){ return a.index - b.index; })
    

    You'll need to add an index property to each element of data that describes the sort order. The normal i is only defined in the context of a particular selection, which is lost when we reselect.

    0 讨论(0)
  • 2020-12-04 19:48

    Instead of a .append(),

    You can also wrap a function that creates new content in a .html()

    d3.select('#parent')
      .selectAll('div')
        .data(data)
      .enter()
        .append('div')
        .html(function(d) {return "<p>" + from data[0] + "<p>" etc..... ;});
    
    0 讨论(0)
  • 2020-12-04 19:54

    You can also do this in a single select/enter cycle as follows

    d3.select('#parent').selectAll('p').data(data).enter().
    append('p').text(function(d) {return 'from data[0]')}).
    select(function() { return this.parentNode; }).
    append('p').text(function(d) {return 'from data[0]')});
    
    0 讨论(0)
提交回复
热议问题