如何使用d3.js更新数据表单文件json(zoomable circle pack)

时间:2014-02-06 10:55:14

标签: javascript json d3.js updating circle-pack

我正在对存储在json文件中的传入数据进行实时可视化。我使用D3进行可视化。这是我使用的图表:http://mbostock.github.io/d3/talk/20111116/pack-hierarchy.html

enter image description here

这是所有代码页:

<body onload="visualize()">

<h2>
    <input type="button" value="Get new data"
        onclick='ajaxSyncRequest("get-current-time")' /> <br /> <br />
    Message from server :: <span id="message"></span>
</h2>

<script type="text/javascript">

function ajaxSyncRequest(reqURL) {
    //Creating a new XMLHttpRequest object
    var xmlhttp;
    if (window.XMLHttpRequest) {
        xmlhttp = new XMLHttpRequest(); //for IE7+, Firefox, Chrome, Opera, Safari
    } else {
        xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); //for IE6, IE5
    }
    //Create a asynchronous GET request
    xmlhttp.open("GET", reqURL, false);
    xmlhttp.send(null);

    //Execution blocked till server send the response
    if (xmlhttp.readyState == 4) {
        if (xmlhttp.status == 200) {
            document.getElementById("message").innerHTML = xmlhttp.responseText;
            //alert(xmlhttp.responseText);
            update();

        } else {
            alert('Something is wrong !!');
        }
    }
}
</script>



<script type="text/javascript" src="d3/d3.js"></script>
<script type="text/javascript" src="d3/d3.layout.js"></script>
<script type="text/javascript">
    function visualize() {

        var w = 1280, h = 800, r = 720, 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
                                + ")");

        d3.json("flare.json", function(data) {
            node = root = data;

            var nodes = pack.nodes(root);

            vis.selectAll("circle").data(nodes).enter()
                    .append("svg:circle").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("click", function(d) {
                        return zoom(node == d ? root : d);
                    });

            vis.selectAll("text").data(nodes).enter().append("svg:text")
                    .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;
                    });

            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();
        }
    }
</script>

<script type="text/javascript">
    function update() {

        var w = 1280, h = 800, r = 720, 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("svg").attr("width", w).attr("height", h)
                .append("svg:g").attr(
                        "transform",
                        "translate(" + (w - r) / 2 + "," + (h - r) / 2
                                + ")");

        d3.json("flare.json", function(data) {

            node = root = data;

            var nodes = pack.nodes(root);
            // DATA JOIN
            // Join new data with old elements, if any.
            var newG = vis.selectAll("circle").data(nodes);

            // UPDATE
            // Update old elements as needed.
            newG.attr("class", "update").transition();

            // ENTER
            // Create new elements as needed.
            newG.enter().append("svg:circle").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("click", function(d) {
                return zoom(node == d ? root : d);
            });

            newG.enter().append("svg:text")
            .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;
            });

            // EXIT
            // Remove old elements as needed.
            newG.exit().attr("class", "exit").transition().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();
        }
    }
</script>

我想从我从服务器获取的新文件中动态更新图表。但是通过这个功能,它绘制了一个旧图表。我尝试了不同的解决方案来更新图表但没有一个工作。 我如何修改代码以获得动态更新?

1 个答案:

答案 0 :(得分:4)

进行此项工作需要进行以下更改。首先,您需要在g函数中选择现有的SVG元素(及其后代vis)作为update

var vis = d3.select("svg > g");

然后,您需要分别计算和处理圆形和文本的输入,更新和退出选择:

var newG = vis.selectAll("circle").data(nodes);

newG.enter().append("svg:circle");
newG.exit().remove();
newG.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("click", function(d) {
    return zoom(node == d ? root : d);
  });

var texts = vis.selectAll("text").data(nodes);

texts.enter().append("svg:text");
texts.exit().remove();
texts.append("svg:text")
  .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;
  }); 

你也可以合并你的功能,因为它们几乎都做同样的事情并且有很多冗余代码。但上述内容应足以使其发挥作用。