简体   繁体   中英

D3 Treemap zoomable

i'm trying to make this d3 treemap zoomable but seem to be struggling with it. I keep getting a " treemap.nodes is not a function" error. I tried to follow the Mike Bostock example here, https://bost.ocks.org/mike/treemap/

Here's my code:

 var data = 
    {
        "name" : "Max",
        "value": 100,
        "children": 
        [
            {
             "name": "A",
             "value": 75,
             "children": [
                 { "name": "Alpha", "result": 20},
                 { "name": "Aplha 2", "result": 40},
                 { "name": "Aplha 3", "result": 35}
             ]
            },
            {
             "name": "B",
             "value": 75,
             "children": [
                 {"name": "Bravo", "result": 80},
                 {"name": "Bravo 2", "result": 20},
                 {"name": "Bravo 3", "result": 33}
             ]
            },
            {
             "name": "C",
             "value": 75,
             "children": [
                 {"name": "Charle", "result": 84},
                 {"name": "Charle 2", "result": 43},
                 {"name": "Charle 3", "result": 24}
              ]
            }
        ]
    }
    var margin = {top: 20, right: 0, bottom: 0, left: 0},
        width = 960,
        height = 500 - margin.top - margin.bottom,
        formatNumber = d3.format(",d"),
        transitioning;

    var x = d3.scale.linear()
        .domain([0, width])
        .range([0, width]);

    var y = d3.scale.linear()
        .domain([0, height])
        .range([0, height]);

    var color = d3.scale.category10();
    var svg = d3.select("#chart").append("svg")
        .attr("width", 1000)
        .attr("height", 1000);

    var treemap =  d3.layout.treemap()
        .size([1000, 1000])
        .children(function(d, depth) { return depth ? null : d.children; })
        .sort(function(a, b) {return a.value - b.value; })
        .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
        .round(false)
        .nodes(data);

    var cells = svg.selectAll(".cell")
        .data(treemap)
        .enter()
        .append("g")
        .attr("class", "cell")

    cells.append("rect")
        .attr("x", function(d){ return d.x})
        .attr("y", function(d){ return d.y})
        .attr("width", function(d){ return d.dx})
        .attr("height", function(d){ return d.dy})
        .attr("stroke", "#fff")
        .attr("fill", function(d){ return d.children ? null : color(d.parent.name);})

    cells.append("text")
        .attr("x", function (d) { return d.x + d.dx /2})
        .attr("y", function (d) { return d.y + d.dy /2})
        .text(function(d) { return d.children ? null : d.name + d.value;})

    var grandparent = svg.append("g")
        .attr("class", "grandparent");

    grandparent.append("rect")
        .attr("y", -margin.top)
        .attr("width", width)
        .attr("height", margin.top);

    grandparent.append("text")
        .attr("x", 6)
        .attr("y", 6 - margin.top)
        .attr("dy", ".75em"); 

   var root = sample_data;
   initialize(root);
    accumulate(root);
    layout(root);
    display(root);

    function initialize(root) {
        root.x = root.y = 0;
        root.dx = width;
        root.dy = height;
        root.depth = 0;
    }

    function accumulate(d) {
        return d.children
            ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0)
            : d.value;
    }

    function layout(d) {
        if (d.children) {
          treemap.nodes({children: d.children});
          d.children.forEach(function(c) {
            c.x = d.x + c.x * d.dx;
            c.y = d.y + c.y * d.dy;
            c.dx *= d.dx;
            c.dy *= d.dy;
            c.parent = d;
            layout(c);
          });
        }
      }

    function display(d) {
        grandparent
           .datum(d.parent)
           .on("click", transition)
          .select("text")
            .text(name(d));

    var g1 = svg.insert("g", ".grandparent")
        .datum(d)
        .attr("class", "depth");

    var g = g1.selectAll("g")
        .data(d.children)
      .enter().append("g");

    g.filter(function(d) { return d.children; })
        .classed("children", true)
        .on("click", transition);

    g.selectAll(".child")
        .data(function(d) { return d.children || [d]; })
      .enter().append("rect")
        .attr("class", "child")
        .call(rect);

    g.append("rect")
        .attr("class", "parent")
        .call(rect)
      .append("title")
        .text(function(d) { return formatNumber(d.value); });

    g.append("text")
        .attr("dy", ".75em")
        .text(function(d) { return d.name; })
        .call(text);

    function transition(d) {
      if (transitioning || !d) return;
      transitioning = true;

        var g2 = display(d),
            t1 = g1.transition().duration(750),
            t2 = g2.transition().duration(750);

        x.domain([d.x, d.x + d.dx]);
        y.domain([d.y, d.y + d.dy]);

        svg.style("shape-rendering", null);

        svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });

        g2.selectAll("text").style("fill-opacity", 0);

        t1.selectAll("text").call(text).style("fill-opacity", 0);
        t2.selectAll("text").call(text).style("fill-opacity", 1);
        t1.selectAll("rect").call(rect);
        t2.selectAll("rect").call(rect);

        t1.remove().each("end", function() {
        svg.style("shape-rendering", "crispEdges");
        transitioning = false;
        });
    }

    return g;
  }

  function text(text) {
    text.attr("x", function(d) { return x(d.x) + 6; })
        .attr("y", function(d) { return y(d.y) + 6; });
  }

  function rect(rect) {
    rect.attr("x", function(d) { return x(d.x); })
        .attr("y", function(d) { return y(d.y); })
        .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
        .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); });
  }

  function size(d) {
    return d.value;
  }

  function name(d) {
    return d.parent
        ? name(d.parent) + "." + d.name
        : d.name;
  }

Any help would be appreciated.

The .nodes() function does not return the treemap on which it is called (like many other functions), but the array of nodes instead, so you cannot have treemap= d3.layout.treemap(). [...] .nodes(data) treemap= d3.layout.treemap(). [...] .nodes(data) . Use the following instead:

 var treemap =  d3.layout.treemap()
    .size([1000, 1000])
    .children(function(d, depth) { return depth ? null : d.children; })
    .sort(function(a, b) {return a.value - b.value; })
    .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
    .round(false);
 var nodes = treemap.nodes(data);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM