d3二图秒杀一图布局
d3 second graph kills first one's force layout
当我想显示多个网络可视化图时,我在使用 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
构造函数的第二个 运行 上,第一个 myGraph
的 window.self
被新值覆盖。因此,两个 myGraph
对象中的事件都引用了第二个 self
,这导致了损坏。
您可能想要启用 strict mode,这样编译器就会对这种难以追踪的错误发出警告。
当我想显示多个网络可视化图时,我在使用 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
构造函数的第二个 运行 上,第一个 myGraph
的 window.self
被新值覆盖。因此,两个 myGraph
对象中的事件都引用了第二个 self
,这导致了损坏。
您可能想要启用 strict mode,这样编译器就会对这种难以追踪的错误发出警告。