加载图像直到外部json数据加载可折叠树-d3.js

时间:2015-04-22 04:57:05

标签: json d3.js preloading collapsable

我正在使用d3.js的可折叠树示例。我成功地在节点点击上加载外部json数据。现在我想显示预加载图像,直到从我点击的相应节点附近的服务器检索到json数据。

我在所有节点中都附加了一个div标签,并且在所有附加的div标签中都有一个img src用于gif。我无法实现解决方案。

在我的代码示例下面:

<!DOCTYPE html>
<html>
<title>Gateways - CollapsibleTree</title>
<meta charset="utf-8">
<style>
    .node {
        cursor: pointer;
    }

    .node circle {
        fill: #fff;
        stroke: steelblue;
        stroke-width: 1.5px;
    }

    .node text {
        font: 12px sans-serif;
    }

    .link {
        fill: none;
        stroke: #ccc;
        stroke-width: 1.5px;
    }

    a:hover {
        text-decoration:underline 
    }
</style>
<body>
    <script src="d3.min.js"></script>
    <script src="jquery.min.js"></script>
    <script>
        var margin = {
                top: 20,
                right: 120,
                bottom: 20,
                left: 120
            },
            width = 960 - margin.right - margin.left,
            height = 800 - margin.top - margin.bottom;

        var i = 0,
            duration = 750,
            root;

        var tree = d3.layout.tree()
            .size([height, width]);

        var diagonal = d3.svg.diagonal()
            .projection(function(d) {
                return [d.y, d.x];
            });

        var svg = d3.select("body").append("svg")
            .attr("id", "treeChart")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

        d3.json("http://localhost:8080/demo/gateways.json", function(error, flare) {
            root = flare;
            root.x0 = height / 2;
            root.y0 = 0;

            function collapse(d) {
                if (d.children) {
                    d._children = d.children;
                    d._children.forEach(collapse);
                    d.children = null;
                }
            }

            root.children.forEach(collapse);
            update(root);
        });

        d3.select(self.frameElement).style("height", "800px");

        function update(source) {

            $('div#loading1').hide();
            // Compute the new tree layout.
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);

            // Normalize for fixed-depth.
            nodes.forEach(function(d) {
                d.y = d.depth * 180;
            });

            // Update the nodes…
            var node = svg.selectAll("g.node")
                .data(nodes, function(d) {
                    return d.id || (d.id = ++i);
                });

            // Enter any new nodes at the parent's previous position.
            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("transform", function(d) {
                    return "translate(" + source.y0 + "," + source.x0 + ")";
                })
                .on("click", click);


            nodeEnter.append("circle")
                .attr("r", 15)
                .style("fill", function(d) {
                    return d._children ? "lightsteelblue" : "#fff";
                });

            nodeEnter.append("svg:image")
                .attr("class", "circle")
                .attr("xlink:href", "logo.png")
                .attr("x", "-8px")
                .attr("y", "-8px")
                .attr("width", "16px")
                .attr("height", "16px");

            var z = 0,
                z2 = 0;

            var spinner = nodeEnter.append("div")
                .attr("top", function(d) {
                    return "15%";
                })
                .attr("left", function(d) {
                    return "50%";
                })
                .attr("width", "16px")
                .attr("height", "16px")
                .attr("position", "absolute")
                .attr("id", function(d) {
                    return "loading" + z++;
                });

            var spinimage = spinner.append("img")
                .attr("src", "loading.GIF")
                .attr("alt", "Processing");

            nodeEnter.append("a")
                .attr("xlink:href", function(d) {
                    return d.url;
                })
                .append("text")
                .attr("x", function(d) {
                    return d.children || d._children ? -10 : 10;
                })
                .attr("dy", ".35em")
                .attr("text-anchor", function(d) {
                    return d.children || d._children ? "end" : "start";
                })
                .text(function(d) {
                    return d.name;
                })
                .style("fill-opacity", 1e-6);

            // Transition nodes to their new position.
            var nodeUpdate = node.transition()
                .duration(duration)
                .attr("transform", function(d) {
                    return "translate(" + d.y + "," + d.x + ")";
                });

            nodeUpdate.select("circle")
                .attr("r", 4.5)
                .style("fill", function(d) {
                    return d._children || d.children ? "lightsteelblue" : "#fff";
                });

            nodeUpdate.select("text")
                .style("fill-opacity", 1);

            // Transition exiting nodes to the parent's new position.
            var nodeExit = node.exit().transition()
                .duration(duration)
                .attr("transform", function(d) {
                    return "translate(" + source.y + "," + source.x + ")";
                })
                .remove();

            nodeExit.select("circle")
                .attr("r", 1e-6);

            nodeExit.select("text")
                .style("fill-opacity", 1e-6);

            // Update the links…
            var link = svg.selectAll("path.link")
                .data(links, function(d) {
                    return d.target.id;
                });

            // Enter any new links at the parent's previous position.
            link.enter().insert("path", "g")
                .attr("class", "link")
                .attr("d", function(d) {
                    var o = {
                        x: source.x0,
                        y: source.y0
                    };
                    return diagonal({
                        source: o,
                        target: o
                    });
                });

            // Transition links to their new position.
            link.transition()
                .duration(duration)
                .attr("d", diagonal);

            // Transition exiting nodes to the parent's new position.
            link.exit().transition()
                .duration(duration)
                .attr("d", function(d) {
                    var o = {
                        x: source.x,
                        y: source.y
                    };
                    return diagonal({
                        source: o,
                        target: o
                    });
                })
                .remove();

            // Stash the old positions for transition.
            nodes.forEach(function(d) {
                d.x0 = d.x;
                d.y0 = d.y;
            });
        }

        // Toggle children on click.
        function click(d) {
            $('div#loading1').show();

            // made a time out to check the preload
            setTimeout(function() {
                $.getJSON("http://localhost:8080/demo/gateways.json", function(addJson) {

                    // on node click get whole json data and parse the data and apppend children of the 
                    //corresponding parent
                    var childObj = getObjects(addJson, 'name', d.name);

                    var len = (childObj[0].children).length;

                    function collapse2(k) {
                        if (k.children) {
                            k._children = k.children;
                            k._children.forEach(collapse2);
                            k.children = null;
                        }
                    }

                    childObj[0].children.forEach(collapse2);

                    var newnodes = tree.nodes(childObj[0].children).reverse();


                    if (d.children) {
                        d._children = newnodes[0];
                        d.children = null;
                    } else {
                        d.children = newnodes[0];
                        d._children = null;
                    }

                    update(d);

                });

                //do something special

            }, 3000);
        }

        function getObjects(obj, key, val) {
            var objects = [];
            for (var i in obj) {
                if (!obj.hasOwnProperty(i)) continue;
                if (typeof obj[i] == 'object') {
                    objects = objects.concat(getObjects(obj[i], key, val));
                } else if (i == key && obj[key] == val) {
                    objects.push(obj);
                }
            }
            return objects;
        }
    </script>
</body>
</html>

2 个答案:

答案 0 :(得分:1)

您必须使用SVG foreignObject标记将非SVG内容添加到svg中。 这是一些示例代码

svg.append("foreignObject")
     .attr("width", 100)
     .attr("height", 100)
     .append("xhtml:div")
     .style("color", "red")
     .html("Object in SVG");

here

了解有关异物的更多信息

答案 1 :(得分:0)

 var spinner=nodeEnter.append("foreignObject")
     .attr("width", 100)
     .attr("height", 100)
     .attr("id",function(d){return "loading"+d.id;})
     .attr("display","none")
     .append("xhtml:div")
     .html("<img src=\"loading.GIF\"/>");