我试图创建一个网页,用户可以选择节点(使用select2),并且他们选择的每个节点都将被添加到网络中。 我目前无法让节点出现在左上角以外的SVG上。d3.js v4 - 节点卡在左上角
这是我在bl.ocks.org代码: https://bl.ocks.org/shaief/2b4d5cfc7dcc0e03c59f0d6be3cc2913
我一直在寻找,看看有什么其他人一样,但我无法找到,说明我的问题的答案。
编辑: 在我看来,虽然代码运行和滴答,在'勾号'功能它不影响节点对象。我不明白为什么。
EDIT2: 我创建了一个新文件,它是Mike Bostock修改Force Layout 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>
谢谢!只是为了澄清,这是一个模拟的JSON,但它有源码和目标码,因为它正在通过Python的NetworkX。 –
好的。所以在我看来,我在我的代码中跟随links.id API - 我通过使用它们的ID而不是索引来引用节点的每个链接。当我将它改变为默认行为时,我得到这个:'''未捕获的TypeError:无法在字符串'node-uuid-1234567890-2'上创建属性'vx' ''' –
如果您使用字符串ID,则需要指定这样的链接力:var simulation = d3.forceSimulation() .force(“link”,d3.forceLink().id(function(d){return d.id;})),这样你的json链接是:{source:“node-uuid-1234567890-1”target:“node-uuid-1234567890-2”value:1}。vx是速度x的位置,它的基本意思是说,我无法弄清楚创建这个属性来移动你的节点/链接 – Robatron