0
votes

The transition between links is not working for me in my d3 tree diagram it is a vertical tree with rectangular nodes so i edited attr which shapes the link to fit my diagram

original code:

var link = svg.selectAll('path.link')
      .data(links, function(d) { return d.id; });

  // Enter any new links at the parent's previous position.
  var linkEnter = link.enter().insert('path', "g")
      .attr("class", "link")
      .attr('d', function(d){
        var o = {x: source.x0, y: source.y0}
        return diagonal(o, o)
      });

  // UPDATE
  var linkUpdate = linkEnter.merge(link);

  // Transition back to the parent element position
  linkUpdate.transition()
      .duration(duration)
      .attr('d', function(d){ return diagonal(d, d.parent) });

  // Remove any exiting links
  var linkExit = link.exit().transition()
      .duration(duration)
      .attr('d', function(d) {
        var o = {x: source.x, y: source.y}
        return diagonal(o, o)
      })
      .remove();

function diagonal(s, d) {

    path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`

    return path
  }

Updated code with a manipulated diagonal that is directly added as an attr:

// Update the links...
            var link = svg.selectAll('path.link')
                .data(links, function(d) { return d.id; });

            // Enter any new links at the parent's previous position.
            var linkEnter = link.enter().insert('path', "g")
                .attr("class", "link")
                .attr("d", function(d) {
                return "M" + (d.x  + rectW / 2) +  "," + (d.y + rectH / 2)
                    + "C" + (d.x  + rectW / 2) + "," + (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," +  (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," + (d.parent.y + rectH / 2);
                });

            // UPDATE
            var linkUpdate = linkEnter.merge(link);

            // Transition back to the parent element position
            linkUpdate.transition()
                .duration(0)
                .attr("d", function(d) {
                return "M" + (d.x  + rectW / 2) +  "," + (d.y + rectH / 2)
                    + "C" + (d.x  + rectW / 2) + "," + (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," +  (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," + (d.parent.y + rectH / 2);
                })

            // Remove any exiting links
            var linkExit = link.exit().transition()
                .duration(duration)
                .attr("d", function(d) {
                return "M" + (d.x  + rectW / 2) +  "," + (d.y + rectH / 2)
                    + "C" + (d.x  + rectW / 2) + "," + (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," +  (d.y + d.parent.y) / 2
                    + " " + (d.parent.x + rectW / 2) + "," + (d.parent.y + rectH / 2);
                })
                .remove();

I've noticed the attr that shapes the links in my updated code is the same for linkEnter, linkUpdateTransition and linkExit but for the original code the linkUpdateTransition is different, since I pretty much got my attr working by trail and error I'm not sure how to adjust the linkUpdateTransition attr to have a smooth transition

1
What is broken with it? Can you share a minimal working example? While it may be possible to guess what is wrong based on sharing only the transition info, sharing a minimal working example that demonstrates the problem and shows additional code is much more likely to be successful. - Andrew Reid
the transition does not work, the links just appear while the nodes move in transition, re working example how do I do that sorry I rarely ask questions. - mmohamud1
That clarification helps in suggesting what the issue is ("does not work" by itself is almost never useful as there are many ways things can not work). My guess with this extra info is you are interpolating from nothing: when you expand a node you create a new one(s) overtop of it and transition it away, but you don't define path data for this link initially because it appears unnecessary (the points are on top of each other). This would cause that behavior. The challenge is that I can't verify this guess or propose a solution because you haven't shared minimal code to reproduce the problem. - Andrew Reid
Hopefully my edit to the question gives more clarity - mmohamud1
That looks like it could help. I've had something unforeseen come up and may not be able to revisit the question for a few days though - I hope that another pair of eyes might provide some more info in the meantime. - Andrew Reid

1 Answers

0
votes

Not sure if this helps anyone but I did end up figuring it out and it turned out to be a combination of my updated code and the original code, below I'll put the working links section

            // Update the links...
            var link = svg.selectAll('path.link')
                .data(links, function(d) { return d.id; });

            // Enter any new links at the parent's previous position.
            var linkEnter = link.enter().insert('path', "g")
                .attr("class", "link")
                .attr('d', function(d) {
                    var o = {x: source.x0, y: source.y0,};
                    return diagonal(o, o);
                });

            // UPDATE
            var linkUpdate = linkEnter.merge(link);

            // Transition back to the parent element position
            linkUpdate.transition()
                .duration(duration)
                .attr('d', function(d) { return diagonal(d, d.parent); });

            // Remove any exiting links
            var linkExit = link.exit().transition()
                .duration(duration)
                .attr('d', function(d) {
                    var o = {x: source.x, y: source.y};
                    return diagonal(o, o);
                })
                .remove();

             // Creates a curved (diagonal) path from parent to the child nodes
             function diagonal(s, d) {
                path = 'M ' + (s.x + rectW / 2) + ' ' + (s.y + rectH / 2) +
                        'C ' + (s.x + rectW / 2 ) + ' ' + (s.y + d.y) / 2 +
                        ', ' + (d.x + rectW / 2) + ' ' + (s.y + d.y) / 2  +
                        ', ' + (d.x + rectW / 2) + ' ' + (d.y + rectH / 2);
                return path;
            }