javascript - d3 force layout initial structure -


is possible give d3 force layout kind of structure? wanting show relationship between staff , users, staff can have many users.

however initial layout while correct incomprehensible.

enter image description here

the nodes red outlines staff, , blue outlines users, ideally nice have users below staff, in force hierarchy layout if exist?

var width = document.queryselector('.visualisation').clientwidth,         height = 500;      var svg = d3.select(".visualisation").append("svg")         .attr("width", width)         .attr("height", height);      var force = d3.layout.force()         .gravity(.05)         .linkdistance(100)         .charge(-300)         .size([width, height]);      var sw  = [],         su = [],         workbase = [],         links = [],         edges = [],         simplified = [];      d3.json("test_example.json", function(error, json) {         if (error) throw error;         console.log(json);         var users = [];         json.foreach(function(data){             if(data.workbase == "cherry tree lodge") {                 data.weight = 1;                 links.push({                     target : data.user_id,                     source : data.staff_id,                 });                 users.push(data);             }         });          console.log(nodes);          // json.foreach(function(data) {          // console.log(json);         users.foreach(function(d) {             if(_.findwhere(sw, { name: d.staff_name}) == undefined) {                 sw.push({                      name : d.staff_name,                     id : d.staff_id,                     role : d.role,                     weight:1,                     type : "worker"                 });             }             if(_.findwhere(su, { name: d.service_user}) == undefined) {                 su.push({                     name : d.service_user,                      type : "user",                     id : d.user_id,                     weight:1                 });             }         });          var nodes = sw.concat(su);          console.log(nodes);          nodes.foreach(function(data){             if(typeof data.linked_to != "undefined") {                 links.push({                     target: _.findindex(nodes, function(user) {                          return user.id == data.linked_to;                      }),                     source: data.id                 });             }            });          console.log(links);         // //console.log(json);console.log(links)         links.foreach(function(e){             var sourcenode = nodes.filter(function(n) { return n.id === e.source})[0];             var targetnode = nodes.filter(function(n) { return n.id === e.target})[0];             edges.push({ source: sourcenode, target: targetnode });         });         console.log(edges);         // console.log(nodes);         force             .nodes(nodes)             .links(edges)             .on("tick", tick)             .start();          var link = svg.selectall(".link")             .data(edges)             .enter().append("line")             .attr("class", "link");          var node = svg.selectall(".node")             .data(nodes)             .enter().append("g")             .attr("class", "node")             .call(force.drag);  //          node.append("defs")             // .append("pattern")             // .attr("id", function(d){             //  return "image-" + d.id;             // })             // .attr("height", 50)             // .attr("width", 50)             // .attr("x", 0)             // .attr("y", 0)             // .append("image")             // .attr("xlink:href", function(d) {             //  return d.image;             // })             // .attr('height',60)          //    .attr('width',60)          //    .attr('x',0)          //    .attr('y',0);          node.append("circle")             .attr("class", function(d){                 return d.type;             })             .attr("r", 25);             // .on("mouseover", showdetails)             // .on("mouseout", removedetails);          node.append("text")             .attr("x", 0)             .attr("dy", ".35em")             .attr("text-anchor", "middle")             .text(function(d){                 //return d.name;         });       //     // node.append("svg:a")      //   //    .attr("xlink:href", function(d){ return "" })      //   //    .append("text")      //   //    .attr("dx", 12)      //   //    .attr("dy", ".35em")      //   //    .text(function(d) { return d.name})           function tick(e) {             var k = 6 * e.alpha;              // push sources , targets down form weak tree.             link                 .each(function(d) { d.source.y -= k, d.target.y += k; })                 .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                 .attr("cx", function(d) { return d.x; })                 .attr("cy", function(d) { return d.y; });              node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });         }      }); 

you can achieve setting position along y axis d3.forcey(). according api:

creates new positioning force along y-axis towards given position y.

so, created array using type specify user , staff:

var nodes = [     {"id": 1, "name": "staff1", "type": "staff"},     {"id": 2, "name": "staff2", "type": "staff"},      {"id": 3, "name": "user1", "type": "user"},     {"id": 4, "name": "user2", "type": "user"},     {"id": 5, "name": "user3", "type": "user"},     {"id": 6, "name": "staff3", "type": "staff"},     {"id": 7, "name": "user4", "type": "user"},     {"id": 8, "name": "user5", "type": "user"},     {"id": 9, "name": "user6", "type": "user"},     {"id": 10, "name": "user7", "type": "user"},     {"id": 11, "name": "user8", "type": "user"},     {"id": 12, "name": "user19", "type": "user"} ]; 

then, used type set position:

var simulation = d3.forcesimulation()     .force('y', d3.forcey((d) => d.type === "staff" ? height/5 : 4*height/5).strength(2)) 

here demo:

var nodes = [    {"id": 1, "name": "staff1", "type": "staff"},    {"id": 2, "name": "staff2", "type": "staff"},    {"id": 3, "name": "user1", "type": "user"},    {"id": 4, "name": "user2", "type": "user"},    {"id": 5, "name": "user3", "type": "user"},    {"id": 6, "name": "staff3", "type": "staff"},    {"id": 7, "name": "user4", "type": "user"},    {"id": 8, "name": "user5", "type": "user"},    {"id": 9, "name": "user6", "type": "user"},  	{"id": 10, "name": "user7", "type": "user"},    {"id": 11, "name": "user8", "type": "user"},    {"id": 12, "name": "user19", "type": "user"}  ];    var links = [    {source: 1, target: 8},    {source: 1, target: 3},    {source: 1, target: 4},  	{source: 1, target: 9},  	{source: 1, target: 10},  	{source: 1, target: 11},    {source: 2, target: 5},    {source: 2, target: 6},  	{source: 2, target: 7},  	{source: 2, target: 12},    {source: 2, target: 4},  	{source: 2, target: 8},    {source: 6, target: 7},    {source: 6, target: 8},    {source: 6, target: 9},  	{source: 6, target: 5},    {source: 6, target: 3},    {source: 6, target: 9},  ]    var index = 10;  var svg = d3.select("svg"),      width = +svg.attr("width"),      height = +svg.attr("height"),      node,      link;    var simulation = d3.forcesimulation()      .force("link", d3.forcelink().id(function(d) { return d.id; }))  		.force('y', d3.forcey((d) => d.type === "staff" ? height/5 : 4*height/5).strength(2))      .force("charge", d3.forcemanybody())  		.force("collide", d3.forcecollide(30))      .force("center", d3.forcecenter(width / 2, height / 2));    update();  function update() {    link = svg.selectall(".link")      .data(links, function(d) { return d.target.id; })      link = link.enter()      .append("line")      .attr("class", "link");      node = svg.selectall(".node")      .data(nodes, function(d) { return d.id; })      node = node.enter()      .append("g")      .attr("class", "node")      .on("click", click)      .call(d3.drag()          .on("start", dragstarted)          .on("drag", dragged)          .on("end", dragended));      node.append("circle")      .attr("r", 6)  		.attr("fill", (d)=> d.type === "user" ? "blue" : "red")      node.append("title")        .text(function(d) { return d.id; });      node.append("text")        .attr("dx", 10)        .text(function(d) { return d.name; });      simulation        .nodes(nodes)        .on("tick", ticked);      simulation.force("link")        .links(links);  }    function click(d) {    nodes.push({id: index, name: "server " + index});    links.push({source: d.id, target: index});    index++;    update();  }    function ticked() {    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        .attr("transform", function(d) { return "translate(" + d.x + ", " + d.y + ")"; });  }    function dragstarted(d) {    if (!d3.event.active) simulation.alphatarget(0.3).restart()  }    function dragged(d) {    d.fx = d3.event.x;    d.fy = d3.event.y;  }    function dragended(d) {    if (!d3.event.active) simulation.alphatarget(0);    d.fx = undefined;    d.fy = undefined;  }
.link {    stroke: #aaa;  }    .node {    pointer-events: all;    stroke: none;    stroke-width: 40px;  }
<script src="https://d3js.org/d3.v4.min.js"></script>  <svg width="400" height="400"></svg>


Comments

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -