我目前正在对此d3js force layout tutorial进行一些自定义修改。通常,我的兴趣是在后端和d3.js可视化之间引入一个抽象层,我正在使用JS类进行此操作。现在,我主要是丢弃我在模拟.json文件中拥有的某些属性,但是这种逻辑可能会变得更加复杂。
这是我似乎无法上班的MWE:
index.html
:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
</head>
<body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="js/model.js"></script>
<script src="js/viz.js"></script>
</body>
</html>
model.js
:
class Node {
constructor(id, name) {
this.id = id;
this.name = name;
this.outEdges = {};
this.inEdges = {};
}
}
class Edge {
constructor(node1, node2) {
this.source = node1;
this.target = node2;
}
}
class Graph {
constructor(nodes, edges) {
this.nodes = {}
for (let node of nodes) {
this.nodes[node.id] = node;
}
for (let edge of edges) {
this.nodes[edge.source].outEdges[edge.target] = edge;
this.nodes[edge.target].inEdges[edge.source] = edge;
}
this.edges = edges;
}
}
viz.js
:
function loadJson() {
path = "mockup2.json";
$.getJSON(path, function(json) {
var nodes = [];
var edges = [];
for (let node of json.nodes) {
var temp = new Node(node.index, node.name);
nodes.push(temp);
}
for (let edge of json.edges) {
var temp = new Edge(edge.node1, edge.node2);
edges.push(temp);
}
var graph = new Graph(nodes, edges);
drawGraph(graph);
});
}
function drawGraph(graph) {
width = "90%";
height = "90%";
// set up svg and layout
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var force = d3.layout.force()
.gravity(.1)
.distance(20)
.charge(-30)
.size([width, height]);
// prep nodes and links for d3 viz
var d3nodes = [];
var temp = {};
for (var key in graph.nodes) {
node = graph.nodes[key]
temp = {}
temp.x = Math.random() * 100;
temp.y = Math.random() * 100;
temp.index = node.id;
d3nodes.push(temp);
}
d3edges = [];
var temp = {}
for (var key in graph.edges) {
edge = graph.edges[key];
temp = {}
temp.source = edge.source;
temp.target = edge.target;
temp.timediff = edge.timediff;
d3edges.push(temp);
}
// draw links and nodes
var svglinks = svg.selectAll('.link')
.data(d3edges)
.enter().append('line')
.attr('class', 'link');
var svgnodes = svg.selectAll('.node')
.data(d3nodes)
.enter().append('g')
.attr('class', 'node')
.call(force.drag);
force.nodes(d3nodes)
.links(d3edges)
.linkDistance(width/3)
.start();
// test svglinks values
svglinks.forEach(function(d) {
console.log(JSON.stringify(d));
});
force.on("tick", function() {
svglinks.attr("x1", function(d) {
console.log(JSON.stringify(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; });
svgnodes.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
// avoid console spam
force.stop();
});
}
$(document).ready(function() {
loadJson();
});
mockup2.json
:
{
"nodes": [
{"index": 0, "name": 0, "timestamp": 1, "group": 1},
{"index": 1, "name": 0, "timestamp": 0, "group": 2},
{"index": 2, "name": 0, "timestamp": 0, "group": 3},
{"index": 3, "name": 0, "timestamp": 2, "group": 1},
{"index": 4, "name": 0, "timestamp": 0, "group": 2},
{"index": 5, "name": 0, "timestamp": 3, "group": 3},
{"index": 6, "name": 0, "timestamp": 2, "group": 3},
{"index": 7, "name": 0, "timestamp": 5, "group": 2},
{"index": 8, "name": 0, "timestamp": 8, "group": 2},
{"index": 9, "name": 0, "timestamp": 3, "group": 1}
],
"edges": [
{"node1": 1, "node2": 2},
{"node1": 2, "node2": 4},
{"node1": 4, "node2": 8},
{"node1": 4, "node2": 8},
{"node1": 8, "node2": 2},
{"node1": 5, "node2": 9}
]
}
对我来说,最可恶的是,svglinks
变量似乎在force.on('tick')
之外之前还不错,它显示x
,y
,{ {1}}和px
-我也提供了一个py
通话供您检查。但是,在该函数中打印相同的对象将为我显示所有这些属性的console.log()
值,这使d3.js可以正确地绘制图形(至少以我的直觉)。
我还有一个更“标准”的示例,该示例使用更标准的null
调用来加载.json文件,该文件已预先格式化为d3.json()
和source
属性;这很完美。因此,我的直觉是我没有在上面正确构建target
和d3nodes
变量;但是,将它们与示例进行比较表明,它们看起来完全一样。我承认,我在这里有些傻眼了!
预先感谢所有愿意花时间去尝试的人。