javascript - 单页多个 svg 中的多个强制布局不起作用

标签 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

下图显示了右侧图表的表现,而左侧图表则正常工作。我还为链接指定了前缀 rightleft 但没有用。 two force layouts in sigle page

最佳答案

update() 函数中,我定义了 link 而没有 var,因此,它在全局范围内可用,并且始终获取最新的图形链接。将其更改为 var link 效果很好。

关于javascript - 单页多个 svg 中的多个强制布局不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36443162/

相关文章:

javascript - 如何读取表内文本框的值

javascript - 为什么追加到元素时我的增量为0

javascript - d3.js 散点图中 [0,0] 处的神秘数据点

SVG 图像在 Safari 中无法正确呈现

javascript - 我如何用颜色填充SVG

javascript - 来自图像拉取的随机图像

javascript - 根据创建时间从对象数组中删除重复项

html - svg 作为背景 html

d3.js - Crossfilter 中过滤维度的大小?

d3.js - d3.csv 函数无法正确加载数据