当我想显示多个网络可视化图时,使用d3.js可视化网络库会遇到一些问题。
由于我绘制了一个新图形,只有最后一个图形可以使用其力布局,因此我无法找出问题出在哪里。

这是jsfiddle:
https://jsfiddle.net/7mn0qy5b/2/

这是我的资料来源:

的HTML

<div id="graph1"></div>
<div id="graph2"></div>


的CSS

#graph1, #graph2 {
    width: 250px;
    height: 250px;
    border: 1px solid #000;
}
.link {
    stroke: #626262;
    strokeWidth: 2px;
}


JS

var graph = {};

function myGraph(el) {
    this.link = {};
    this.node = {};
    this.container = el;

    // Add and remove elements on the graph object
    this.addNode = function (id) {
        nodes.push({"id":id});
        update();
    };

    this.removeNode = function (id) {
        var i = 0;
        var n = findNode(id);
        while (i < links.length) {
            if ((links[i]['source'] == n)||(links[i]['target'] == n))
            {
                links.splice(i,1);
            }
            else i++;
        }
        nodes.splice(findNodeIndex(id),1);
        update();
    };

    this.removeLink = function (source,target){
        for(var i=0;i<links.length;i++)
        {
            if(links[i].source.id == source && links[i].target.id == target)
            {
                links.splice(i,1);
                break;
            }
        }
        update();
    };

    this.removeallLinks = function(){
        links.splice(0,links.length);
        update();
    };

    this.removeAllNodes = function(){
        nodes.splice(0,links.length);
        update();
    };

    this.addLink = function (source, target, value) {
        links.push({"source":findNode(source),"target":findNode(target),"value":value});
        update();
    };

    var findNode = function(id) {
        for (var i in nodes) {
            if (nodes[i]["id"] === id) return nodes[i];
        };
        return null;
    };

    var findNodeIndex = function(id) {
        for (var i=0;i<nodes.length;i++) {
            if (nodes[i].id==id){
                return i;
            }
        };
        return null;
    };

    // set up the D3 visualisation in the specified element
    var w = 250,
        h = 250;

    this.vis = d3.select(el)
        .append("svg:svg")
        .attr("width", w)
        .attr("height", h)
        .attr("id","svg")
        .attr("pointer-events", "all")
        .attr("viewBox","0 0 "+w+" "+h)
        .attr("perserveAspectRatio","xMinYMid")
        .append('svg:g');

    this.force = d3.layout.force();

    var nodes = this.force.nodes(),
        links = this.force.links();

    self = this;
    var update = function () {
        self.link = self.vis.selectAll("line")
                .data(links, function(d) {
                    return d.source.id + "-" + d.target.id;
                });

        self.link.enter().append("line")
            .attr("id",function(d){return d.source.id + "-" + d.target.id;})
            .attr("class","link")
            .append("title")
            .text(function(d){
                return d.value;
            });
        self.link.exit().remove();

        self.node = self.vis.selectAll("g.node")
            .data(nodes, function(d) {
                return d.id;
            });

        var nodeEnter = self.node.enter().append("g")
            .attr("class", "node")
            .call(self.force.drag);

        nodeEnter.append("svg:circle")
            .attr("r", 16)
            .attr("id",function(d) { return "svgNode_"+self.container+"_"+d.id;})
            .attr("class","nodeStrokeClass");

        nodeEnter.append("svg:text")
            .attr("class","textClass")
            .text( function(d){return d.id;}) ;

        self.node.exit().remove();
        self.force.on("tick", function() {
            //console.log(self.container);
            /*self.node.attr("cx", function(d) { return d.x = Math.max(d.radius, Math.min(svg[spaceId].attr('width') - d.radius, d.x)); })
                    .attr("cy", function(d) { return d.y = Math.max(d.radius, Math.min(svg[spaceId].attr('height') - d.radius, d.y)); })
                    .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; })
            */self.node.attr("transform", function(d) { return "translate("+d.x+","+d.y+")"; });

            self.link.attr("x1", function(d) { return d.source.x; })
                .attr("y1", function(d) { return d.source.y; })
                .attr("x2", function(d) { return d.target.x; })
                .attr("y2", function(d) { return d.target.y; });
        });

        // Restart the force layout.
        self.force
            .gravity(.06)
            .distance(100)
            .charge(-300)
            .size([w, h])
            .start();
    };
    // Make it all go
    update();
}
graph["#graph1"] = new myGraph("#graph1");
graph["#graph1"].addNode('A');
graph["#graph1"].addNode('B');
graph["#graph1"].addNode('C');
graph["#graph1"].addLink('A','B','10');
graph["#graph1"].addLink('A','C','8');
graph["#graph1"].addLink('B','C','15');
setTimeout(function() {
    graph["#graph2"] = new myGraph("#graph2");
    graph["#graph2"].addNode('D');
    graph["#graph2"].addNode('E');
    graph["#graph2"].addNode('F');
    graph["#graph2"].addLink('D','E','10');
    graph["#graph2"].addLink('D','F','8');
    graph["#graph2"].addLink('E','F','15');
}, 2000);


谢谢您的帮助,我很生气。

最佳答案

这条线

self = this;


缺少var关键字。没有它,会将self分配给全局window范围,而不是本地myGraph范围。在myGraph构造函数的第二次运行中,第一个myGraphwindow.self被新值覆盖。因此,两个myGraph对象中的事件都引用第二个self,这会导致损坏。

您可能要启用strict mode,以便编译器将对此类可追溯性很差的错误发出警告。

09-13 02:13