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のサイクルをきれいにたどっています。