d3从GUI更新数据(圆组布局)

时间:2014-06-18 08:54:00

标签: javascript d3.js circle-pack

据我看到update(),输入(),exit()用于从数据更新视图。还有另一种方法,从GUI更新数据吗?

e.g。点击B-circle,点击删除 - >将从GUI中删除,但仍然存在于数据中..通过单击刷新,它会再次出现:

http://jsfiddle.net/stefanf/6Qm2z/33/

'var nodesToRemove = pack.nodes(data);
    var sel = vis.selectAll("circle").data(nodesToRemove, function(d){
      return d.id;
    });
    sel.remove();'

P.S。我现在可以通过首先使用javascript更新数据来实现,但我的问题是,是否有适当的d3方式..

1 个答案:

答案 0 :(得分:1)

我做过这个工作小提琴http://jsfiddle.net/6Qm2z/36/

var dataGlobal =  {  
"name": "Area",
    "id": 1,
    "size": 1,
  "children": [
    {
      "name": "F",
      "id": 2,
    "size": 1,
      "children": [
        {     "name": "C",
         "id": "3",
              "size": 1
         },
            {
              "name": "D",
                 "id": 4,
    "size": 1,
               "children": [
                {     "name": "A",
                 "id": 5,

                  "size": 0.5
                 },
                {     "name": "B",
                  "id": 6,
                  "size": 1
                 }
                   ]
            },
           {
              "name": "H",
               "id": 7,
              "size": 1
            }
          ]
          }
      ]
};

var w = 680,
    h = 600,
    r = 420,
    x = d3.scale.linear().range([0, r]),
    y = d3.scale.linear().range([0, r]),
    node,
    root;

var pack = d3.layout.pack()
    .size([r, r])
    .value(function(d) { return d.size; })

var vis = d3.select("body").insert("svg:svg", "h2")
    .attr("width", w)
    .attr("height", h)
  .append("svg:g")
    .attr("transform", "translate(" + (w - r) / 2 + "," + (h - r) / 2 + ")");
node = root = dataGlobal;

var refreshGraph = function(newArray) {
    var nodes;
    if(newArray != null){
       nodes=newArray;
    }
    else{
        nodes = pack.nodes(root);    
    }

          var sel = vis.selectAll("circle")
              .data(nodes, function(d) { return d.id; });
            sel
              .enter().append("svg:circle");
            sel
              .attr("class", function(d) { return d.children ? "parent" : "child"; })
              .attr("cx", function(d) { return d.x; })
              .attr("cy", function(d) { return d.y; })
              .attr("r", function(d) { return d.r; })
              .on("dblclick", function(d) { return zoom(node == d ? root : d); })
              .on("click", function () {
                    d3.select(".selected").classed("selected", false);
                    d3.select(this).classed("selected", true);
                });
            sel.exit().remove();
          sel = vis.selectAll("text")
              .data(nodes,  function(d) { return d.name; });
            sel
            .enter().append("svg:text");
            sel
              .attr("class", function(d) { return d.children ? "parent" : "child"; })
              .attr("x", function(d) { return d.x; })
              .attr("y", function(d) { return d.y; })
              .attr("dy", ".35em")
              .attr("text-anchor", "middle")
              .style("opacity", function(d) { return d.r > 20 ? 1 : 0; })
              .text(function(d) { return d.name; });
            sel.exit().remove();

          d3.select(window).on("click", function() { zoom(root); });
}

function zoom(d, i) {
  var k = r / d.r / 2;
  x.domain([d.x - d.r, d.x + d.r]);
  y.domain([d.y - d.r, d.y + d.r]);
  var t = vis.transition()
      .duration(d3.event.altKey ? 7500 : 750);
  t.selectAll("circle")
      .attr("cx", function(d) { return x(d.x); })
      .attr("cy", function(d) { return y(d.y); })
      .attr("r", function(d) { return k * d.r; });
  t.selectAll("text")
      .attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y(d.y); })
      .style("opacity", function(d) { return k * d.r > 20 ? 1 : 0; });
  node = d;
  d3.event.stopPropagation();
}

d3.select('#refreshBtn').on("click", function(d) {         
    updatedRefresh(dataGlobal);
});

d3.select('#addBtn').on("click", function(d) {         
    obj = {
              "name": document.getElementById('textBtn').value,
               "id": document.getElementById('idBtn').value,
              "size": 1
     }
     d3.select(".selected").datum().children.push(obj)
     refreshGraph()
});

d3.select("#deleteBtn").on("click", function() {
    d3.select(".selected").each(function(data){
        var nodesToRemove = pack.nodes(data);

        var sel = vis.selectAll("circle").data(nodesToRemove, function(d){
          return d.id;
        });
        sel.remove();
        vis.selectAll("text").data(nodesToRemove, function(d){
          return d.name;
        })
        .remove();

        dataGlobal.children = prune(dataGlobal.children, data.id);
    });

});

refreshGraph();

function prune(array, label) {
    for (var i = 0; i < array.length; ++i) {
        var obj = array[i];
        if (obj.id === label) {
            // splice out 1 element starting at position i
            array.splice(i, 1);
            return array;
        }
        if (obj.children) {
            if (prune(obj.children, label)) {
                if (obj.children.length === 0) {
                    // delete children property when empty
                    delete obj.children;

                    // or, to delete this parent altogether
                    // as a result of it having no more children
                    // do this instead
                    array.splice(i, 1);
                }
                return array;
            }
        }
    }
}


function updatedRefresh(newArray) {
   debugger;
    var nodes;
    if(newArray != null){
       nodes=pack.nodes(newArray);
    }
    else{
        nodes = pack.nodes(root);    
    }

          var sel = vis.selectAll("circle")
              .data(nodes, function(d) { return d.id; });
            sel
              .enter().append("svg:circle");
            sel
              .attr("class", function(d) { return d.children ? "parent" : "child"; })
              .attr("cx", function(d) { return d.x; })
              .attr("cy", function(d) { return d.y; })
              .attr("r", function(d) { return d.r; })
              .on("dblclick", function(d) { return zoom(node == d ? root : d); })
              .on("click", function () {
                    d3.select(".selected").classed("selected", false);
                    d3.select(this).classed("selected", true);
                });
            sel.exit().remove();
          sel = vis.selectAll("text")
              .data(nodes,  function(d) { return d.name; });
            sel
            .enter().append("svg:text");
            sel
              .attr("class", function(d) { return d.children ? "parent" : "child"; })
              .attr("x", function(d) { return d.x; })
              .attr("y", function(d) { return d.y; })
              .attr("dy", ".35em")
              .attr("text-anchor", "middle")
              .style("opacity", function(d) { return d.r > 20 ? 1 : 0; })
              .text(function(d) { return d.name; });
            sel.exit().remove();

          d3.select(window).on("click", function() { zoom(root); });
}

每次删除一项时,我都会使用dataGlobal函数更新prune数组。

查看要使用数组输入更新的updatedRefresh函数