Tampilkan data pada mouse di atas lingkaran

162

Saya memiliki satu set data yang saya plot di sebar. Ketika saya mengarahkan mouse ke salah satu lingkaran saya ingin popup dengan data (seperti nilai x, y, mungkin lebih). Inilah yang saya coba gunakan:

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
   .attr("cx", function(d) { return x(d.x);})
   .attr("cy", function(d) {return y(d.y)})
   .attr("fill", "red").attr("r", 15)
   .on("mouseover", function() {
        d3.select(this).enter().append("text")
            .text(function(d) {return d.x;})
            .attr("x", function(d) {return x(d.x);})
            .attr("y", function (d) {return y(d.y);}); });

Saya kira saya harus lebih informatif tentang data apa yang akan dimasukkan?

ScottieB
sumber
1
Saya juga sudah mencoba: vis.selectAll ("lingkaran"). Masing-masing (fungsi (d) {vis.append ("svg: text"). Attr ("x", dx) .attr ("y", dy) .text (fungsi (d) {return dx;});}); sia-sia sayangnya.
ScottieB

Jawaban:

181

Saya berasumsi bahwa yang Anda inginkan adalah tooltip. Cara termudah untuk melakukan ini adalah menambahkansvg:title elemen ke setiap lingkaran, karena browser akan mengurus menunjukkan tooltip dan Anda tidak perlu penangan mouse. Kode tersebut akan menjadi sesuatu seperti

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
   ...
   .append("svg:title")
   .text(function(d) { return d.x; });

Jika Anda ingin tooltips yang lebih keren, Anda bisa menggunakan tipsy misalnya. Lihat di sini untuk contoh.

Lars Kotthoff
sumber
3
Saya suka mabuk. Satu-satunya masalah saya sekarang adalah bahwa ia menunjuk ke sudut kiri atas lingkaran, daripada tepi seperti dalam demo itu. Saya tidak menemukan alasan yang jelas mengapa. jsfiddle.net/scottieb/JwaaV (mabuk di bagian paling bawah)
ScottieB
Jsfiddle itu tampaknya tidak memiliki tooltips?
Lars Kotthoff
Anda bisa mencoba menambahkan tooltip ke svg:gyang Anda overlay dengan lingkaran yang sebenarnya, tetapi berikan nol lebar dan tinggi. Saat ini sedang mengambil kotak pembatas dan meletakkan tooltip di tepinya. Bermain-main dengan opsi tipy mungkin bisa membantu juga.
Lars Kotthoff
1
Sepertinya tidak berfungsi lagi. Juga saya menemukan contoh menggunakan svg: judul yang gagal: bl.ocks.org/ilyabo/1339996
nos
1
@nos Bekerja untuk saya.
Lars Kotthoff
145

Cara yang sangat baik untuk membuat tooltip dijelaskan di sini: Contoh tooltip D3 sederhana

Anda harus menambahkan div

var tooltip = d3.select("body")
    .append("div")
    .style("position", "absolute")
    .style("z-index", "10")
    .style("visibility", "hidden")
    .text("a simple tooltip");

Maka Anda bisa beralih menggunakan

