3d.js - 更新力导向图上的节点
3d.js - Updating nodes on a force directed graph
我目前正在开发一个程序来创建图形(顶点 + 边)并应用算法。我选择了 3d.js 来制作这个程序。
添加顶点时,我遇到了有关 repaint
函数的问题。
当我添加第一个顶点时,它是有效的,但对于接下来的顶点,我的顶点迅速增加(顶点和标签)...
截图:
源代码:
var graph = (function() {
return {
modules: {},
nodes: [],
links: []
}
})();
graph.modules.engin = (function() {
var w, h, circleWidth, svgApp, force, link, node, nodes;
var palette = {
"white": "#FFFFFF",
"gray": "#708284",
"orange": "#BD3613",
"red": "#D11C24",
"blue": "#2176C7"
};
return {
init: function() {
var w = 960,
h = 450;
circleWidth = 7;
svgApp = d3.select("body")
.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');
force = d3.layout.force()
.nodes(graph.nodes)
.links([])
.gravity(0.1)
.charge(-1000)
.size([w, h]);
//console.log(nodes);
//nodes.push({})
graph.modules.engin.repaint();
graph.modules.engin.insertNode('V1');
graph.modules.engin.insertNode('V2');
graph.modules.engin.insertNode('V3');
},
repaint: function() {
console.log('update');
nodes = force.nodes();
var links = force.links();
link = svgApp.selectAll(".link")
.data(links);
link.enter().append("line")
.attr("class", "link")
.attr("stroke", palette.gray)
.attr("fill", "none");
link.exit().remove();
node = svgApp.selectAll("circle.node")
.data(nodes);
node.enter().append("g")
.attr("class", "node")
.on("mouseover", function(d, i) { //MOUSEOVER
if (!d.root) {
d3.select(this).selectAll("circle")
.transition()
.duration(250)
.style("cursor", "none")
.attr("r", circleWidth + 3)
.attr("fill", palette.orange);
d3.select(this).select("text")
.transition()
.style("cursor", "none")
.duration(250)
.style("cursor", "none")
.attr("font-size", "1.5em")
.attr("x", 15)
.attr("y", 5)
} else {
d3.select(this).selectAll("circle")
.style("cursor", "none");
d3.select(this).select("text")
.style("cursor", "none");
}
})
.on("mouseout", function(d, i) { //MOUSEOUT
if (!d.root) {
//CIRCLE
d3.select(this).selectAll("circle")
.transition()
.duration(250)
.attr("r", circleWidth)
.attr("fill", palette.blue);
//TEXT
d3.select(this).select("text")
.transition()
.duration(250)
.attr("font-size", "1em")
.attr("x", 8)
.attr("y", 4)
}
})
.call(force.drag);
node.append("svg:circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", circleWidth)
.attr("fill", function(d, i) {
if (!d.root) {
return palette.blue;
} else {
return palette.red
}
});
node.append("text")
.text(function(d, i) {
return d.name;
})
.attr("x", function(d, i) {
return circleWidth + 5;
})
.attr("y", function(d, i) {
if (!d.root) {
return circleWidth
} else {
return circleWidth + 5
}
})
.attr("font-family", "Bree Serif")
.attr("fill", function(d, i) {
return palette.white;
})
.attr("font-size", function(d, i) {
return "1em";
})
.attr("text-anchor", function(d, i) {
if (!d.root) {
return "beginning";
} else {
return "end"
}
});
node.exit().remove();
force.on("tick", function(e) {
node.attr("transform", function(d, i) {
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;
})
});
force.start();
},
insertNode: function(name) {
nodes.push({
name: name
})
graph.modules.engin.repaint();
}
}
})();
$(document).ready(function() {
graph.modules.engin.init();
});
html {
background-color: #042029;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<button onclick="addNodes()">Restart Animation</button>
谢谢,
YM
我解决了我的问题:变量引用错误和选择器元素:
源代码:
var graph = (function() {
return {
modules: {},
nodes: [],
links: []
}
})();
graph.modules.engin = (function() {
var w, h, circleWidth, svgApp, force;
var palette = {
"white": "#FFFFFF",
"gray": "#708284",
"orange": "#BD3613",
"red": "#D11C24",
"blue": "#2176C7"
};
return {
init: function() {
h = $('body').height();
w = $('body').width();
circleWidth = 7;
svgApp = d3.select("body")
.append("svg:svg")
.attr("pointer-events", "all")
.attr("width", w)
.attr("height", h)
.attr("viewBox", "0 0 " + w + " " + h)
.attr("perserveAspectRatio", "xMinYMid");
force = d3.layout.force();
graph.nodes = force.nodes();
graph.links = force.links();
graph.modules.engin.repaint();
graph.modules.engin.insertNode('V1');
graph.modules.engin.insertNode('V2');
graph.modules.engin.insertNode('V3');
},
repaint: function() {
console.log('update');
var nodes = force.nodes();
var links = force.links();
console.log('BEFORE REPAINT');
console.log(nodes);
console.log(links);
console.log(graph.nodes);
console.log(graph.links);
var link = svgApp.selectAll("line.link")
.data(links);
var linkEnter = link.enter().append("line")
.attr("class", "link")
.attr("stroke", palette.gray)
.attr("fill", "none");
link.exit().remove();
var node = svgApp.selectAll("g.node")
.data(nodes, function(d) {
return d.name;
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.on("mouseover", function(d, i) {
if (!d.root) {
d3.select(this).select("circle")
.transition()
.duration(250)
.style("cursor", "none")
.attr("r", circleWidth + 3)
.attr("fill", palette.yellow);
d3.select(this) //.select("text")
.transition()
.style("cursor", "none")
.duration(250)
.style("cursor", "none")
.attr("font-size", "1.5em")
.attr("x", 15)
.attr("y", 5)
} else {
d3.select(this).select("circle")
.style("cursor", "none");
d3.select(this).select("text")
.style("cursor", "none");
}
})
.on("mouseout", function(d, i) {
if (!d.root) {
d3.select(this).select("circle")
.transition()
.duration(250)
.attr("r", circleWidth)
.attr("fill", palette.blue);
d3.select(this) //.select("text")
.transition()
.duration(250)
.attr("font-size", "1em")
.attr("x", 8)
.attr("y", 4)
}
})
.call(force.drag);
nodeEnter.append("svg:circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", circleWidth)
.attr("fill", function(d, i) {
if (!d.root) {
return palette.blue;
} else {
return palette.red
}
}).attr("id", function(d) {
return "Node-" + d.name;
});
nodeEnter.append("svg:text")
.text(function(d, i) {
return d.name;
})
.attr("x", function(d, i) {
return circleWidth + 5;
})
.attr("y", function(d, i) {
if (!d.root) {
return circleWidth - 2
} else {
return circleWidth + 5
}
})
.attr("font-family", "Bree Serif")
.attr("fill", function(d, i) {
return palette.white;
})
.attr("font-size", function(d, i) {
return "1em";
})
.attr("text-anchor", function(d, i) {
if (!d.root) {
return "beginning";
} else {
return "end"
}
});
node.exit().remove();
force.on("tick", function(e) {
node.attr("transform", function(d, i) {
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;
})
});
force.gravity(0.1)
.charge(-1000)
.size([w, h])
.start();
},
insertNode: function(name) {
graph.nodes.push({
name: name
})
graph.modules.engin.repaint();
}
}
})();
$(document).ready(function() {
graph.modules.engin.init();
});
html {
background-color: #042029;
}
body {
height: 600px;
width: 100%;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<button onclick="addNodes()">Restart Animation</button>
我目前正在开发一个程序来创建图形(顶点 + 边)并应用算法。我选择了 3d.js 来制作这个程序。
添加顶点时,我遇到了有关 repaint
函数的问题。
当我添加第一个顶点时,它是有效的,但对于接下来的顶点,我的顶点迅速增加(顶点和标签)...
截图:
源代码:
var graph = (function() {
return {
modules: {},
nodes: [],
links: []
}
})();
graph.modules.engin = (function() {
var w, h, circleWidth, svgApp, force, link, node, nodes;
var palette = {
"white": "#FFFFFF",
"gray": "#708284",
"orange": "#BD3613",
"red": "#D11C24",
"blue": "#2176C7"
};
return {
init: function() {
var w = 960,
h = 450;
circleWidth = 7;
svgApp = d3.select("body")
.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');
force = d3.layout.force()
.nodes(graph.nodes)
.links([])
.gravity(0.1)
.charge(-1000)
.size([w, h]);
//console.log(nodes);
//nodes.push({})
graph.modules.engin.repaint();
graph.modules.engin.insertNode('V1');
graph.modules.engin.insertNode('V2');
graph.modules.engin.insertNode('V3');
},
repaint: function() {
console.log('update');
nodes = force.nodes();
var links = force.links();
link = svgApp.selectAll(".link")
.data(links);
link.enter().append("line")
.attr("class", "link")
.attr("stroke", palette.gray)
.attr("fill", "none");
link.exit().remove();
node = svgApp.selectAll("circle.node")
.data(nodes);
node.enter().append("g")
.attr("class", "node")
.on("mouseover", function(d, i) { //MOUSEOVER
if (!d.root) {
d3.select(this).selectAll("circle")
.transition()
.duration(250)
.style("cursor", "none")
.attr("r", circleWidth + 3)
.attr("fill", palette.orange);
d3.select(this).select("text")
.transition()
.style("cursor", "none")
.duration(250)
.style("cursor", "none")
.attr("font-size", "1.5em")
.attr("x", 15)
.attr("y", 5)
} else {
d3.select(this).selectAll("circle")
.style("cursor", "none");
d3.select(this).select("text")
.style("cursor", "none");
}
})
.on("mouseout", function(d, i) { //MOUSEOUT
if (!d.root) {
//CIRCLE
d3.select(this).selectAll("circle")
.transition()
.duration(250)
.attr("r", circleWidth)
.attr("fill", palette.blue);
//TEXT
d3.select(this).select("text")
.transition()
.duration(250)
.attr("font-size", "1em")
.attr("x", 8)
.attr("y", 4)
}
})
.call(force.drag);
node.append("svg:circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", circleWidth)
.attr("fill", function(d, i) {
if (!d.root) {
return palette.blue;
} else {
return palette.red
}
});
node.append("text")
.text(function(d, i) {
return d.name;
})
.attr("x", function(d, i) {
return circleWidth + 5;
})
.attr("y", function(d, i) {
if (!d.root) {
return circleWidth
} else {
return circleWidth + 5
}
})
.attr("font-family", "Bree Serif")
.attr("fill", function(d, i) {
return palette.white;
})
.attr("font-size", function(d, i) {
return "1em";
})
.attr("text-anchor", function(d, i) {
if (!d.root) {
return "beginning";
} else {
return "end"
}
});
node.exit().remove();
force.on("tick", function(e) {
node.attr("transform", function(d, i) {
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;
})
});
force.start();
},
insertNode: function(name) {
nodes.push({
name: name
})
graph.modules.engin.repaint();
}
}
})();
$(document).ready(function() {
graph.modules.engin.init();
});
html {
background-color: #042029;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<button onclick="addNodes()">Restart Animation</button>
谢谢, YM
我解决了我的问题:变量引用错误和选择器元素:
源代码:
var graph = (function() {
return {
modules: {},
nodes: [],
links: []
}
})();
graph.modules.engin = (function() {
var w, h, circleWidth, svgApp, force;
var palette = {
"white": "#FFFFFF",
"gray": "#708284",
"orange": "#BD3613",
"red": "#D11C24",
"blue": "#2176C7"
};
return {
init: function() {
h = $('body').height();
w = $('body').width();
circleWidth = 7;
svgApp = d3.select("body")
.append("svg:svg")
.attr("pointer-events", "all")
.attr("width", w)
.attr("height", h)
.attr("viewBox", "0 0 " + w + " " + h)
.attr("perserveAspectRatio", "xMinYMid");
force = d3.layout.force();
graph.nodes = force.nodes();
graph.links = force.links();
graph.modules.engin.repaint();
graph.modules.engin.insertNode('V1');
graph.modules.engin.insertNode('V2');
graph.modules.engin.insertNode('V3');
},
repaint: function() {
console.log('update');
var nodes = force.nodes();
var links = force.links();
console.log('BEFORE REPAINT');
console.log(nodes);
console.log(links);
console.log(graph.nodes);
console.log(graph.links);
var link = svgApp.selectAll("line.link")
.data(links);
var linkEnter = link.enter().append("line")
.attr("class", "link")
.attr("stroke", palette.gray)
.attr("fill", "none");
link.exit().remove();
var node = svgApp.selectAll("g.node")
.data(nodes, function(d) {
return d.name;
});
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.on("mouseover", function(d, i) {
if (!d.root) {
d3.select(this).select("circle")
.transition()
.duration(250)
.style("cursor", "none")
.attr("r", circleWidth + 3)
.attr("fill", palette.yellow);
d3.select(this) //.select("text")
.transition()
.style("cursor", "none")
.duration(250)
.style("cursor", "none")
.attr("font-size", "1.5em")
.attr("x", 15)
.attr("y", 5)
} else {
d3.select(this).select("circle")
.style("cursor", "none");
d3.select(this).select("text")
.style("cursor", "none");
}
})
.on("mouseout", function(d, i) {
if (!d.root) {
d3.select(this).select("circle")
.transition()
.duration(250)
.attr("r", circleWidth)
.attr("fill", palette.blue);
d3.select(this) //.select("text")
.transition()
.duration(250)
.attr("font-size", "1em")
.attr("x", 8)
.attr("y", 4)
}
})
.call(force.drag);
nodeEnter.append("svg:circle")
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.attr("r", circleWidth)
.attr("fill", function(d, i) {
if (!d.root) {
return palette.blue;
} else {
return palette.red
}
}).attr("id", function(d) {
return "Node-" + d.name;
});
nodeEnter.append("svg:text")
.text(function(d, i) {
return d.name;
})
.attr("x", function(d, i) {
return circleWidth + 5;
})
.attr("y", function(d, i) {
if (!d.root) {
return circleWidth - 2
} else {
return circleWidth + 5
}
})
.attr("font-family", "Bree Serif")
.attr("fill", function(d, i) {
return palette.white;
})
.attr("font-size", function(d, i) {
return "1em";
})
.attr("text-anchor", function(d, i) {
if (!d.root) {
return "beginning";
} else {
return "end"
}
});
node.exit().remove();
force.on("tick", function(e) {
node.attr("transform", function(d, i) {
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;
})
});
force.gravity(0.1)
.charge(-1000)
.size([w, h])
.start();
},
insertNode: function(name) {
graph.nodes.push({
name: name
})
graph.modules.engin.repaint();
}
}
})();
$(document).ready(function() {
graph.modules.engin.init();
});
html {
background-color: #042029;
}
body {
height: 600px;
width: 100%;
}
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<button onclick="addNodes()">Restart Animation</button>