Draw connection after node is moved in d3 org chart

38 views Asked by At

I want to draw a connection between nodes (node1 and node2) after moving certain node2 to different position using custom layout binding (nodeUpdateTransform). In the following example the connection is drawn to origin position of the nodes. How can I adjust the connection if a node has been moved?

const data = [
    { customId: 1, customParentId: null, customName: 'node1' },
    { customId: 2, customParentId: 1, customName: 'node2' },
    { customId: 3, customParentId: 1, customName: 'node3' },
  ];

  chart = new d3.OrgChart()
    .nodeId((dataItem) => dataItem.customId)
    .parentNodeId((dataItem) => dataItem.customParentId)
    .nodeWidth((node) => 100)
    .nodeHeight((node) => 100)
    .nodeContent((node) => {
      return `<div customId="${node.data.customId}" 
        style="background-color:aqua;width:${node.width}px;height:${node.height}px"
      > 
           ${node.data.customName}
       </div>`;
    })
    .container('.chart-container')
    .data(data)
    .render();
  
  i=0;
  const layout = chart.layoutBindings();
  layout.top.nodeUpdateTransform = function(node){
    if(i==1){
      i+=1;
      return `translate(${(node.x-100) - node.width / 2},${node.y})`;
    }
    //console.log(node.parentNode);
    i+=1;
    return `translate(${(node.x) - node.width / 2},${node.y})`;
  }
  
  chart.layoutBindings(layout);
  chart.connections([{from:"1",to:"2",label:"Conflicts of interest"}]).render();    
  
1

There are 1 answers

2
Mark On BEST ANSWER

I got this from looking at the source code to d3-org-chart. Adding this line seems to do it:

layout.top.linkJoinX = node => node.x - 100;

Running code:

const data = [{
    customId: 1,
    customParentId: null,
    customName: 'node1'
  },
  {
    customId: 2,
    customParentId: 1,
    customName: 'node2'
  },
  {
    customId: 3,
    customParentId: 1,
    customName: 'node3'
  },
];

chart = new d3.OrgChart()
  .nodeId((dataItem) => dataItem.customId)
  .parentNodeId((dataItem) => dataItem.customParentId)
  .nodeWidth((node) => 100)
  .nodeHeight((node) => 100)
  .nodeContent((node) => {
    return `<div customId="${node.data.customId}" 
            style="background-color:aqua;width:${node.width}px;height:${node.height}px"
          > 
               ${node.data.customName}
           </div>`;
  })
  .container('.chart-container')
  .data(data);

i = 0;
const layout = chart.layoutBindings();
layout.top.nodeUpdateTransform = function(node) {
  if (i == 1) {
    i += 1;
    return `translate(${(node.x-100) - node.width / 2},${node.y})`;
  }
  //console.log(node.parentNode);
  i += 1;
  return `translate(${(node.x) - node.width / 2},${node.y})`;
}

layout.top.linkJoinX = node => node.x - 100;

chart.layoutBindings(layout);
setTimeout(function() {
  chart.connections([{
    from: "1",
    to: "2",
    label: "Conflicts of interest"
  }]).render();
}, 500);
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/d3-flextree.js"></script>

<div class="chart-container"></div>