javascript - 使用和不使用 d3.json() 驱动 D3 图表

标签 javascript json d3.js transition interpolation

我有一段代码可以创建一个 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/

相关文章:

javascript - 将 Bookmarklet Javascript 添加到 block ?

javascript - 如果按钮存在则单击它

javascript - D3.js强制布局: Dynamically added node doesn't move with rest of graph

javascript - 跨浏览器d3.js SVG线条渲染日期排序

javascript - 为什么我无法选择列表框值?

javascript - 通过页面模板 Meteor 操作集合数组?

json - 检查 JSON 是对象还是数组

javascript - 使用多个缩略图加载页面的技术 (laravel 5.3)

java - Android内部存储: File is empty as soon as it has been read

angular - d3v5 Angular 8 生产模式 - 错误类型错误 : (void 0) is not a function