Chart.js - gambar titik arbitrer dengan tooltip
Saya telah menerapkan teknik yang dijelaskan dalam pertanyaan ini untuk membuat garis vertikal pada bagan saya untuk menunjukkan tanggal-tanggal penting ketika sesuatu yang penting terjadi.
Namun, teks yang mendeskripsikan peristiwa ini bisa sangat panjang, jadi menggambar teks di kanvas bukanlah solusi yang baik.
Apakah ada cara untuk menggunakan API chart.js untuk menggambar titik tak terlihat pada grafik (di bagian atas garis) yang akan menjadi interaktif dan menampilkan tooltip saat mouse diarahkan ke atasnya?
Sejauh yang saya bisa lihat, hanya titik data yang akan menampilkan tooltips. Saya mencoba untuk menambahkan seri lain untuk memuat data garis, tetapi tidak banyak berhasil - itu juga menciptakan legenda untuk seri ini, yang tidak saya inginkan. Saya menetapkan nilai ke 9999 untuk mencoba membuatnya muncul di atas kanvas, tetapi ini tidak berhasil dan tampak seperti retasan.
Jawaban
Anda dapat menambahkan kumpulan data kedua yang berisi satu nilai di posisi x di mana garis vertikal harus digambar, nilainya harus sesuai dengan nilai tertinggi dari kumpulan data pertama. Untuk membuat titik tidak terlihat, tentukan latar belakang transparan dan warna batas menggunakan 'rgba(0,0,0,0)'.
{
data: [null, null, 12],
pointRadius: 10,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)'
}
Untuk hanya menampilkan label legenda dari kumpulan data yang relevan, Anda perlu menentukan legend.labels.filterfungsi.
legend: {
labels: {
filter: legendItem => legendItem.datasetIndex == 0
}
},
Selanjutnya kita perlu mendefinisikan beberapa tooltip.callbackfungsi untuk menampilkan data yang diinginkan di tooltips.
Silakan lihat cuplikan kode runnable di bawah ini dan lihat cara kerjanya. Kode ini menggunakan versi stabil terbaru dari Chart.js (saat ini 2.9.3).
new Chart('canvas', {
type: 'line',
plugins: [{
beforeDraw: chart => {
var ctx = chart.chart.ctx;
var xAxis = chart.scales['x-axis-0'];
var yAxis = chart.scales['y-axis-0'];
ctx.save();
var lineAtIndex = chart.data.datasets[0].lineAtIndex;
var x = xAxis.getPixelForTick(lineAtIndex);
ctx.strokeStyle = '#ff0000';
ctx.beginPath();
ctx.moveTo(x, yAxis.bottom);
ctx.lineTo(x, yAxis.top);
ctx.stroke();
ctx.restore();
}
}],
data: {
labels: ["JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"],
datasets: [{
label: 'My Dataset',
data: [12, 3, 2, 1, 8, 8, 2, 2, 3, 5, 7, 1],
lineAtIndex: 2,
lineTooltip: ['This is', 'a multi-line', 'tooltip']
},
{
data: [null, null, 12],
pointRadius: 10,
backgroundColor: 'rgba(0,0,0,0)',
borderColor: 'rgba(0,0,0,0)'
}
]
},
options: {
legend: {
labels: {
filter: legendItem => legendItem.datasetIndex == 0
}
},
tooltips: {
callbacks: {
title: (tooltipItems, data) => {
if (tooltipItems[0].datasetIndex == 0) {
return data.labels[tooltipItems[0].index];
}
return data.datasets[0].lineTooltip;
},
label: (tooltipItems, data) => {
if (tooltipItems.datasetIndex == 0) {
return data.datasets[0].label + ': ' + data.datasets[0].data[tooltipItems.index];
}
return null;
}
}
},
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="canvas" height="90"></canvas>