2

このd3ビジュアライゼーションhttp://bl.ocks.org/4745936を実装して、.tsvの代わりに動的データをロードしました

私の場合、サーバーが新しい情報をセレクターに渡すと、既存のグラフの内容を変更する代わりに、最初のグラフの下に2番目のグラフがレンダリングされます。

私はそれがこのappend方法に関係していると信じています。

var svg = d3.select(selector).append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

exit().remove()そのため、凡例変数と都市変数の直後に他のメソッドを追加しようとしましappend('g');たが、JavaScriptコンソールには、exit()その時点ではメソッドが存在しないと表示されます。

私は完全に間違ったアプローチをしていると感じていますが、このような既存のグラフを更新するにはどうすればよいですか?2番目と3番目のグラフを前のグラフと一緒に生成することは、私が望んでいた結果ではありません。

4

4 に答える 4

2

そうです、appendメソッドは毎回新しいsvg要素を追加しています。チャートの重複を防ぐには、svg要素がすでに存在するかどうかを確認する必要があります。したがって、最初に次のようなことを試してください。

var svg = d3.select("#mycontainer > svg")
if (svg.empty())
    svg = d3.select(selector).append("svg");
...

exit()のドキュメントに記載されているように、このメソッドは、データ演算子によって返された選択に対してのみ定義されます。したがって、から返された選択に対してexitを呼び出していることを確認してください.data(..)

于 2013-02-13T20:06:31.257 に答える
1

scottの答えは、初期化が1回だけ行われるようにする1つの方法です。

しかし、私はこれを処理するよりd3-icの方法を好みます:

var svg = d3.select(selector)
            .selectAll('svg')
            .data( [ dataFromTSV ] ); // 1 element array -> 1 svg element

// This will be empty if the `svg` element already exists.
var gEnter = svg.enter()
               .append('svg')
               .append('g');

gEnter.append( ... ); // Other elements to be appended only once like axis

svg.attr('width', ...)
   .attr('height', ...);

// Finally, working with the elements which are surely in the DOM.
var g = svg.select("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

g.selectAll(...).attr(...);

このアプローチは、再利用可能なチャートの例ソースコードに例示されています。

このアプローチは、初期化と更新のロジックを隠すことで、コードを非常に宣言的で視覚化に忠実に保つため、私はこのアプローチを好みます。


元の例を変更します:http://jsfiddle.net/8Axn7/5/からhttp://jsfiddle.net/3Ztt8/

凡例とグラフはどちらも、svgElemデータの1つの要素から定義されます。

var svgElem = d3.select("#multiLinegraph").selectAll('svg')
            .data([cities]);

// ...

var svg = svgElem.select('g');

// ...


var city = svg.selectAll(".city")
    .data(
        function (d) { return d; },
        function (d) { return d.name; } // Object consistency 
    );

// ...


var legend = svg.selectAll('g.legend')
    .data(
        function(d) { return d; }, 
        function (d) { return d.name; } // Object consistency 
    );

また、静的プロパティは要素が入力(または終了)されるときに1回だけ設定され、更新プロパティは更新ごとに設定(遷移)されます。

gEnter.append("g")
    .attr("class", "y multiLineaxis")
  .append('text')
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Requests (#)");

svg.select('g.y.multiLineaxis').transition().call(yAxis);

私の意見では、コードはenter-update-exitのサイクルをきれいにたどっています。

于 2013-02-13T20:29:08.110 に答える
1

私はいくつかのjQueryとCSSブードゥーでこの問題を解決することができました

基本的に、私のd3グラフは既存のセレクター(私の場合はdiv)にsvg要素を追加するので、これの名前を動的にチェックすることができました

var svgtest = d3.select(selector+" > svg"); そのdivのsvgサブチャイルド要素を取得します。次に、jqueryを使用してその要素をdomから完全に削除し、d3を実行し続け、svgの必要なものをすべて追加することができます。

 var svgtest = d3.select(selector+" > svg");
    if(!svgtest.empty())
    {
        $(selector+" > svg").remove();
    }
于 2013-02-14T22:01:54.540 に答える
1

まず、古いsvgを削除する必要があります。その後、更新されたグラフを追加できます。そのためには、svgを追加する前に1行だけ追加する必要があります。そしてその働き。

 var flag=d3.select("selector svg").remove();

//----古いコードはここから始まります-------

var svg = d3.select(selector).append("svg")
于 2014-02-25T12:56:48.983 に答える