单页中多个svg中的多个强制布局无法正常工作

时间:2016-04-06 06:27:12

标签: javascript d3.js svg

我想在两个不同的SVG中在单个页面中实现两个强制布局。我为不同的功能创建了不同的对象。

//object for handling 
var forceGraph = function(){


var force = d3.layout.force();

var width,height,vis;
var nodes = force.nodes();
var links = force.links();
this.disNodes = nodes;
this.disLinks = links;
var removedNodes = [];
var removedLinks = [];
var newNodes=[],newLinks=[];

this.setWidth = function(w){
    width = w;
}
this.setHeight = function(h){
    height = h;
}
this.setCanvas = function(c){
    vis = c;
}
//adds new node to force.nodes of not existing in force.nodes
this.addNode = function(id){
    if(!isNodeExisting(id)){
        nodes.push({'id':id,'type':'circle'});
        this.update();
    }
}
//adds new square node to force.nodes
this.addSquareNode = function(id){
    if(!isNodeExisting(id)){
        nodes.push({'id':id,'type':'rect'});
        this.update();
    }
}

//remove extra nodes from force.nodes
this.removeNodes = function(switches,hosts){
    var obj = this;
    for(i=nodes.length-1;i>-1;i--){
            if(switches.indexOf(nodes[i].id)==-1 && hosts.indexOf(nodes[i].id)==-1){
                removedNodes.push(nodes[i]);
                nodes.splice(i,1);
                obj.update();
            }
        }
}
//removes extra links from force.links
this.removeLinks = function(){
    var obj = this;
    $.each(removedNodes,function(i,val){
        for(i=links.length-1;i>-1;i--){
            if(links[i].source.id==val.id || links[i].target.id==val.id){
                var temp = links.splice(i,1);
                removedLinks.push(temp[0]);
                obj.update();
            }
        }
    });
    removedNodes.splice(0,removedNodes.length);
}
//determines if node is existing in force.nodes
var isNodeExisting = function(id){
    for (var i in nodes) {
        if (nodes[i]["id"] === id) return true;
    }
    return false;
}
//determines if links is existing force.links
var isLinkExisting = function(linkId){
    for (var i in links) {
        if (links[i].linkId === linkId) return true;
    }
}

//adds a link to force.links if link is not existing
this.addLink = function(source,target,linkId){
    if(!isLinkExisting(linkId)){
        links.push({
            'source':findNode(source),
            'target':findNode(target),
            'linkId':linkId
        });
        this.update();
    }  

}


//returns index of switch by taking its id
var findNode = function (id) {
    for (var i in nodes) {
        if (nodes[i]["id"] === id) return nodes[i];
    };
};
var dragstart= function(d) {
        d3.select(this).classed("fixed", d.fixed = true);
}
var dblclick = function(d){
        d3.select(this).classed("fixed",d.fixed=false);
}
var displayHintText = function(d){
        d3.select(this).select('.hintText').text(d.id);
}
var hideHintText = function(d){
        d3.select(this).select('.hintText').text('');
}
//bring nodes to top of links.
this.keepNodesOnTop =function() {

    $(".node").each(function(index) {
        this.parentNode.appendChild(this);
    });

}

var drag = force.drag()
            .on('dragstart',dragstart);

this.update = function(){


    link = vis.selectAll('.link')
              .data(links,function(d){ return d.linkId});

    //remove extra links from SVG
    link.exit().remove();

    //add extra links to SVG
    link.enter()
        .append('line')
        .attr('class','link');

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

    //remove extra nodes from SVG
    node.exit().remove();

    //add extra nodes to SVG
    var nodeEnter = node.enter()
                    .append('g')
                    .attr('class','node')
                    .on('dblclick', dblclick)
                    .on('mouseover',displayHintText)
                    .on('mouseout',hideHintText)
                    .call(drag);

    //append text element to node group element
    nodeEnter.append('text')
             .attr('class','hintText');

    //append circle to node group element
    nodeEnter.append(function(d){ 

            if(d.type=='circle'){
                return document.createElementNS("http://www.w3.org/2000/svg",d.type);
            }else if(d.type=='rect'){
                return document.createElementNS("http://www.w3.org/2000/svg",d.type);
            }

            }).attr('class','node')
              .each(function(d){
                    if(d.type=='circle'){
                        d3.select(this).attr({
                          r:8,
                        });
                    }else if(d.type=='rect'){
                        d3.select(this).attr({
                          width:16,
                          height:16
                        });
                    }
              });


    force.on('tick',function(e){

        node.attr("transform", function (d) {

            if(d.index==0){
                damper = 0.1;
                d.x = d.x + (width/3 - d.x) * (damper + 0.71) * e.alpha;
                d.y = d.y + (height/3 - d.y) * (damper + 0.71) * e.alpha;
            }

            d.x = Math.min(width,Math.max(d.x,10));
            d.y = Math.min(height,Math.max(d.y,10));
            return "translate(" + d.x + "," + d.y + ")";
            });

        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;
            })
            .attr("id",function(d){
                return d.linkId;
            })

    });
    force.gravity(0.06)
        .charge(-1000)
        .linkDistance( function(d) { return 90 } )
        .size([width, height])
        .start();

}

};

我能够获得两个不同的动力图(draggale),但问题是只有最新绘制的图形链接才能连接到节点。前图是动态的,但链接是静态的。

我在下面提到了链接,他们没有工作: Multiple instances of d3 force layout on the same page Multiple force-layout graphs with d3 in seperate svg/div's

下面是右侧图表如何正常运行的图片。我还为正确提供了链接前缀,但没有用。 two force layouts in sigle page

1 个答案:

答案 0 :(得分:1)

update()函数中,我定义了link而没有var,因为它在全球范围内可用,并且始终采用最新的图形链接。将其更改为var link工作正常。