2

ドーナツを作成するコード (つまり、d3.layout.pie()) があります。

以前は、次の方法で JSON データをロードしていました

d3.json(jsonFilePath,
    function(json) {
             //logic
             ....
            })

私のビジュアライゼーションはインタラクティブです (つまり、ドーナツのサイズは、innerRadius と "d" 属性の両方で変化します)。したがって、enter、remove、update の 3 つのケースと、「d」属性を遷移させる attrTween 関数を正しく実装しました。

それは今まで働いていました。ある種のキャッシング メカニズムを実装することにしました (つまり、データを保持する変数を用意して、データを一度プリフェッチし、必要に応じて再利用できるようにします)。キャッシュの動作をテストしましたが、動作しています。ここにスニペットがあります...

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));
    };
}
4

2 に答える 2

4

スニペットは未定義の変数を参照していますrev。また、配列でfor-inループを使用しないでください。私はあなたがこのような何かを意味したと仮定するつもりです:

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コールバックは非同期であり、クロージャはforループの現在の反復での値rev(またはそれに関しては)をキャプチャしないため、これらはどちらも期待どおりに機能しません。ではなく参照をキャプチャし、したがって、コールバックが後で呼び出されると、すべてのコールバックは、各d3.jsonが呼び出されたときの値ではなく、forループの最後の反復()の値を参照します。irevs.length

これを修正するには、クロージャーを使用して値をキャプチャします。例えば:

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。クロージャーの詳細については、以下を参照してください。

于 2012-04-26T17:11:39.477 に答える
2

問題のあるコードが含まれているとは思いません.JSONキャッシングコードであると思われます. 私の推測では、あなたはまだ JSON を非同期で取得していますが、すぐに使用しようとしています。d3.json()データが実際にロードされるまで呼び出されないコールバック関数を受け取ります-現在のコードに同様の構造は見られないため、リモートファイルからではなくインラインで JSON をロードしない限り、それはおそらく問題。

この場合、コンソールを手動で確認しても役に立ちません。コンソールを確認するまでにデータロードされているためです。問題があるのはコードが実際に実行されているときです。

于 2012-04-26T16:51:21.323 に答える