在D3上,我对这两种Javascript都不熟悉,但是我正在尽力创建自己的第一个可视化对象。我创建了一个API,在其中我应私有服务器的请求以json格式请求节点,尝试使用回调,这似乎可行。当我尝试使用d3.hierarcy将此节点用作节点时,它会成功,直到到达图形的渲染为止。启用了拖动功能,在调试过程中,我看到一个节点的x坐标和y坐标在后端按下并拖动时发生了变化,但是在视觉上却没有变化。知道为什么我的代码没有呈现要在更新中进行的更改吗?
谢谢。
var color = d3.scaleOrdinal(d3.schemeCategory10);
var svg = d3.select("svg")
var width = +svg.attr("width");
var height = +svg.attr("height");
var g = svg.append("g").attr("class", "everything");
var link = g.selectAll(".link"),
node = g.selectAll(".node");
var minSize, maxSize;
var sizeScale = d3.scalePow();
var nodes = [],
links = [];
var simulation = d3.forceSimulation()
.force("charge", d3.forceManyBody(nodes).strength(-1000))
.force("link", d3.forceLink(links).distance(200))
.force("x", d3.forceX())
.force("y", d3.forceY())
.alphaTarget(1)
.on("tick", tick);
function load_address(addr, target, callback){
console.log("load address called");
d3.json("/api/address/" + addr, function(error, json) {
if (error || json.error) {
alert("Bad json respnse from API.");
return;
}//throw error;
obj = d3.hierarchy(json);
callback(obj);
});
}
function initialize(){
console.log("Init called");
var root_address = document.getElementById("root_address").value;
load_address(root_address, clusters, update);
}
function setup() {
var maxSize = 0, minSize = Infinity;
var nodes = flatten(clusters[0]);
for (var i = 0; i < nodes.length; ++i) {
maxSize = Math.max(maxSize, nodes[i].total_received);
minSize = Math.min(minSize, nodes[i].total_received);
}
sizeScale.exponent(1)
.domain([minSize, maxSize])
.range([5, 25]);
}
function update_all() {
//reset all nodes, regenerated
all_nodes = [];
all_links = [];
for (var cluster in clusters) {
update(cluster);
}
}
function get_all_descending_nodes(root){
//Recursively get a list of nodes and links
var node_list = [];
var link_list = [];
if(root.descendants){
for (node in root.descendants){
node_list.push(get_all_descending_nodes(node)[0]);
}
link_list.concat(root.descendants)
}
node_list.push(root);
return node_list, link_list
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
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 bound_x(d) {
var r = sizeScale(d.data.total_received);
return Math.max( r, Math.min(width - r, d.x) );
}
function bound_y(d) {
var r = sizeScale(d.data.total_received);
return Math.max( r, Math.min(height - r, d.y) );
}
function tick() {
link
.attr("x1", function(d) { return bound_x(d.source); })
.attr("y1", function(d) { return bound_y(d.source); })
.attr("x2", function(d) { return bound_x(d.target); })
.attr("y2", function(d) { return bound_y(d.target); });
node.attr("transform", function(d) {
return "translate(" + bound_x(d) + "," + bound_y(d) + ")";
});
}
function update(cluster_root) {
console.log("Update called with", cluster_root);
nodes = cluster_root.descendants();
console.log("Nodes so far", nodes);
links = cluster_root.links();
node = node.data(nodes, function(d) { return d.name; });
var nodeEnter = node.enter().append("g")
.attr("class", "node");
nodeEnter.append("circle")
.attr("r", 30)
.attr("cy", 30)
.attr("cx", 30)
.attr("fill", color_classify)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
nodeEnter.append("text")
.attr("dy", ".60em")
.text("test");
node.exit().remove();
link = link.data(links);
var linkEnter = link.enter().append("g")
.attr("class", "link");
linkEnter
.append("line")
.attr("class", "link");
link.exit().remove();
console.log(simulation);
// Restart the force layout.
simulation.nodes(nodes);
console.log(simulation);
console.log(nodes);
simulation.force("link")
.links(links);
console.log(links);
simulation.alpha(1).restart();
}
.node circle {
cursor: pointer;
stroke: #3182bd;
stroke-width: 1.5px;
}
.node text {
font: 8px sans-serif;
pointer-events: none;
text-anchor: middle;
}
.link line {
fill: none;
stroke: #9ecae1;
stroke-width: 1.5px;
}