如何从局部变量jsonNodes
创建d3图表(JSON数据)而不是从文件中读取,我使用的示例是Andrew-Reid’s online example on bl.ocks。
以下是我正在尝试的代码,按钮' Go'正在调用refresh
函数以使用jsonNodes
变量刷新图形。 (我实际上是调用WebSocket服务来填充jsonNodes
但是到目前为止我刚刚在函数中对其进行了硬编码。)
当我点击' Go'按钮,它什么都不做。
<canvas width="960" height="500"></canvas>
<body>
<button id="refresh" onclick="refresh();">Go</button>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
var jsonNodes;
function refresh(){
jsonNodes = {
"nodes": [
{"id": "Myriel", "group": 1},
{"id": "Napoleon", "group": 1},
{"id": "Mlle.Baptistine", "group": 1} ],
"links": [
{"source": "Napoleon", "target": "Myriel", "value": 1} ]
} ;
simulation
.nodes(jsonNodes.nodes)
.force("link")
.links(jsonNodes.links);
};
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
d3.json("../data/miserables.json", function(error, graph) {
if (error) throw error;
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
d3.select(canvas)
.call(d3.drag()
.container(canvas)
.subject(dragsubject));
function ticked() {
var margin = 20;
graph.nodes.forEach(function(d) {
d.x = Math.max(margin, Math.min(width - margin, d.x))
d.y = Math.max(margin, Math.min(height - margin, d.y))
})
context.clearRect(0, 0, width, height);
context.beginPath();
graph.links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
graph.nodes.forEach(drawNode);
context.fill();
context.strokeStyle = "#fff";
context.stroke();
}
function dragsubject() {
return simulation.find(d3.event.x, d3.event.y);
}
});
function drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}
function drawNode(d) {
context.moveTo(d.x + 3, d.y);
context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
}
</script>
</body>
答案 0 :(得分:1)
根据您使用示例代码更新的帖子,很少有可能导致无法获得所需结果的内容。
首先,我可以看到jsonNodes已经是所需格式的对象。
其次,由于数据在变量中已经是所需的格式,因此您无需使用d3.json("../data/miserables.json", function(error, graph) {
if (error) throw error;
对其进行解析。
同样在Andrew Reid的例子中,他使用对象graph
,在您的情况下jsonNodes
。因此,无论何时,您都会看到graph.nodes
或graph.links
将其替换为jsonNodes.nodes
和jsonNodes.links
。更改所有单个位置的更简单的替代方法是将数据从jsonNodes
传输到名为graph
的变量,并使用graph
变量,如Andrew Reid的示例中所示。
最后,您声明模拟的顺序是错误的。你在打电话
simulation
.nodes(jsonNodes.nodes)
.force("link")
.links(jsonNodes.links);
};
之前
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
这是相反的。
这是一个为您准备好一切的东西: https://plnkr.co/edit/LcsGes?p=preview
其他一些例子:http://jsfiddle.net/DavidHoksza/0d7en4po/直接使用变量中的数据。但是,请记住,此示例使用d3 v3,并且力模拟的语法已更改。还有更多的例子直接在力模拟中使用变量:http://blockbuilder.org/kenpenn/268878b410ddb1201277be3f0305d566 您可以使用http://blockbuilder.org/search
搜索更多示例我希望这会有所帮助。如果没有,请为我创建plunker / block来检查你到底发生了什么。并将更多数据填充到jsonNodes变量中。