.on("mouseover", function(){return tooltip.style("visibility", "visible");})
.on("mousemove", function(){return tooltip.style("top",
    (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
.on("mouseout", function(){return tooltip.style("visibility", "hidden");});

d3.event.pageX/ d3.event.pageYadalah koordinat mouse saat ini.

Jika Anda ingin mengubah teks yang dapat Anda gunakan tooltip.text("my tooltip text");

Contoh Kerja

Pwdr
sumber
4
Bisakah Anda mengikat data ke tooltip ini?
Jorge Leitao
2
Afaik Anda dapat mengikat data ke setiap elemen DOM.
Pwdr
untuk mengikat data ke ini, tambahkan saja d di dalam tanda kurung seperti ini: function (d) {... dan ubah teks menjadi apa yang Anda inginkan. Misalnya, Anda memiliki nama: tooltip.text (d.name):
thatOneGuy
39

Ada perpustakaan yang luar biasa untuk melakukan itu yang baru-baru ini saya temukan. Sangat mudah digunakan dan hasilnya cukup rapi: d3-tip.

Anda dapat melihat contoh di sini :

masukkan deskripsi gambar di sini

Pada dasarnya, yang harus Anda lakukan adalah mengunduh ( index.js ), termasuk skrip:

<script src="index.js"></script>

dan kemudian ikuti instruksi dari sini (tautan yang sama seperti contoh)

Tetapi untuk kode Anda, itu akan menjadi seperti:

tentukan metode:

var tip = d3.tip()
  .attr('class', 'd3-tip')
  .offset([-10, 0])
  .html(function(d) {
    return "<strong>Frequency:</strong> <span style='color:red'>" + d.frequency + "</span>";
  })

buat svg Anda (seperti yang sudah Anda lakukan)

var svg = ...

panggil metode:

svg.call(tip);

tambahkan tip ke objek Anda:

vis.selectAll("circle")
   .data(datafiltered).enter().append("svg:circle")
...
   .on('mouseover', tip.show)
   .on('mouseout', tip.hide)

Jangan lupa untuk menambahkan CSS:

<style>
.d3-tip {
  line-height: 1;
  font-weight: bold;
  padding: 12px;
  background: rgba(0, 0, 0, 0.8);
  color: #fff;
  border-radius: 2px;
}

/* Creates a small triangle extender for the tooltip */
.d3-tip:after {
  box-sizing: border-box;
  display: inline;
  font-size: 10px;
  width: 100%;
  line-height: 1;
  color: rgba(0, 0, 0, 0.8);
  content: "\25BC";
  position: absolute;
  text-align: center;
}

/* Style northward tooltips differently */
.d3-tip.n:after {
  margin: -1px 0 0 0;
  top: 100%;
  left: 0;
}
</style>
DanielX2010
sumber
2
Tip d3 terbaru mendukung d3v4 dengan baik. Tidak jelas jika Anda mencari di sekitar Google, tetapi ini berfungsi baik bagi saya dengan d3v4.
moodboom
6

Anda dapat mengirimkan data yang akan digunakan di mouseover seperti ini- acara mouseover menggunakan fungsi dengan enterdata yang sebelumnya Anda ed sebagai argumen (dan indeks sebagai argumen kedua) sehingga Anda tidak perlu menggunakan enter()kedua kalinya.

vis.selectAll("circle")
.data(datafiltered).enter().append("svg:circle")
.attr("cx", function(d) { return x(d.x);})
.attr("cy", function(d) {return y(d.y)})
.attr("fill", "red").attr("r", 15)
.on("mouseover", function(d,i) {
    d3.select(this).append("text")
        .text( d.x)
        .attr("x", x(d.x))
        .attr("y", y(d.y)); 
});
danimal
sumber
Terima kasih. Saya benar-benar membutuhkan d3.select(this)untuk memodifikasi bentuk dan tidak tahu bagaimana mendapatkan instance dalam enter / pembaruan.
Turbo
Anda menggunakan beberapa fungsi x () dan y () yang tidak didefinisikan dalam kode Anda. Saya pikir itu bisa dihapus.
Robert
mereka diberikan dalam OP
danimal
5

Contoh ringkas ini menunjukkan cara umum cara membuat tooltip kustom di d3.

var w = 500;
var h = 150;

var dataset = [5, 10, 15, 20, 25];

// firstly we create div element that we can use as
// tooltip container, it have absolute position and
// visibility: hidden by default

var tooltip = d3.select("body")
  .append("div")
  .attr('class', 'tooltip');

var svg = d3.select("body")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

// here we add some circles on the page

var circles = svg.selectAll("circle")
  .data(dataset)
  .enter()
  .append("circle");

circles.attr("cx", function(d, i) {
    return (i * 50) + 25;
  })
  .attr("cy", h / 2)
  .attr("r", function(d) {
    return d;
  })
  
  // we define "mouseover" handler, here we change tooltip
  // visibility to "visible" and add appropriate test
  
  .on("mouseover", function(d) {
    return tooltip.style("visibility", "visible").text('radius = ' + d);
  })
  
  // we move tooltip during of "mousemove"
  
  .on("mousemove", function() {
    return tooltip.style("top", (event.pageY - 30) + "px")
      .style("left", event.pageX + "px");
  })
  
  // we hide our tooltip on "mouseout"
  
  .on("mouseout", function() {
    return tooltip.style("visibility", "hidden");
  });
.tooltip {
    position: absolute;
    z-index: 10;
    visibility: hidden;
    background-color: lightblue;
    text-align: center;
    padding: 4px;
    border-radius: 4px;
    font-weight: bold;
    color: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>

Mikhail Shabrikov
sumber
Jika ada yang membutuhkan ujung alat untuk bergerak relatif ke posisi objek. Seperti dalam kasus grafik pohon. Anda mungkin ingin menggunakan return tooltip.style("top", (d.x + 40) + "px") .style("left", (d.y + 80) + "px");dalam 'mousemove'atribut. Ini d.xakan membantu memindahkan ujung alat relatif ke objek, bukan seluruh halaman
Chandra Kanth