我正在尝试创建一个网页,用户可以在其中选择节点(使用select2),并且他们选择的每个节点都将添加到网络中。 我目前无法使节点出现在SVG上除左上角之外的某个位置。
这是我在bl.ocks.org上的代码: https://bl.ocks.org/shaief/2b4d5cfc7dcc0e03c59f0d6be3cc2913
我希望看到其他人做了什么,但我没有找到解释我的问题的答案。
编辑: 在我看来,虽然代码运行和滴答,但在'ticked'函数中它不会影响节点对象。我无法弄明白为什么。
EDIT2: 我创建了一个新文件,它是Mike Bostock修改力布局II(https://bl.ocks.org/mbostock/0adcc447925ffae87975a3a81628a196)的复制粘贴,并添加了我的select2部分。结果是日志已满:
Uncaught TypeError: Cannot create property 'vx' on string 'node-uuid-1234567890-5'
at n (d3.v4.min.js:2)
at d3.v4.min.js:2
at be.each (d3.v4.min.js:2)
at e (d3.v4.min.js:2)
at n (d3.v4.min.js:2)
at vn (d3.v4.min.js:2)
at _n (d3.v4.min.js:2)
这很奇怪,因为迈克的例子确实使用节点ID而不是序数索引,我不明白原因。
EDIT3: 我在这里添加相关代码,因为我用完全不同的代码更新了我的要点。
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/js/select2.min.js"></script>
</head>
<style>
.container {
margin-top: 10px;
display: flex;
}
.controls {
/* padding: 10px; */
width: 350px;
}
#select-node-names {
width: 100%;
}
.d3-container {
flex-grow: 1;
}
.links line {
stroke: #999;
stroke-opacity: 0.6;
}
.nodes circle {
stroke: #fff;
/* stroke-width: 1.5px; */
stroke-width: 0px;
}
text {
font: 10px sans-serif;
color: red;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
</style>
<div class='row'>
<select id="select-node-names" multiple="multiple">
</select>
<div class="container">
<div class="controls">
<div class="test-nodes"></div>
</div>
<div class="d3-container">
<svg width="960" height="600"></svg>
</div>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
d3.json("test.json", function(error, graph) {
if (error) throw error;
$("#select-node-names")
.select2();
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
// Color scale for node colors
var color = d3.scaleOrdinal(d3.schemeCategory10);
// Color scale for link colors
var linkColor = d3.scaleOrdinal(d3.schemeCategory10);
var simulation = d3.forceSimulation(graph.nodes)
.force("charge", d3.forceManyBody()
.strength(function(d) {
return d.degree;
}))
.force('x', d3.forceX())
.force('y', d3.forceY())
.force("collision", d3.forceCollide(20))
.force("centering", d3.forceCenter(width / 2, height / 2))
.force("link", d3.forceLink()
.id(function(d) {
return d.id
}))
.on("tick", ticked);
var nodes = [];
var links = [];
var nodeNames = Object.values(graph.nodes);
var listItem = d3.select("#select-node-names")
.selectAll("option")
.data(nodeNames)
.enter()
.append("option")
.text(function(d) {
return d.object_name;
})
.attr("id", function(d) {
return d.id;
})
.attr("value", function(d) {
return d.id;
});
linksID = [];
graph.links.forEach(function(e) {
var sourceNode = graph.nodes[e.source]["id"];
var targetNode = graph.nodes[e.target]["id"];
linksID.push({
source: sourceNode,
target: targetNode,
value: e.type
});
});
$(document.body)
.on("change", "#select-node-names", function() {
nodes = search($("#select-node-names")
.val(), "id", graph.nodes);
nodesID = nodes.map(function(d) {
return d.id;
});
linksSource = search(nodesID, "source", linksID);
linksTarget = search(nodesID, "target", linksID);
links = [];
links = links.concat(linksSource, linksTarget);
update();
});
var nodesG = svg.append("g");
var linksG = svg.append("g");
var node = nodesG
.selectAll(".nodes")
var link = linksG
.selectAll(".links")
update()
function update() {
var showSelectedNodes = d3.select(".test-nodes")
.html("");
var showSelectedNodes = d3.select(".test-nodes")
.selectAll("myText")
.data(nodes);
showSelectedNodes.exit()
.remove(); // EXIT
showSelectedNodes.enter()
.append("small") // ENTER
.text(function(d) {
return d.object_name + " // ";
})
.merge(showSelectedNodes) // ENTER + UPDATE
var node = nodesG
.selectAll("circle")
.data(nodes);
exitNode = node.exit()
.remove(); // EXIT
node = node.enter()
.append("circle") // ENTER
.attr("class", "nodes")
.attr("r", 10)
.attr("fill", function(d) {
return color(d.node_type);
})
.append("title")
.text(function(d) {
return "Node: " + d.id + "\nName: " + d.object_name +
"\nCoordinates: " + d.x + " - " + d.y;
})
.append("text")
.attr("dx", 8)
.attr("dy", ".31em")
.text(function(d) {
return d.object_name;
})
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended))
.merge(node) // ENTER + UPDATE
link = link.enter()
.data(links)
.append("line")
.style('stroke', function(d) {
return linkColor(d.type);
})
.attr("stroke-width", 2)
.append("title")
.text(function(d) {
return "Source: " + d.source + "\nTarget: " + d.target +
"\nType: " + d.type;
});
// Update and restart the simulation.
simulation.nodes(nodes);
simulation.force("link", d3.forceLink()
.id(function(d) {
return d.id
}));
simulation.alphaTarget(1);
simulation.restart();
}
function ticked() {
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;
});
node.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
/* node.attr("transform", transform);*/
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3)
.restart();
d.fx = null;
d.fy = null;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
function transform(d) {
return "translate(" + d.x + "," + d.y + ")";
};
});
function search(valuesArray, prop, myArray) {
var res = [];
for (var i = 0; i < valuesArray.length; i++) {
for (var j = 0; j < myArray.length; j++) {
if (myArray[j][prop] == valuesArray[i]) {
res.push(myArray[j]);
break;
}
}
}
return res
}
</script>
答案 0 :(得分:0)
我看到的直接事情:
您并未在所有情况下都将链接添加到模拟中:应通过simulation.force(&#34; ..&#34;)。链接( link-array)完成)
您需要明确您用于链接的ID。你需要使用节点的顺序位置,例如0是第一个节点。或节点的实际id,例如&#34; node-uuid-1234567890-1&#34;。你正在为后者而努力。阅读以选择您要使用的是哪一个。在你的json中,你使用数字作为链接源和目标。
总结这些要点,这可能是您基于已完成的重启逻辑,但您需要与您的ID使用保持一致:
simulation.nodes(nodes);
simulation.force("link").links(links);
simulation.alpha(1).restart();
了解Mike的links.id api ref,了解如何更新模拟。你做了太多工作