Saya menggunakan D3 untuk mencetak beberapa rect out. Sekarang saya berharap rect dapat memungkinkan pengguna mengkliknya dan mengaktifkan beberapa fungsi.

Misalnya, ada 3 persegi panjang, "Tom", "Mary" dan "Ben". Ketika pengguna mengklik rect yang berbeda, itu akan melewati nilai saat ini. Seperti ketika saya mengklik "Tom" itu akan melewati "Tom" untuk memanggil fungsi.

Namun, saya menemukan bahwa setelah selesai mencetak rect, tidak peduli saya mengklik rect mana, keduanya mengembalikan nilai terkecil dari dataset.

Dalam contoh saya, bahkan saya mengklik "Tom" atau "Mary", keduanya mengembalikan "Ben".

for (var i = 0; i < ward_set.length; i++) {
  var ward_id = ward_set[i];
  legend.append("rect")
    .attr("x", legend_x + 180 + 100 * n)
    .attr("y", legend_y)
    .attr("width", 18)
    .attr("height", 18)
    .attr("fill", colors[count])
    .attr("class", "legend" + ward_set[i])
    .on("click", function() {
      console.log(ward_id);
    });
}
1
skt_fans_boy 20 Maret 2019, 10:32

1 menjawab

Jawaban Terbaik

Pertanyaan Anda dengan sempurna menggambarkan prinsip yang sangat penting, aturan praktis jika Anda suka, saat menulis kode D3: jangan pernah menggunakan loop untuk menambahkan elemen. Gunakan pola masuk/perbarui/keluar sebagai gantinya.

Apa yang terjadi ketika Anda menggunakan loop (baik itu for, while, forEach dll...) adalah bahwa tidak hanya tidak ada pengikatan data, tetapi Anda juga mengalami hasil yang aneh ini. dijelaskan (selalu mendapatkan nilai terakhir), yang dijelaskan di sini: Penutupan JavaScript di dalam loop – contoh praktis sederhana

Oleh karena itu, solusi menggunakan pilihan enter idiomatis D3 adalah:

const data = ["Tom", "Mary", "Ben"];

const svg = d3.select("svg");

const rects = svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  //etc...

Kemudian, di pendengar click, Anda mendapatkan argumen pertama, yaitu datum:

.on("click", function(d) {
    console.log(d)
})

Berikut adalah demonya:

const data = ["Tom", "Mary", "Ben"];

const svg = d3.select("svg");

const rects = svg.selectAll(null)
  .data(data)
  .enter()
  .append("rect")
  .attr("width", 50)
  .attr("height", 150)
  .attr("x", (_, i) => i * 60)
  .on("click", function(d) {
    console.log(d)
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>
1
Gerardo Furtado 20 Maret 2019, 07:55