d3.js force directed tree matrix d3.js force directed tree matrix

In previous applications, I have adapted standalone trees into a "matrix" format that uses rows and columns to display many small hierarchical relationships in one visual. See: D3.js v5 - Swarm Tree - How to iteratively center swarms around tree nodes

For the next project, I was attempting the same thing but with "force-directed-trees."

Hit a roadblock though after I followed the identical procedure as above and no errors were thrown in the process.

Snippet:

var margins = {top:100, bottom:300, left:100, right:100};

var height = 600;
var width = 900;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

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

var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");

  var data =
[ {name:"Company1", tree:  {
   "name": "Product offerings",
   "children": [

    {"name": "Equity line", "size": 2200,
  "children": [
    {"name": "Equity fund 1", "size": 800,  "type" : "equity"},
    {"name": "Equity fund 2", "size": 600,  "type" : "equity"},
    {"name": "Equity fund 3", "size": 300,  "type" : "equity"},
    {"name": "Equity fund 4", "size": 250,  "type" : "equity"},
    {"name": "Equity fund 5", "size": 250,  "type" : "equity"},
    {"name": "Equity fund 6", "size": 525,  "type" : "equity"},
   ]
  },

    {"name": "Bond fund line", "size": 1400,
   "children": [
     {"name": "Bond fund 1", "size": 800,  "type" : "bond"},
     {"name": "Bond fund 2", "size": 600,  "type" : "bond"},
     {"name": "Bond fund 3", "size": 300,  "type" : "bond"},
     {"name": "Bond fund 4", "size": 250,  "type" : "bond"},
   ]
 },

 {"name": "Balanced line", "size": 1400,
"children": [
  {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
  {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
  {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
  {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
  {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
  {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
  {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
  {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
  {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
  {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
  {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
  {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
]
  },

   ]
 }},
 {name:"Company2", tree:  {
        "name": "Product offerings",
        "children": [

         {"name": "Equity line", "size": 2200,
      "children": [
         {"name": "Equity fund 1", "size": 800,  "type" : "equity"},
         {"name": "Equity fund 2", "size": 600,  "type" : "equity"},
         {"name": "Equity fund 3", "size": 300,  "type" : "equity"},
         {"name": "Equity fund 4", "size": 250,  "type" : "equity"},
        {"name": "Equity fund 5", "size": 250,  "type" : "equity"},
        {"name": "Equity fund 6", "size": 525,  "type" : "equity"},
        ]
      },

         {"name": "Bond fund line", "size": 1400,
       "children": [
          {"name": "Bond fund 1", "size": 800,  "type" : "bond"},
          {"name": "Bond fund 2", "size": 600,  "type" : "bond"},
          {"name": "Bond fund 3", "size": 300,  "type" : "bond"},
          {"name": "Bond fund 4", "size": 250,  "type" : "bond"},
        ]
      },

      {"name": "Balanced line", "size": 1400,
     "children": [
       {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
       {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
       {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
       {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
       {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
       {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
       {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
       {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
       {"name": "Bond fund 1", "size": 800,  "type" : "balanced"},
       {"name": "Bond fund 2", "size": 600,  "type" : "balanced"},
       {"name": "Bond fund 3", "size": 300,  "type" : "balanced"},
       {"name": "Bond fund 4", "size": 250,  "type" : "balanced"},
     ]
   },

        ]
      }},

]


  var columns = 3;
  var spacing = 200;
  var vSpacing = 180;

  var regionG = graphGroup.selectAll('.region')
.data(data)
.enter()
.append('g')
.attr('class', 'region')
.attr('id', (d, i) => 'region' + i)
.attr('transform', (d, k) => {
  var horSpace = (k % columns) * spacing;
  var vertSpace = ~~((k / columns)) * vSpacing;
  return "translate(" + horSpace + "," + vertSpace + ")";
});


var colorMap = {
  'equity':"#003366",
  'bond':"#f6d18b",
  'balanced':"#95b3d7"
};

  //const root = d3.hierarchy(data);
  //const links = root.links();
  //const nodes = root.descendants();

  const simulation = d3.forceSimulation(d3.hierarchy(function(d) {return d.tree}).descendants())
  .force("link", d3.forceLink(d3.hierarchy(function(d) {return d.tree}).links()).id(d => d.id).distance(0).strength(1))
  .force("charge", d3.forceManyBody().strength(-50))
  .force("x", d3.forceX())
  .force("y", d3.forceY());

  const link = regionG.append("g")
  .attr("stroke", "#999")
  .attr("stroke-opacity", 0.6)
.selectAll("line")
.data(d3.hierarchy(function(d) {return d.tree}).links())
.join("line");

  const node = regionG.append("g")
  .attr("fill", "#fff")
  .attr("stroke", "#000")
  .attr("stroke-width", 1.5)
.selectAll("circle")
.data(d3.hierarchy(function(d) {return d.tree}).descendants())
.join("circle")
  .attr("fill", d => d.children ? null : colorMap[d.data.type])
  .attr("stroke", d => d.children ? null : "#fff")
  .attr("r", 3.5);

  simulation.on("tick", () => {
link
    .attr("x1", d => d.source.x)
    .attr("y1", d => d.source.y)
    .attr("x2", d => d.target.x)
    .attr("y2", d => d.target.y);

node
    .attr("cx", d => d.x)
    .attr("cy", d => d.y);
  });
<script src="https://d3js.org/d3.v5.min.js"></script>

As we can see, I'm using the same approach, constructing data to be an array of objects. One object entry is tree -- which contains the hierarchy data. (I limited the list to simply two for the sake of simplicity.

Question

What could be throwing the process off for force-directed trees, given the success we've had thus far with earlier, identical approaches?

Note If there is away to achieve the force tree matrix without the initial force animation that would be acceptable (actually preferable).



from Stackoverflow

Comments

Popular posts from this blog

With jQuery, how to automatically select the value of an input text that has been modified with the arrows? With jQuery, how to automatically select the value of an input text that has been modified with the arrows?

Cannot create an instance of a defined class in Javascript Cannot create an instance of a defined class in Javascript

Using Ts-Standard linting, JSDoc comment at beginning of file triggers "This rule requires the `strictNullChecks` compiler option" error Using Ts-Standard linting, JSDoc comment at beginning of file triggers "This rule requires the `strictNullChecks` compiler option" error