誰かがD3.jsのdatum()とdata()の違いを説明できますか?両方が使用されているのがわかりますが、なぜどちらを選択する必要があるのか分かりませんか?
マイク自身から正しい答えを見つけました。
データを単一のSVG要素にバインドする場合は、使用します
(...).data([data])
または
(...).datum(data)
データを複数のSVG要素にバインドする場合
(...).data(data).enter().append("svg")
.....
ここにいくつかの良いリンクがあります:
D3 "data()"に関する適切な議論: D3.jsがデータをノードにバインドする方法を理解する
後者ごと:
# selection.data([values[, key]])
指定されたデータの配列を現在の選択と結合します。指定された値は、数値やオブジェクトの配列などのデータ値の配列、または値の配列を返す関数です。
...
# selection.datum([value])
選択された各要素の連結データを取得または設定します。 selection.dataメソッドとは異なり、このメソッドは結合を計算しません(したがって、入力および終了選択を計算しません)。
これを少し調べた後、SOの答えは、入力data
パラメーターを使用してselection.data
およびselection.datum
を呼び出す場合のみを対象としているため、完全ではないことがわかりました。そのシナリオでも、選択が単一の要素である場合と複数の要素が含まれる場合の2つの動作は異なります。さらに、これらのメソッドの両方は、選択範囲内のバインドされたデータ/データを照会するために入力引数なしで呼び出すこともできます。その場合、これらは再び異なる動作をし、異なるものを返します。
編集-私はこの質問に対するもう少し詳細な答えを投稿しました here 、しかし、以下の投稿は2つの方法とそれらがどのように異なるかに関するすべての重要なポイントをほとんどキャプチャします。
指定時data
as 入力引数
selection.data(data)
は、data
配列の要素間でデータ結合を実行しようとしますが、選択するとenter()
、exit()
、update()
の選択が作成され、それらを後で操作できます。この最終結果は、配列data = [1,2,3]
を渡すと、個々のデータ要素(つまりデータム)を選択に結合する試みが行われます。選択の各要素には、data
のデータ要素が1つだけバインドされます。
selection.datum(data)
は、データ結合プロセスを完全にバイパスします。これは、データ結合の場合のように分割することなく、選択範囲内のすべての要素にdata
全体を単に割り当てます。したがって、配列data = [1, 2, 3]
をselection
内のすべてのDOM要素にバインドする場合、selection.datum(data)
はこれを実現します。
警告:
selection.datum(data)
はselection.data([data])
と同等であると信じていますが、これはselection
の場合にのみ当てはまります単一の要素を含む。selection
に複数のDOM要素が含まれている場合、selection.datum(data)
は、data
全体を選択範囲内のすべての要素にバインドします。対照的に、selection.data([data])
はdata
全体をselection
の最初の要素にのみバインドします。これは、selection.data
のデータ結合動作と一致しています。
data
入力引数を指定しない場合
selection.data()
は、選択範囲内の各要素のバインドされたデータを取得し、それらを結合して返される配列にします。したがって、selection
にデータ"a"
、"b"
、および"c"
がそれぞれバインドされた3つのDOM要素が含まれている場合、selection.data()
は["a", "b", "c"]
を返します。 selection
が(例として)データム"a"
がバインドされた単一の要素である場合、selection.data()
は一部の人が期待するように["a"]
ではなく"a"
を返すことに注意することが重要です。
selection.datum()
は、選択のデータム最初の要素にバインドを返すように定義されているため、単一の選択に対してのみ意味があります。したがって、"a"
、"b"
、および"c"
のバインドされたデータムを含むDOM要素で構成される選択の上記の例では、selection.datum()
は単に"a"
を返します。
selection
に単一の要素がある場合でも、selection.datum()
とselection.data()
は異なる値を返すことに注意してください。前者は選択範囲のバインドされたデータム(上の例では"a"
)を返し、後者は配列内のバインドされたデータム(上の例では["a"]
)を返します。
これは、入力引数としてデータを提供する場合と、入力引数を提供しないことでバインドされたデータを照会する場合の両方でselection.data
とselection.datum()
がどのように異なるかを明確にするのに役立ちます。
PS-これがどのように機能するかを理解する最良の方法は、Chromeの空のHTMLドキュメントから開始し、コンソールを開いてドキュメントにいくつかの要素を追加し、selection.data
およびselection.datum
を使用してデータのバインドを開始することです。時々、読むよりも行うことで何かを「グロッキング」する方がずっと簡単です。
HamsterHueyの説明はこれまでのところ最高だと思います。それを拡張し、違いを視覚的に表現するために、data
name__とdatum
name__の違いの少なくとも一部を示すサンプルドキュメントを作成しました。
以下の答えは、これらの方法を使用することから得られた意見の詳細ですが、間違っている場合は修正できてうれしいです。
この例は、以下または このFiddleで で実行できます。
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
datum
name__は結合を行わないため、把握するのが簡単だと思いますが、もちろん、これは異なるユースケースがあることも意味します。
私にとって大きな違いは-さらにありますが、data
name__がd3チャートで(ライブ)更新を行う自然な方法であるという事実です。
一方、datum
name__は静的な表現により適しているようです。たとえば、次の例では、元の配列でループし、次のようにインデックスでデータにアクセスすると同じ結果が得られます。
data.map((n, i) => {
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node-${n} => data: ${d[i]}`);
});
ここで試してください: https://jsfiddle.net/gleezer/e4m6j2d8/6/
繰り返しになりますが、enter/update/exitパターンによる精神的な負担から解放されるので、これは把握しやすいと思いますが、選択を更新または変更する必要があるとすぐに、きっと.data()
に頼る方が良いでしょう。
const data = [1,2,3,4,5];
const el = d3.select('#root');
el
.append('div')
.classed('a', true)
.datum(data)
.text(d => `node => data: ${d}`);
const join= el
.selectAll('div.b')
.data(data);
join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)
/* Ignore all the css */
html {
font-family: arial;
}
.l {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
margin: 10px 0;
}
.l-a {
background: #cf58e4;
}
.l-b {
background: #42e4e4;
}
.a {
border-bottom: 2px solid #cf58e4;
}
.b {
border-bottom: 2px solid #42e4e4;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script>
<div style="margin-bottom: 20px;">
<span class="l l-a"></span> .datum() <br />
<span class="l l-b"></span> .data()
</div>
<div id="root"></div>