重新加载(更新)d3.js 力导向图保留旧的 JSON 数据
Reloading (updating) d3.js force-directed graph holds onto old JSON data
所以我有一个 d3.js 力导向图,显示来自 JSON 提要的数据。当我单击一个节点时,我请求了一个基于被单击节点的更新 JSON 提要。
返回的JSON是正确的。但是图表中显示的内容并不反映 JSON 中保存的数据。我有一种感觉,图表保留了以前的图表数据。
这是一个快速的 gif 图像,应该有助于形象化问题。
这里有一个 JSFiddle 让您了解图表当前的工作原理。
而 Javascript 本身就是这个问题的底部。
更详细一点。当您单击一个节点时,它会将与该节点关联的词传递到 URL 的查询字符串中。然后我 运行 d3.js 使用这个新的 'clicked' url 和 运行 更新函数来重新创建图形。
这是一个错误的例子。因此,如果您转到 JSFiddle 并单击名为 'piercingly' 的节点,您会发现下一个加载的图表甚至没有 'piercingly' 这个词,并且仍然有与 bitter 关联的标签(原始搜索)。然而,如果您将 JS 顶部的变量更改为 'piercingly',则会加载一个不同但正确的图表。
节点数正确。但是完整版(不是 JSFiddle 上的版本)中的标签和其他属性是不正确的。
如有任何帮助,我们将不胜感激。
$wordToSearch = "bitter";
var w = 960,
h = 960,
node,
link,
root,
title;
var jsonURL = 'http://desolate-taiga-6759.herokuapp.com/word/basic/' + $wordToSearch;
d3.json(jsonURL, function(json) {
root = json.words[0]; //set root node
root.fixed = true;
root.x = w / 2;
root.y = h / 2 - 80;
update();
});
var force = d3.layout.force()
.on("tick", tick)
.charge(-700)
.gravity(0.1)
.friction(0.9)
.linkDistance(50)
.size([w, h]);
var svg = d3.select(".graph").append("svg")
.attr("width", w)
.attr("height", h);
//Update the graph
function update() {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
// Update the links…
link = svg.selectAll("line.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "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; });
// Exit any old links.
link.exit().remove();
// Update the nodes…
node = svg.selectAll(".node")
.data(nodes);
var nodeE = node
.enter();
var nodeG = nodeE.append("g")
.attr("class", "node")
.call(force.drag);
nodeG.append("circle")
.attr("r", 10)
.on("click", click)
.style("fill", "red");
nodeG.append("text")
.attr("dy", 10 + 15)
.attr("text-anchor", "middle")
.text(function(d) { return d.word });
node.exit().remove();
}
function tick() {
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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
/***********************
*** CUSTOM FUNCTIONS ***
***********************/
//Request extended JSON objects when clicking a clickable node
function click(d) {
$wordClicked = d.word;
var jsonURL = 'http://desolate-taiga-6759.herokuapp.com/word/basic/' + $wordClicked;
console.log(jsonURL);
updateGraph(jsonURL);
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node.children) node.size = node.children.reduce(function(p, v) { return p + recurse(v); }, 0);
if (!node.id) node.id = ++i;
nodes.push(node);
return node.size;
}
root.size = recurse(root);
return nodes;
}
//Update graph with new extended JSON objects
function updateGraph(newURL) {
d3.json(newURL, function(json) {
root = json.words[0]; //set root node
root.fixed = true;
root.x = w / 2;
root.y = h / 2 - 80;
update();
});
}
function getUrlParameter(sParam)
{
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++)
{
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam) {
return sParameterName[1];
}
}
}
编辑: 所以我尝试在将单词添加到文本元素时将其注销。在第一次加载时,所有的单词都会被记录为分配给它们受尊重的文本元素的 get。但是当您单击该节点时,它们不会。 (请参阅下面的 gif)。这很奇怪,因为我在点击时调用了更新功能。所以这个词(理论上)应该为那个节点再次获取。但事实并非如此。
很难掌握 phone 但我认为原因可能是因为它对新数据感到困惑。默认情况下,data()
函数使用项目的索引来加入 DOM。
您需要做的是将另一个函数传递给您对 data()
的调用,该函数被描述为关键函数。在这里你大概可以return这个词。
.data(nodes, function(d) { return d.word; })
查看 API 文档 https://github.com/mbostock/d3/wiki/Selections 中的数据函数。我遇到过几次复杂的情况,但我错过了一个关键功能。
所以我有一个 d3.js 力导向图,显示来自 JSON 提要的数据。当我单击一个节点时,我请求了一个基于被单击节点的更新 JSON 提要。
返回的JSON是正确的。但是图表中显示的内容并不反映 JSON 中保存的数据。我有一种感觉,图表保留了以前的图表数据。
这是一个快速的 gif 图像,应该有助于形象化问题。
这里有一个 JSFiddle 让您了解图表当前的工作原理。 而 Javascript 本身就是这个问题的底部。
更详细一点。当您单击一个节点时,它会将与该节点关联的词传递到 URL 的查询字符串中。然后我 运行 d3.js 使用这个新的 'clicked' url 和 运行 更新函数来重新创建图形。
这是一个错误的例子。因此,如果您转到 JSFiddle 并单击名为 'piercingly' 的节点,您会发现下一个加载的图表甚至没有 'piercingly' 这个词,并且仍然有与 bitter 关联的标签(原始搜索)。然而,如果您将 JS 顶部的变量更改为 'piercingly',则会加载一个不同但正确的图表。
节点数正确。但是完整版(不是 JSFiddle 上的版本)中的标签和其他属性是不正确的。
如有任何帮助,我们将不胜感激。
$wordToSearch = "bitter";
var w = 960,
h = 960,
node,
link,
root,
title;
var jsonURL = 'http://desolate-taiga-6759.herokuapp.com/word/basic/' + $wordToSearch;
d3.json(jsonURL, function(json) {
root = json.words[0]; //set root node
root.fixed = true;
root.x = w / 2;
root.y = h / 2 - 80;
update();
});
var force = d3.layout.force()
.on("tick", tick)
.charge(-700)
.gravity(0.1)
.friction(0.9)
.linkDistance(50)
.size([w, h]);
var svg = d3.select(".graph").append("svg")
.attr("width", w)
.attr("height", h);
//Update the graph
function update() {
var nodes = flatten(root),
links = d3.layout.tree().links(nodes);
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
// Update the links…
link = svg.selectAll("line.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "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; });
// Exit any old links.
link.exit().remove();
// Update the nodes…
node = svg.selectAll(".node")
.data(nodes);
var nodeE = node
.enter();
var nodeG = nodeE.append("g")
.attr("class", "node")
.call(force.drag);
nodeG.append("circle")
.attr("r", 10)
.on("click", click)
.style("fill", "red");
nodeG.append("text")
.attr("dy", 10 + 15)
.attr("text-anchor", "middle")
.text(function(d) { return d.word });
node.exit().remove();
}
function tick() {
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("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
}
/***********************
*** CUSTOM FUNCTIONS ***
***********************/
//Request extended JSON objects when clicking a clickable node
function click(d) {
$wordClicked = d.word;
var jsonURL = 'http://desolate-taiga-6759.herokuapp.com/word/basic/' + $wordClicked;
console.log(jsonURL);
updateGraph(jsonURL);
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node.children) node.size = node.children.reduce(function(p, v) { return p + recurse(v); }, 0);
if (!node.id) node.id = ++i;
nodes.push(node);
return node.size;
}
root.size = recurse(root);
return nodes;
}
//Update graph with new extended JSON objects
function updateGraph(newURL) {
d3.json(newURL, function(json) {
root = json.words[0]; //set root node
root.fixed = true;
root.x = w / 2;
root.y = h / 2 - 80;
update();
});
}
function getUrlParameter(sParam)
{
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++)
{
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == sParam) {
return sParameterName[1];
}
}
}
编辑: 所以我尝试在将单词添加到文本元素时将其注销。在第一次加载时,所有的单词都会被记录为分配给它们受尊重的文本元素的 get。但是当您单击该节点时,它们不会。 (请参阅下面的 gif)。这很奇怪,因为我在点击时调用了更新功能。所以这个词(理论上)应该为那个节点再次获取。但事实并非如此。
很难掌握 phone 但我认为原因可能是因为它对新数据感到困惑。默认情况下,data()
函数使用项目的索引来加入 DOM。
您需要做的是将另一个函数传递给您对 data()
的调用,该函数被描述为关键函数。在这里你大概可以return这个词。
.data(nodes, function(d) { return d.word; })
查看 API 文档 https://github.com/mbostock/d3/wiki/Selections 中的数据函数。我遇到过几次复杂的情况,但我错过了一个关键功能。