1
"nodes": [
{
  "data": {
    "id": 1,
    "desc": "Rohit",
    "pos": [
      121.0284957885742,
      116.3165512084961,
      59.36788940429688
    ]
   }
  },
  {
  "data": {
    "id": 2,
    "desc": "Deep",
    "pos": [
      12.10284957885742,
      116.3165512084961,
      5.936788940429688
    ]
  }
 },
 "data": {
    "id": 3,
    "desc": "Deepa",
    "pos": [
      12.10284957885742,
      11.63165512084961,
      5.936788940429688
    ]
   }
  }
  ]

The above is the co-ordinates of nodes.

"edges": [
{
  "data": {
    "id": "1_2",
    "source": 1,
    "target": 2
  }
}

The above is a sample input for the link. How can I create and assign the positions of nodes in d3 according to the given co-ordinates? I've tried with co-ordinates which has pixel as unit of the co-ordinates but the above sample set does not contain any units as such.

The full code is below...

<!DOCTYPE html>
<meta charset="utf-8">
<style>
 .node {
   fill: blue;
   stroke: black;
   stroke-width: 2px;
  }

 .node.visited {
   fill: red;
 }

 .link {
   stroke-width: 2px;
 }
</style>

<body>
 <script src="https://d3js.org/d3.v3.min.js"></script>
 <script>
   var width = 640,
       height = 480;

   var links = [{
       source: 'Rohit',
       target: 'Deep'
     },
     {
       source: 'Deep',
       target: 'Deepa'
     },
     {
       source: 'Deepa',
       target: 'Rohit'
     },
   ];


     var nodes = [{
    "id": 1,
    "desc": "Rohit",
    "x": 121.0284957885742,
    "y": 116.3165512084961,
    "z": 59.36788940429688
  },
  {
    "id": 2,
    "desc": "Deep",
    "x": 12.10284957885742,
    "y": 116.3165512084961,
    "z": 5.936788940429688
  },
  {
    "id": 3,
    "desc": "Deepa",
    "x": 12.10284957885742,
    "y": 11.63165512084961,
    "z": 135.936788940429688
  }
];

   

   //adding svg to body

   var svg = d3.select('body').append('svg')
     .attr('width', width)
     .attr('height', height);

   var defs = svg.append('defs');

   var gradient = defs
     .append('linearGradient')
     .attr('id', 'svgGradient')
     .attr('x1', '0%')
     .attr('x2', '10%')
     .attr('y1', '0%')
     .attr('y2', '10%');

   gradient
     .append('stop')
     .attr('class', 'start')
     .attr('offset', '0%')
     .attr('start-color', 'red')
     .attr('start-opacity', 1);

   gradient
     .append('stop')
     .attr('class', 'end')
     .attr('offset', '100%')
     .attr('stop-color', 'blue')
     .attr('stop-opacity', 1);

   var force = d3.layout.force()
     .size([width, height])
     .nodes(d3.values(nodes))
     .links(links)
     .on("tick", tick)
     .linkDistance(300)
     .start();

   var link = svg.selectAll('.link')
     .data(links)
     .enter().append('line')
     .attr('class', 'link')
     .attr('stroke', 'url(#svgGradient)');

   var node = svg.selectAll('.node')
     .data(force.nodes())
     .enter().append('circle')
     .attr('class', 'node')
     .on("click", clicked)
     .attr('r', width * 0.03);

   function clicked(event, d) {
     if (event.defaultPrevented) return; // dragged

     d3.select(this).transition()
       .style("fill", "black")
       .attr("r", width * 0.2)
       .transition()
       .attr("r", width * 0.03)
       .transition()
       .style("fill", "blue")
       //.attr("fill", d3.schemeCategory10[d.index % 10]);
   }


   //define the tick func.
   function tick(e) {
     node
       .attr('cx', function(d) {
         return d.x;
       })
       .attr('cy', function(d) {
         return d.y;
       })
       .call(force.drag);

     link
       .attr('x1', function(d) {
         return d.source.x;
       })
       .attr('y1', function(d) {
         return d.source.y;
       })
       .attr('x2', function(d) {
         return d.target.x;
       })
       .attr('y2', function(d) {
         return d.target.y;
       })

   }
    </script>
  </body>
</html>

Any changes to the above code snippet is acceptable. What can I try next?


Edit

I ran the code but the nodes are not accepting the positions assigned to them.

Here is the image of the result that has come after running the code

As you can see there is no defined edge in the force-directed graph and also the positions of the nodes do not change with the change in the co-ordinates.

halfer
  • 19,824
  • 17
  • 99
  • 186
  • Does this answer your question? [Fix Node Position in D3 Force Directed Layout](https://stackoverflow.com/questions/10392505/fix-node-position-in-d3-force-directed-layout) – Robin Mackenzie Jan 22 '23 at 11:04

1 Answers1

1

Try this solution:

var width = 640;
var height = 480;

var links = [{
    source: 'Rohit',
    target: 'Deep'
  },
  {
    source: 'Deep',
    target: 'Deepa'
  },
  {
    source: 'Deepa',
    target: 'Rohit'
  },
];

var nodes = [{
    "id": 1,
    "desc": "Rohit",
    "x": 121.0284957885742,
    "y": 116.3165512084961,
    "z": 59.36788940429688
  },
  {
    "id": 2,
    "desc": "Deep",
    "x": 12.10284957885742,
    "y": 116.3165512084961,
    "z": 5.936788940429688
  },
  {
    "id": 3,
    "desc": "Deepa",
    "x": 12.10284957885742,
    "y": 11.63165512084961,
    "z": 5.936788940429688
  }
];

//adding to nodes
links.forEach(function(link) {
  link.source = nodes[link.source] ||
    (nodes[link.source] = {
      name: link.source
    });

  link.target = nodes[link.target] ||
    (nodes[link.target] = {
      name: link.target
    });
});

//adding svg to body

var svg = d3.select('body').append('svg')
  .attr('width', width)
  .attr('height', height);

var defs = svg.append('defs');

var gradient = defs
  .append('linearGradient')
  .attr('id', 'svgGradient')
  .attr('x1', '0%')
  .attr('x2', '10%')
  .attr('y1', '0%')
  .attr('y2', '10%');

gradient
  .append('stop')
  .attr('class', 'start')
  .attr('offset', '0%')
  .attr('start-color', 'red')
  .attr('start-opacity', 1);

gradient
  .append('stop')
  .attr('class', 'end')
  .attr('offset', '100%')
  .attr('stop-color', 'blue')
  .attr('stop-opacity', 1);

var force = d3.layout.force()
  .size([width, height])
  .nodes(d3.values(nodes))
  .links(links)
  .on("tick", tick)
  .linkDistance(300)
  .start();

var link = svg.selectAll('.link')
  .data(links)
  .enter().append('line')
  .attr('class', 'link')
  .attr('stroke', 'url(#svgGradient)');

var node = svg.selectAll('.node')
  .data(force.nodes())
  .enter().append('circle')
  .attr('class', 'node')
  .on("click", clicked)
  .attr('r', width * 0.03)
  .attr('cx', function(d) {
    return d.x;
  })
  .attr('cy', function(d) {
    return d.y;
  });



function clicked(event, d) {
  if (event.defaultPrevented) return; // dragged

  d3.select(this).transition()
    .style("fill", "black")
    .attr("r", width * 0.2)
    .transition()
    .attr("r", width * 0.03)
    .transition()
    .style("fill", "blue")
  //.attr("fill", d3.schemeCategory10[d.index % 10]);
}


//define the tick func.
function tick(e) {
  node
    .attr('cx', function(d) {
      return d.x;
    })
    .attr('cy', function(d) {
      return d.y;
    })
    .call(force.drag);

  link
    .attr('x1', function(d) {
      return d.source.x;
    })
    .attr('y1', function(d) {
      return d.source.y;
    })
    .attr('x2', function(d) {
      return d.target.x;
    })
    .attr('y2', function(d) {
      return d.target.y;
    })

}
.node {
  fill: blue;
  stroke: black;
  stroke-width: 2px;
}

.node.visited {
  fill: red;
}

.link {
  stroke-width: 2px;
}
<script src="https://d3js.org/d3.v3.min.js"></script>