Sunday, 20 September 2020

How should I bind data to appended elements to a transformed D3.js group?

I am approaching the problem of appending a complex (two or more glyphs) symbol to some data. With D3.js, it seems that the right way to do so is appending the glyphs (in this example, circles) to groups (g) joined to data:

datum <=> g <=> (circle, circle)

In order to achieve this, I wrote the following code (see the notebook), which however does not work as expected

function updatea (){
    a[0].start += 10*Math.sin(t);
    a[0].end += 10*Math.cos(t);
    console.log(a[0].end - a[0].start);
    t += 0.1;
    
    var miao = svg.selectAll('g.aaa').data(a).join('g')
        .classed('aaa',true)
        .attr('transform',(d, i)=>('translate('+d.start+','+(i+1)*50+')'));
    miao.append('circle').attr('r', 10).attr('fill','red');
    miao.append('circle').attr('r', 10).attr('cx', d=>d.end).attr('fill','red');
  }

The expected result would be as follows: two circles oscillate around their initial position, with a phase of period/4 between them. Instead, the second circle (to which I assigned an attribute cx, in order to give the position relative to the first one) is not refreshed, but instead all of its positions are drawn one after the other, oscillating with the translation in the attribute "transform".

translate without update


I think that the problem is appending circles every time I update data; but how should I then append them? I tried something like this, following https://bost.ocks.org/mike/nest/:

var groups = svg.selectAll('g').data(a).enter().append('g').attr('transform',(d, i)=>('translate('+d.start+','+(i+1)*50+')'));
  var circle_start = groups.selectAll('circle').data((d)=>{return d.start;}).enter().append('circle').attr('cx', d=>d).attr('cy', d=>100).attr('r', 10);
  var circle_end = groups.selectAll('circle').data((d)=>{return d.end;}).enter().append('circle').attr('cx', d=>d).attr('cy', d=>100).attr('r', 10);

but it gives no output. Doing a bit of debug, for example assigning another dataset to one of the two circles, apparently the problem lies in .data(d)=>{return d.end;}).



from How should I bind data to appended elements to a transformed D3.js group?

No comments:

Post a Comment