Saya menggunakan Chart.js untuk menggambar diagram lingkaran di halaman php saya. Saya menemukan tooltip sebagai menunjukkan setiap nilai irisan.
Tapi saya ingin menampilkan nilai-nilai itu seperti gambar di bawah ini.
Saya tidak tahu bagaimana melakukan ini dengan chart.js.
Tolong bantu saya.
Kode Javascript saya:
function drawPie(canvasId,data,legend){
var ctx = $("#pie-canvas-" + canvasId).get(0).getContext("2d");
var piedata = [];
$.each(data,function(i,val){
piedata.push({value:val.count,color:val.color,label:val.status});
});
var options =
{
tooltipTemplate: "<%= Math.round(circumference / 6.283 * 100) %>%",
}
var pie = new Chart(ctx).Pie(piedata,options);
if(legend)document.getElementById("legend").innerHTML = pie.generateLegend();
}
kode php:
printf('<table><tr>');
echo '<td style="text-align: right;"><canvas id="pie-canvas-'
. $canvasId
. '" width="256" height="256" ></canvas></td><td style="text-align: left;width:360px;height:auto" id="legend" class="chart-legend"></td></tr></table>';
echo '<script type="text/javascript">drawPie('
. $canvasId
. ', '
. $data3
.', '
. $legend
. ');</script>';
Untuk Chart.js 2.0 ke atas, data objek Chart telah berubah. Bagi yang menggunakan Chart.js 2.0+, di bawah ini adalah contoh penggunaan metode HTML5 Canvas fillText()
untuk menampilkan nilai data di dalam potongan pie. Kode ini juga berfungsi untuk grafik donat, dengan satu-satunya perbedaan adalah type: 'pie'
versus type: 'doughnut'
saat membuat grafik.
Script:
Javascript
var data = {
datasets: [{
data: [
11,
16,
7,
3,
14
],
backgroundColor: [
"#FF6384",
"#4BC0C0",
"#FFCE56",
"#E7E9ED",
"#36A2EB"
],
label: 'My dataset' // for legend
}],
labels: [
"Red",
"Green",
"Yellow",
"Grey",
"Blue"
]
};
var pieOptions = {
events: false,
animation: {
duration: 500,
easing: "easeOutQuart",
onComplete: function () {
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
total = dataset._meta[Object.keys(dataset._meta)[0]].total,
mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
start_angle = model.startAngle,
end_angle = model.endAngle,
mid_angle = start_angle + (end_angle - start_angle)/2;
var x = mid_radius * Math.cos(mid_angle);
var y = mid_radius * Math.sin(mid_angle);
ctx.fillStyle = '#fff';
if (i == 3){ // Darker text color for lighter background
ctx.fillStyle = '#444';
}
var percent = String(Math.round(dataset.data[i]/total*100)) + "%";
//Don't Display If Legend is hide or value is 0
if(dataset.data[i] != 0 && dataset._meta[0].data[i].hidden != true) {
ctx.fillText(dataset.data[i], model.x + x, model.y + y);
// Display percent in another line, line break doesn't work for fillText
ctx.fillText(percent, model.x + x, model.y + y + 15);
}
}
});
}
}
};
var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
type: 'pie', // or doughnut
data: data,
options: pieOptions
});
HTML
<canvas id="pieChart" width=200 height=200></canvas>
[jsFiddle][1]
Dari apa yang saya ketahui, saya tidak percaya bahwa Chart.JS memiliki fungsi apa pun untuk membantu menggambar teks pada diagram lingkaran. Tetapi itu tidak berarti Anda tidak dapat melakukannya sendiri dalam JavaScript asli. Saya akan memberi Anda contoh bagaimana melakukannya, di bawah ini adalah kode untuk menggambar teks untuk setiap segmen dalam diagram lingkaran:
function drawSegmentValues()
{
for(var i=0; i<myPieChart.segments.length; i++)
{
// Default properties for text (size is scaled)
ctx.fillStyle="white";
var textSize = canvas.width/10;
ctx.font= textSize+"px Verdana";
// Get needed variables
var value = myPieChart.segments[i].value;
var startAngle = myPieChart.segments[i].startAngle;
var endAngle = myPieChart.segments[i].endAngle;
var middleAngle = startAngle + ((endAngle - startAngle)/2);
// Compute text location
var posX = (radius/2) * Math.cos(middleAngle) + midX;
var posY = (radius/2) * Math.sin(middleAngle) + midY;
// Text offside to middle of text
var w_offset = ctx.measureText(value).width/2;
var h_offset = textSize/4;
ctx.fillText(value, posX - w_offset, posY + h_offset);
}
}
Pie Chart memiliki array segmen yang disimpan dalam PieChart.segments
, kita dapat melihat startAngle
dan endAngle
dari segmen-segmen ini untuk menentukan sudut di antara tempat teks akan menjadi middleAngle
. Kemudian kita akan bergerak ke arah itu dengan Radius/2
untuk berada di titik tengah grafik dalam radian.
Pada contoh di atas beberapa operasi pembersihan lainnya dilakukan, karena posisi teks yang digambar di fillText()
menjadi sudut kanan atas, kita perlu mendapatkan beberapa nilai offset untuk mengoreksi hal itu. Dan akhirnya textSize
ditentukan berdasarkan ukuran grafik itu sendiri, semakin besar grafik semakin besar teksnya.
[Contoh Teka-Teki](
)Dengan sedikit modifikasi, Anda dapat mengubah nilai angka diskrit untuk dataset menjadi angka persentil dalam grafik. Untuk melakukan ini, dapatkan total nilai
dari item-item dalam dataset Anda, sebut ini totalValue
. Kemudian pada setiap segmen Anda dapat menemukan persen dengan melakukan:
Math.round(myPieChart.segments[i].value/totalValue*100)+'%';
Bagian di sini myPieChart.segments[i].value/totalValue
adalah apa yang menghitung persen yang diambil oleh segmen dalam grafik. Sebagai contoh jika segmen saat ini memiliki nilai 50
dan totalValue adalah 200
. Maka persentase yang diambil segmen akan menjadi: 50/200 => 0.25
. Sisanya adalah untuk membuat ini terlihat bagus. 0.25*100 => 25
, lalu kita tambahkan %
di akhir. Untuk ubin persen bilangan bulat, saya membulatkan ke bilangan bulat terdekat, meskipun dapat menyebabkan masalah dengan akurasi. Jika kita membutuhkan akurasi yang lebih tinggi, Anda dapat menggunakan .toFixed(n)
untuk menghemat tempat desimal. Sebagai contoh kita bisa melakukan ini untuk menyimpan satu tempat desimal ketika dibutuhkan:
var value = myPieChart.segments[i].value/totalValue*100;
if(Math.round(value) !== value)
value = (myPieChart.segments[i].value/totalValue*100).toFixed(1);
value = value + '%';
[Contoh Tengah-tengah persentil dengan desimal](
2/)[Teka-teki Contoh persentil dengan bilangan bulat](
1/)Jawaban @Hung Tran'bekerja dengan sempurna. Sebagai perbaikan, saya sarankan untuk tidak menampilkan nilai yang 0. Katakanlah Anda memiliki 5 elemen dan 2 di antaranya adalah 0 dan sisanya memiliki nilai, solusi di atas akan menampilkan 0 dan 0%. Lebih baik untuk menyaringnya dengan pemeriksaan tidak sama dengan 0!
var val = dataset.data[i]; var persen = String(Math.round(val/total*100)) + "%";
if(val != 0) { ctx.fillText(dataset.data[i], model.x + x, model.y + y); // Menampilkan persen di baris lain, jeda baris tidak berfungsi untuk fillText ctx.fillText(percent, model.x + x, model.y + y + 15); }
Kode yang diperbarui di bawah ini:
var data = {
datasets: [{
data: [
11,
16,
7,
3,
14
],
backgroundColor: [
"#FF6384",
"#4BC0C0",
"#FFCE56",
"#E7E9ED",
"#36A2EB"
],
label: 'My dataset' // for legend
}],
labels: [
"Red",
"Green",
"Yellow",
"Grey",
"Blue"
]
};
var pieOptions = {
events: false,
animation: {
duration: 500,
easing: "easeOutQuart",
onComplete: function () {
var ctx = this.chart.ctx;
ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
ctx.textAlign = 'center';
ctx.textBaseline = 'bottom';
this.data.datasets.forEach(function (dataset) {
for (var i = 0; i < dataset.data.length; i++) {
var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
total = dataset._meta[Object.keys(dataset._meta)[0]].total,
mid_radius = model.innerRadius + (model.outerRadius - model.innerRadius)/2,
start_angle = model.startAngle,
end_angle = model.endAngle,
mid_angle = start_angle + (end_angle - start_angle)/2;
var x = mid_radius * Math.cos(mid_angle);
var y = mid_radius * Math.sin(mid_angle);
ctx.fillStyle = '#fff';
if (i == 3){ // Darker text color for lighter background
ctx.fillStyle = '#444';
}
var val = dataset.data[i];
var percent = String(Math.round(val/total*100)) + "%";
if(val != 0) {
ctx.fillText(dataset.data[i], model.x + x, model.y + y);
// Display percent in another line, line break doesn't work for fillText
ctx.fillText(percent, model.x + x, model.y + y + 15);
}
}
});
}
}
};
var pieChartCanvas = $("#pieChart");
var pieChart = new Chart(pieChartCanvas, {
type: 'pie', // or doughnut
data: data,
options: pieOptions
});