我有一段代码可以创建一个 donut (即 d3.layout.pie())。
我以前用下面的方式加载JSON数据
d3.json(jsonFilePath,
function(json) {
//logic
....
})
我的可视化是交互式的(即 donut 的大小变化,innerRadius 和“d”属性)。所以我正确地实现了三种情况,enter、remove 和 update 以及 attrTween 函数来转换“d”属性。
它一直有效到现在。我决定实现某种缓存机制(即,我有一个保存数据的变量,以便数据被预取一次并在需要时重新使用)。我测试了我的缓存的行为并且它正在工作。 这是一个片段......
if(cache[name] == undefined) {
console.log('Loading data and create viz');
// Loading all the JSONs for this name
var remaining = revs.length;
// revs is an array w/ json file names to load (elements in the form r1, r4 etc.)
var current = {};
for (var i in revs) {
d3.json(revs[i] + ".json" , function(json) {
current["r"+json.revision] = json;
if (!--remaining) {
// Data loaded, here, hence setting cache
cache[appName] = current;
createViz(rev);
}
});
}
}
我说到重点了。我用包含加载的 JSON 字符串的缓存数据的简单访问替换了我用来加载数据的方式,所以现在我没有上面的代码块,而是看起来像
var currentCache = cache[someName];
var json = currentCache[revisionName];
当我检查 json 变量时,json 已正确加载并且看起来很好。关键是现在过渡不再有效,我收到了很多消息,例如
Error: Problem parsing d="M2.1431318985078682e-14,-350A350,350 0 1,1 NaN,NaNLNaN,NaNA230.68565589945686,230.68565589945686 0 1,0 1.412542250532388e-14,-230.68565589945686Z"
我之前已经收到过这些消息,但现在我不知道为什么会这样。代码没有改变,我没有使用 d3.json(),而是使用变量中的 json 字符串。有什么建议吗?
附上部分代码供引用...
// An array of objects such as {"name" : myObject, "calls" : 23}
var calls = json.children;
var donut = d3.layout.pie()
.value(function(d) { return d.calls; })
.sort(null)
var arcs = d3.select("#vizGroup")
.selectAll(".callSlice")
.data(donut(calls));
//update
arcs
.data(donut(calls))
.transition()
.duration(750)
.attrTween("d", arcTween)
.style("fill", function(d) { return somecolor(d.data.name); } )
//enter
arcs.enter()
.append("svg:path")
.style("fill", function(d) { return somecolor(d.data.name); } )
.attr("stroke", "#EEF")
.attr('class', 'callSlice')
.each(function(d) { this._current = d; })
.transition()
.duration(750)
.attrTween("d", arcTween)
//remove
arcs.exit().remove();
function arcTween(a) {
a.innerRadius = myScale(myVariable);
var i = d3.interpolate({
startAngle: this._current.startAngle,
endAngle: this._current.endAngle,
innerRadius: this._current.innerRadius}, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
最佳答案
您的代码段引用了 undefined variable rev
。另外,不要使用 for-in loop用一个数组。我假设你的意思是这样的:
for (var i = 0, n = revs.length; i < n; ++i) {
d3.json(revs[i] + ".json", function(json) {
var rev = revs[i];
/* do something with rev here */
});
}
或者等价地,像这样:
for (var i = 0, n = revs.length; i < n; ++i) {
var rev = revs[i];
d3.json(revs[i] + ".json", function(json) {
/* do something with rev here */
});
}
这些都不会按预期工作,因为 d3.json 回调是异步的,并且闭包不会捕获 rev
的值(或者就此而言 i
)在 for 循环的当前迭代中:它们捕获一个引用,而不是一个值,因此当稍后调用回调时,您的所有回调都将看到for 循环的最后 迭代中的值 (revs.length
),而不是调用每个 d3.json 时的值。
您可以通过使用闭包捕获值来解决此问题。例如:
for (var i = 0, n = revs.length; i < n; ++i) {
fetch(revs[i]);
}
function fetch(rev) {
d3.json(rev + ".json", function(json) {
/* do something with rev here */
});
}
这是有效的,因为 rev
的每个唯一值都由函数 fetch
捕获。有关闭包的更多信息,请参阅:
关于javascript - 使用和不使用 d3.json() 驱动 D3 图表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10337668/