Frage

So I have been using d3's zoom circle(http://mbostock.github.com/d3/talk/20111116/pack-hierarchy.html):

enter image description here

The data is passed to the d3 script as a json array with a few different levels of arrays and objects.

object = {
    class: "show",
    name: "Game of Thrones",
    children : [
        {
            class: "family",
            name: "Starks",
            children: [
                {
                    class: "members",
                    name: "Rob"
                },
                {
                    class: "members",
                    name: "Jon Snow"
                }
            ],
        },
        {
            class: "family",
            name: "Lannisters"
            children: [
                {
                    class: "members",
                    name: "Ser Jaime"
                },
                {
                    class: "members",
                    name: "Cersei"
                }
            ],
        }            
    ],
}

I had no problem displaying the circles. I am now trying to create a navigation display on the side that maps out the hierarchy of the data. Ideally all I want is something like this:

<ul>
  <li> Game of Thrones
    <ul>
      <li> Starks
        <ul>
          <li> Rob </li>
          <li> Jon Snow </li>
        </ul>
      </li>
      <li> Lannisters
        <ul> 
          <li> Ser Jaime </li>
          <li> Cersei </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

It's a basic list structure. The only thing I've been able to do is access 1 level down in the data. I used 'divs' to just try to the the structure down first.

var sentimentData = data.children;

var navBox = d3.select("body").append("body:div");

navBox
    .attr("class", "navBox");

var sentimentNav = navBox.selectAll('div')
    .data(sentimentData)
    .enter()
    .append('div')
    .text(function(d){ return d.name; });

I haven't been able to proceed anymore levels past that. I was thinking a recursive way would probably be the best way. I tried this function below but it just appended divs to the top div and not the parent node.

function buildNav(d) {
 if (d.children) {
   children = d.children;
   d3.select('body').append('div')
      .data(children)
      .enter()
      .append('div')
      .attr("class", function(d) {return d.name; });
   children.forEach(buildNav); 
   d._children = d.children;  
   d.children = null;
 }
}

buildNav(data);

Any suggestions to how to append the children to their parents, or how to access data multiple levels down would be greatly appreciated.

War es hilfreich?

Lösung

Nick! Here is the complete code of an example that creates lists that you described in the question: (there might be a nicer code to do the same thing, but this code works and produces 100% what you said) (if course, this is only a starting point, you will naturally develop further real navigation)

index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Navigation</title>
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script src="script.js"></script>
</head>
<body onload="load()">
    <h2>Navigation</h2>
    <h4>(using D3.js-generated navigation items)</h4>
</body>
</html>

script.js:

function load(){
    object = {
        class: "show", name: "Game of Thrones",
        children : [
            {
                class: "family", name: "Starks",
                children: [
                    { class: "members", name: "Rob" },
                    { class: "members", name: "Jon Snow" }
                ],
            },
            {
                class: "family", name: "Lannisters",
                children: [
                    { class: "members", name: "Ser Jaime"},
                    { class: "members", name: "Cersei" }
                ],
            }            
        ],
    };

    buildNav(null, object);

    function buildNav(parent_ul, node){
        var current_ul, current_li;
        if(parent_ul == null)
            parent_ul = d3.select("body").append("ul");
        current_li = parent_ul.append("li").text(node.name);
        if (node.children) {
            current_ul = current_li.append("ul");  
            for (var i=0; i<node.children.length; i++) {
                buildNav(current_ul, node.children[i]); 
            };
        };
    };
};

This produces following page:

enter image description here

Hope this would help you.

Let me know if you have additional questions.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top