Bagaimana membuat Teks di dalam bagan donat, saya menggunakan ChartJs .
Jawaban:
Anda harus mengubah kode seperti: in chart.Doughnut.defaults
labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"
dan kemudian berfungsi drawPieSegments
ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);
Lihat tarikan ini: https://github.com/nnnick/Chart.js/pull/35
berikut adalah biola http://jsfiddle.net/mayankcpdixit/6xV78/ menerapkan hal yang sama.
Tidak ada jawaban lain yang mengubah ukuran teks berdasarkan jumlah teks dan ukuran donat. Berikut ini skrip kecil yang dapat Anda gunakan untuk secara dinamis menempatkan sejumlah teks di tengah, dan secara otomatis akan mengubah ukurannya.
Contoh: http://jsfiddle.net/kdvuxbtj/
Ini akan membutuhkan teks dalam jumlah berapa pun yang berukuran sempurna untuk donat. Untuk menghindari menyentuh tepi, Anda dapat mengatur bantalan samping sebagai persentase dari diameter bagian dalam lingkaran. Jika Anda tidak mengaturnya, maka defaultnya adalah 20. Anda juga akan memilih warna, font, dan teks. Plugin akan menangani sisanya.
Kode plugin akan dimulai dengan ukuran font dasar 30px. Dari sana itu akan memeriksa lebar teks dan membandingkannya dengan jari-jari lingkaran dan mengubah ukurannya berdasarkan rasio lebar lingkaran / teks.
Ini memiliki ukuran font minimum default 20px. Jika teks melebihi batas pada ukuran font minimum, itu akan membungkus teks. Tinggi garis default saat membungkus teks adalah 25px, tetapi Anda dapat mengubahnya. Jika Anda menyetel ukuran font minimum default ke false, teks akan menjadi sangat kecil dan tidak akan terbungkus.
Ini juga memiliki ukuran font maks default 75px jika tidak ada cukup teks dan hurufnya akan terlalu besar.
Ini adalah kode plugin
Chart.pluginService.register({
beforeDraw: function(chart) {
if (chart.config.options.elements.center) {
// Get ctx from string
var ctx = chart.chart.ctx;
// Get options from the center object in options
var centerConfig = chart.config.options.elements.center;
var fontStyle = centerConfig.fontStyle || 'Arial';
var txt = centerConfig.text;
var color = centerConfig.color || '#000';
var maxFontSize = centerConfig.maxFontSize || 75;
var sidePadding = centerConfig.sidePadding || 20;
var sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
// Start with a base font of 30px
ctx.font = "30px " + fontStyle;
// Get the width of the string and also the width of the element minus 10 to give it 5px side padding
var stringWidth = ctx.measureText(txt).width;
var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
// Find out how much the font can grow in width.
var widthRatio = elementWidth / stringWidth;
var newFontSize = Math.floor(30 * widthRatio);
var elementHeight = (chart.innerRadius * 2);
// Pick a new font size so it will not be larger than the height of label.
var fontSizeToUse = Math.min(newFontSize, elementHeight, maxFontSize);
var minFontSize = centerConfig.minFontSize;
var lineHeight = centerConfig.lineHeight || 25;
var wrapText = false;
if (minFontSize === undefined) {
minFontSize = 20;
}
if (minFontSize && fontSizeToUse < minFontSize) {
fontSizeToUse = minFontSize;
wrapText = true;
}
// Set font settings to draw it correctly.
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
ctx.font = fontSizeToUse + "px " + fontStyle;
ctx.fillStyle = color;
if (!wrapText) {
ctx.fillText(txt, centerX, centerY);
return;
}
var words = txt.split(' ');
var line = '';
var lines = [];
// Break words up into multiple lines if necessary
for (var n = 0; n < words.length; n++) {
var testLine = line + words[n] + ' ';
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > elementWidth && n > 0) {
lines.push(line);
line = words[n] + ' ';
} else {
line = testLine;
}
}
// Move the center up depending on line height and number of lines
centerY -= (lines.length / 2) * lineHeight;
for (var n = 0; n < lines.length; n++) {
ctx.fillText(lines[n], centerX, centerY);
centerY += lineHeight;
}
//Draw text in center
ctx.fillText(line, centerX, centerY);
}
}
});
Dan Anda menggunakan opsi berikut di objek bagan Anda
options: {
elements: {
center: {
text: 'Red is 2/3 the total numbers',
color: '#FF6384', // Default is #000000
fontStyle: 'Arial', // Default is Arial
sidePadding: 20, // Default is 20 (as a percentage)
minFontSize: 20, // Default is 20 (in px), set to false and text will not wrap.
lineHeight: 25 // Default is 25 (in px), used for when text wraps
}
}
}
Penghargaan untuk @Jenna Sloan atas bantuannya dalam matematika yang digunakan dalam solusi ini.
Berikut adalah contoh yang dibersihkan dan gabungan dari solusi di atas - responsif (coba ubah ukuran jendela), mendukung penyelarasan otomatis animasi, mendukung tooltips
https://jsfiddle.net/cmyker/u6rr5moq/
Chart.types.Doughnut.extend({
name: "DoughnutTextInside",
showTooltip: function() {
this.chart.ctx.save();
Chart.types.Doughnut.prototype.showTooltip.apply(this, arguments);
this.chart.ctx.restore();
},
draw: function() {
Chart.types.Doughnut.prototype.draw.apply(this, arguments);
var width = this.chart.width,
height = this.chart.height;
var fontSize = (height / 114).toFixed(2);
this.chart.ctx.font = fontSize + "em Verdana";
this.chart.ctx.textBaseline = "middle";
var text = "82%",
textX = Math.round((width - this.chart.ctx.measureText(text).width) / 2),
textY = height / 2;
this.chart.ctx.fillText(text, textX, textY);
}
});
var data = [{
value: 30,
color: "#F7464A"
}, {
value: 50,
color: "#E2EAE9"
}, {
value: 100,
color: "#D4CCC5"
}, {
value: 40,
color: "#949FB1"
}, {
value: 120,
color: "#4D5360"
}];
var DoughnutTextInsideChart = new Chart($('#myChart')[0].getContext('2d')).DoughnutTextInside(data, {
responsive: true
});
<html>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<body>
<canvas id="myChart"></canvas>
</body>
</html>
UPDATE 17.06.16:
Fungsionalitas yang sama tetapi untuk chart.js versi 2:
https://jsfiddle.net/cmyker/ooxdL2vj/
var data = {
labels: [
"Red",
"Blue",
"Yellow"
],
datasets: [
{
data: [300, 50, 100],
backgroundColor: [
"#FF6384",
"#36A2EB",
"#FFCE56"
],
hoverBackgroundColor: [
"#FF6384",
"#36A2EB",
"#FFCE56"
]
}]
};
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx;
ctx.restore();
var fontSize = (height / 114).toFixed(2);
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle";
var text = "75%",
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = height / 2;
ctx.fillText(text, textX, textY);
ctx.save();
}
});
var chart = new Chart(document.getElementById('myChart'), {
type: 'doughnut',
data: data,
options: {
responsive: true,
legend: {
display: false
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
Uncaught TypeError: Cannot read property 'extend' of undefined
ide?
Saya akan menghindari memodifikasi kode chart.js untuk mencapai ini, karena cukup mudah dengan CSS dan HTML biasa. Inilah solusi saya:
HTML:
<canvas id="productChart1" width="170"></canvas>
<div class="donut-inner">
<h5>47 / 60 st</h5>
<span>(30 / 25 st)</span>
</div>
CSS:
.donut-inner {
margin-top: -100px;
margin-bottom: 100px;
}
.donut-inner h5 {
margin-bottom: 5px;
margin-top: 0;
}
.donut-inner span {
font-size: 12px;
}
Outputnya terlihat seperti ini:
Ini juga bekerja di akhir saya ...
<div style="width: 100px; height: 100px; float: left; position: relative;">
<div
style="width: 100%; height: 40px; position: absolute; top: 50%; left: 0; margin-top: -20px; line-height:19px; text-align: center; z-index: 999999999999999">
99%<Br />
Total
</div>
<canvas id="chart-area" width="100" height="100" />
</div>
Berdasarkan jawaban @ rap-2-h, Berikut kode untuk menggunakan teks pada diagram donat di Chart.js untuk digunakan di dashboard seperti. Ini memiliki ukuran font dinamis untuk opsi responsif.
HTML:
<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>
Naskah:
var doughnutData = [
{
value: 100,
color:"#F7464A",
highlight: "#FF5A5E",
label: "Red"
},
{
value: 50,
color: "#CCCCCC",
highlight: "#5AD3D1",
label: "Green"
}
];
$(document).ready(function(){
var ctx = $('#chart-area').get(0).getContext("2d");
var myDoughnut = new Chart(ctx).Doughnut(doughnutData,{
animation:true,
responsive: true,
showTooltips: false,
percentageInnerCutout : 70,
segmentShowStroke : false,
onAnimationComplete: function() {
var canvasWidthvar = $('#chart-area').width();
var canvasHeight = $('#chart-area').height();
//this constant base on canvasHeight / 2.8em
var constant = 114;
var fontsize = (canvasHeight/constant).toFixed(2);
ctx.font=fontsize +"em Verdana";
ctx.textBaseline="middle";
var total = 0;
$.each(doughnutData,function() {
total += parseInt(this.value,10);
});
var tpercentage = ((doughnutData[0].value/total)*100).toFixed(2)+"%";
var textWidth = ctx.measureText(tpercentage).width;
var txtPosx = Math.round((canvasWidthvar - textWidth)/2);
ctx.fillText(tpercentage, txtPosx, canvasHeight/2);
}
});
});
Berikut kode contoh. Coba ubah ukuran jendela. http://jsbin.com/wapono/13/edit
Anda dapat menggunakan css dengan pemosisian relatif / absolut jika ingin responsif. Selain itu, alat ini dapat menangani multi-line dengan mudah.
https://jsfiddle.net/mgyp0jkk/
<div class="relative">
<canvas id="myChart"></canvas>
<div class="absolute-center text-center">
<p>Some text</p>
<p>Some text</p>
</div>
</div>
Ini didasarkan pada pembaruan Cmyker untuk Chart.js 2. (diposting sebagai jawaban lain karena saya belum bisa berkomentar)
Saya mengalami masalah dengan perataan teks di Chrome saat legenda ditampilkan karena tinggi bagan tidak menyertakan ini sehingga tidak disejajarkan dengan benar di tengah. Memperbaiki ini dengan memperhitungkan ini dalam perhitungan fontSize dan textY.
Saya menghitung persentase di dalam metode daripada nilai yang ditetapkan karena saya memiliki beberapa di halaman ini. Asumsinya adalah bagan Anda hanya memiliki 2 nilai (jika tidak, berapa persentasenya? Dan yang pertama adalah yang ingin Anda perlihatkan persentasenya. Saya juga memiliki banyak bagan lain, jadi saya melakukan pemeriksaan untuk type = donut. Saya hanya menggunakan donat untuk menunjukkan persentase jadi itu berhasil untuk saya.
Warna teks tampaknya sedikit terpukul dan terlewat tergantung pada urutan apa yang dijalankan dll jadi saya mengalami masalah saat mengubah ukuran bahwa teks akan berubah warna (antara hitam dan warna primer dalam satu kasus, dan warna sekunder dan putih di kasus lain) jadi Saya "menyimpan" apa pun gaya isian yang ada, menggambar teks (dengan warna data utama) lalu mengembalikan gaya isian yang lama. (Mempertahankan gaya pengisian lama sepertinya tidak diperlukan tetapi Anda tidak pernah tahu.)
https://jsfiddle.net/g733tj8h/
Chart.pluginService.register({
beforeDraw: function(chart) {
var width = chart.chart.width,
height = chart.chart.height,
ctx = chart.chart.ctx,
type = chart.config.type;
if (type == 'doughnut')
{
var percent = Math.round((chart.config.data.datasets[0].data[0] * 100) /
(chart.config.data.datasets[0].data[0] +
chart.config.data.datasets[0].data[1]));
var oldFill = ctx.fillStyle;
var fontSize = ((height - chart.chartArea.top) / 100).toFixed(2);
ctx.restore();
ctx.font = fontSize + "em sans-serif";
ctx.textBaseline = "middle"
var text = percent + "%",
textX = Math.round((width - ctx.measureText(text).width) / 2),
textY = (height + chart.chartArea.top) / 2;
ctx.fillStyle = chart.config.data.datasets[0].backgroundColor[0];
ctx.fillText(text, textX, textY);
ctx.fillStyle = oldFill;
ctx.save();
}
}
});
Anda juga dapat menempelkan kode mayankcpdixit di onAnimationComplete
opsi:
// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
onAnimationComplete: function() {
ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
}
});
Teks akan ditampilkan setelah animasi
save
metode
Saya membuat demo dengan 7 jQueryUI Slider dan ChartJs (dengan teks dinamis di dalamnya)
Chart.types.Doughnut.extend({
name: "DoughnutTextInside",
showTooltip: function() {
this.chart.ctx.save();
Chart.types.Doughnut.prototype.showTooltip.apply(this, arguments);
this.chart.ctx.restore();
},
draw: function() {
Chart.types.Doughnut.prototype.draw.apply(this, arguments);
var width = this.chart.width,
height = this.chart.height;
var fontSize = (height / 140).toFixed(2);
this.chart.ctx.font = fontSize + "em Verdana";
this.chart.ctx.textBaseline = "middle";
var red = $( "#red" ).slider( "value" ),
green = $( "#green" ).slider( "value" ),
blue = $( "#blue" ).slider( "value" ),
yellow = $( "#yellow" ).slider( "value" ),
sienna = $( "#sienna" ).slider( "value" ),
gold = $( "#gold" ).slider( "value" ),
violet = $( "#violet" ).slider( "value" );
var text = (red+green+blue+yellow+sienna+gold+violet) + " minutes";
var textX = Math.round((width - this.chart.ctx.measureText(text).width) / 2);
var textY = height / 2;
this.chart.ctx.fillStyle = '#000000';
this.chart.ctx.fillText(text, textX, textY);
}
});
var ctx = $("#myChart").get(0).getContext("2d");
var myDoughnutChart = new Chart(ctx).DoughnutTextInside(data, {
responsive: false
});
@ rap-2-h dan @Ztuons Ch jawaban tidak memungkinkan showTooltips
opsi untuk aktif, tetapi yang dapat Anda lakukan adalah membuat dan melapisi keduacanvas
objek belakang yang menampilkan bagan.
Bagian penting adalah gaya yang diperlukan dalam div dan untuk objek kanvas itu sendiri sehingga mereka ditampilkan di atas satu sama lain.
var data = [
{value : 100, color : 'rgba(226,151,093,1)', highlight : 'rgba(226,151,093,0.75)', label : "Sector 1"},
{value : 100, color : 'rgba(214,113,088,1)', highlight : 'rgba(214,113,088,0.75)', label : "Sector 2"},
{value : 100, color : 'rgba(202,097,096,1)', highlight : 'rgba(202,097,096,0.75)', label : "Sector 3"}
]
var options = { showTooltips : true };
var total = 0;
for (i = 0; i < data.length; i++) {
total = total + data[i].value;
}
var chartCtx = $("#canvas").get(0).getContext("2d");
var chart = new Chart(chartCtx).Doughnut(data, options);
var textCtx = $("#text").get(0).getContext("2d");
textCtx.textAlign = "center";
textCtx.textBaseline = "middle";
textCtx.font = "30px sans-serif";
textCtx.fillText(total, 150, 150);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js"></script>
<html>
<body>
<div style="position: relative; width:300px; height:300px;">
<canvas id="text"
style="z-index: 1;
position: absolute;
left: 0px;
top: 0px;"
height="300"
width="300"></canvas>
<canvas id="canvas"
style="z-index: 2;
position: absolute;
left: 0px;
top: 0px;"
height="300"
width="300"></canvas>
</div>
</body>
</html>
Inilah jsfiddle: https://jsfiddle.net/68vxqyak/1/
@Cmyker, solusi hebat untuk chart.js v2
Satu peningkatan kecil: Masuk akal untuk memeriksa id kanvas yang sesuai, lihat cuplikan yang dimodifikasi di bawah ini. Jika tidak, teks (yaitu 75%) juga ditampilkan di tengah jenis bagan lain dalam halaman.
Chart.pluginService.register({
beforeDraw: function(chart) {
if (chart.canvas.id === 'doghnutChart') {
let width = chart.chart.width,
height = chart.chart.outerRadius * 2,
ctx = chart.chart.ctx;
rewardImg.width = 40;
rewardImg.height = 40;
let imageX = Math.round((width - rewardImg.width) / 2),
imageY = (height - rewardImg.height ) / 2;
ctx.drawImage(rewardImg, imageX, imageY, 40, 40);
ctx.save();
}
}
});
Karena sebuah legenda (lihat: http://www.chartjs.org/docs/latest/configuration/legend.html ) memperbesar tinggi bagan, nilai untuk tinggi harus diperoleh dari radius.
Pertama-tama, pujian dalam memilih Chart.js! Saya menggunakannya di salah satu proyek saya saat ini dan saya sangat menyukainya - ini melakukan pekerjaan dengan sempurna.
Meskipun label / tooltips belum menjadi bagian dari pustaka, Anda mungkin ingin melihat tiga permintaan tarik berikut:
Dan, seperti yang disebutkan Cracker0dks , Chart.js digunakan canvas
untuk rendering sehingga Anda mungkin juga menerapkan tooltips Anda sendiri dengan berinteraksi dengannya secara langsung.
Semoga ini membantu.
Solusi Alesana bekerja dengan sangat baik untuk saya secara umum, tetapi seperti orang lain, saya ingin dapat menentukan di mana jeda baris terjadi. Saya membuat beberapa modifikasi sederhana untuk membungkus baris pada karakter '\ n', selama teks sudah dibungkus. Solusi yang lebih lengkap akan memaksa pembungkusan jika ada karakter '\ n' dalam teks, tetapi saya tidak punya waktu saat ini untuk membuatnya berfungsi dengan ukuran font. Perubahan juga berpusat sedikit lebih baik secara horizontal saat membungkus (menghindari spasi tambahan). Kode di bawah (saya belum bisa mengirim komentar).
Akan keren jika seseorang memasang plugin ini di GitHub ...
Chart.pluginService.register({
beforeDraw: function(chart) {
if (chart.config.options.elements.center) {
// Get ctx from string
var ctx = chart.chart.ctx;
// Get options from the center object in options
var centerConfig = chart.config.options.elements.center;
var fontStyle = centerConfig.fontStyle || 'Arial';
var txt = centerConfig.text;
var color = centerConfig.color || '#000';
var maxFontSize = centerConfig.maxFontSize || 75;
var sidePadding = centerConfig.sidePadding || 20;
var sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
// Start with a base font of 30px
ctx.font = "30px " + fontStyle;
// Get the width of the string and also the width of the element minus 10 to give it 5px side padding
var stringWidth = ctx.measureText(txt).width;
var elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
// Find out how much the font can grow in width.
var widthRatio = elementWidth / stringWidth;
var newFontSize = Math.floor(30 * widthRatio);
var elementHeight = (chart.innerRadius * 2);
// Pick a new font size so it will not be larger than the height of label.
var fontSizeToUse = Math.min(newFontSize, elementHeight, maxFontSize);
var minFontSize = centerConfig.minFontSize;
var lineHeight = centerConfig.lineHeight || 25;
var wrapText = false;
if (minFontSize === undefined) {
minFontSize = 20;
}
if (minFontSize && fontSizeToUse < minFontSize) {
fontSizeToUse = minFontSize;
wrapText = true;
}
// Set font settings to draw it correctly.
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
var centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
ctx.font = fontSizeToUse + "px " + fontStyle;
ctx.fillStyle = color;
if (!wrapText) {
ctx.fillText(txt, centerX, centerY);
return;
}
var lines = [];
var chunks = txt.split('\n');
for (var m = 0; m < chunks.length; m++) {
var words = chunks[m].split(' ');
var line;
// Break words up into multiple lines if necessary
for (var n = 0; n < words.length; n++) {
var testLine = (n == 0) ? words[n] : line + ' ' + words[n];
var metrics = ctx.measureText(testLine);
var testWidth = metrics.width;
if (testWidth > elementWidth && n > 0) {
lines.push(line);
line = words[n];
} else {
line = testLine;
}
}
lines.push(line);
}
// Move the center up depending on line height and number of lines
centerY -= ((lines.length-1) / 2) * lineHeight;
// All but last line
for (var n = 0; n < lines.length; n++) {
ctx.fillText(lines[n], centerX, centerY);
centerY += lineHeight;
}
}
}
});