Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bundle layout using d3.js and given json file structure

I have a json file with elements like this:

[{
    "name": "Manuel Jose",
    "ttags": ["vivant", "designer", "artista", "empreendedor"]
}]

I'm trying to get the node and the edges using this structure to complete a graph like:

enter image description here

(diagram is taken from d3.js documentation)

Both name and ttags in my json file refer to nodes, ttags are actually links between the node and another nodes.

But, I cannot understand how to create this diagram using this library d3 and above json file.

    d3.json("/data/tedxufrj.json", function(classes) {
      var nodes = cluster.nodes(package.root(classes)),
          links = package.imports(nodes);

      vis.selectAll("path.link")
          .data(splines = bundle(links))
        .enter().append("path")
          .attr("class", "link")
          .attr("d", line);

      vis.selectAll("g.node")
          .data(nodes.filter(function(n) { return !n.children; }))
        .enter().append("g")
          .attr("class", "node")
          .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
        .append("text")
          .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
          .attr("dy", ".31em")
          .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
          .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
          .text(function(d) { return d.key; });
    });

And this is file package.js:

        (function() {
              packages = {

                // Lazily construct the package hierarchy from class names.
                root: function(classes) {
                  var map = {};

                  function find(name, data) {
                    var node = map[name], i;  
                    if (!node) {
                      node = map[name] = data || {name: name, children: []};
                      if (name.length) {
                        node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
                        node.parent.children.push(node);
                        node.key = name.substring(i + 1);
                      }
                    }
                    return node;
                  }

                  classes.forEach(function(d) {
                    find(d.name, d);
                  });

                  return map[""];
                },

                // Return a list of imports for the given array of nodes.
                imports: function(nodes) {
                  var map = {},
                      imports = [];

                  // Compute a map from name to node.
                  nodes.forEach(function(d) {
                    map[d.name] = d;
                  });

                  // For each import, construct a link from the source to target node.
                  nodes.forEach(function(d) {
                    if (d.imports) d.imports.forEach(function(i) {
                      imports.push({source: map[d.name], target: map[i]});
                    });
                  });

                  return imports;
                }

              };
            })();
like image 889
cleliodpaula Avatar asked May 28 '12 15:05

cleliodpaula


2 Answers

Take a look at this: http://testprogramming.googlecode.com/svn-history/r391/trunk/javascript/svg/d3/test/flare-imports.json

This example shows the data structure required by the bundle layout. Orginally the data structure is hierarchical like the visualization in this graph: http://mbostock.github.com/d3/ex/cluster.html

What I would do in your place is to add fictional root to make a hierarchy, like this:

[
{"name": "root.Manuel_Jose", "imports": ["root.vivant", "root.designer", "root.artista", "root.empreendedor"]},
{"name": "root.vivant", "imports": []},
{"name": "root.designer", "imports": []},
{"name": "root.artista", "imports": []},
{"name": "root.empreendedor", "imports": []}
]
like image 198
wceo Avatar answered Sep 30 '22 01:09

wceo


@wceo, the root is not actually required. It is optional and is used the create a visual separation.

@VividD, what you need to do is to create nodes for "vivant", "designer", "artista", "empreendedor", linking back to themselves.

I know it's weird but that is what's required.

so your json should look like this:

[
  {"name": "Manuel Jose", "ttags": ["vivant", "designer", "artista", "empreendedor"]},
  {"name": "vivant", "ttags": ["vivant"]},
  {"name": "designer", "ttags": ["designer"]},
  {"name": "artista", "ttags": ["artista"]},
  {"name": "empreendedor", "ttags": ["empreendedor"]}
]
like image 42
Zaakiy Siddiqui Avatar answered Sep 30 '22 01:09

Zaakiy Siddiqui