Halka grafiğin içindeki Metin nasıl işlenir , ChartJs kullanıyorum .
Yanıtlar:
Kodu şu şekilde değiştirmeniz gerekir: chart.Doughnut.defaults
labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"
ve sonra işlevde drawPieSegments
ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);
Bu çekime bakın: https://github.com/nnnick/Chart.js/pull/35
işte aynı şeyi uygulayan bir keman http://jsfiddle.net/mayankcpdixit/6xV78/ .
Diğer yanıtların hiçbiri, metnin miktarına ve simidin boyutuna göre metni yeniden boyutlandırmaz. Burada, ortada herhangi bir miktarda metni dinamik olarak yerleştirmek için kullanabileceğiniz küçük bir komut dosyası var ve otomatik olarak yeniden boyutlandıracaktır.
Örnek: http://jsfiddle.net/kdvuxbtj/
Çörek için mükemmel boyuttaki çörek içinde herhangi bir miktarda metin alacaktır. Kenarlara dokunmaktan kaçınmak için yan dolguyu dairenin iç çapının yüzdesi olarak ayarlayabilirsiniz. Ayarlamazsanız, varsayılan olarak 20 olacaktır. Ayrıca renk, yazı tipi ve metin de siz olacak. Eklenti gerisini halleder.
Eklenti kodu, 30px'lik bir temel yazı tipi boyutuyla başlayacaktır. Oradan metnin genişliğini kontrol edecek ve onu dairenin yarıçapıyla karşılaştıracak ve daire / metin genişliği oranına göre yeniden boyutlandıracaktır.
Varsayılan minimum yazı tipi boyutu 20 pikseldir. Metin, minimum yazı tipi boyutunda sınırları aşarsa, metni kaydırır. Metni kaydırırken varsayılan satır yüksekliği 25 pikseldir, ancak bunu değiştirebilirsiniz. Varsayılan minimum yazı tipi boyutunu yanlış olarak ayarlarsanız, metin sonsuz derecede küçülür ve kaydırılmaz.
Ayrıca yeterli metin olmaması ve yazı çok büyük olması durumunda varsayılan maksimum yazı tipi boyutu 75 pikseldir.
Bu eklenti kodudur
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);
}
}
});
Ve grafik nesnenizde aşağıdaki seçenekleri kullanırsınız
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
}
}
}
Bu çözümde kullanılan matematikle ilgili yardım için @ Jenna Sloan'a kredi verin .
İşte temizlenmiş ve yukarıdaki çözümlerin birleşik örneği - duyarlı (pencereyi yeniden boyutlandırmayı deneyin), animasyonun kendi kendini hizalamasını destekler, araç ipuçlarını destekler
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>
GÜNCELLEME 17.06.16:
Aynı işlevsellik, ancak chart.js sürüm 2 için:
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
Herhangi bir fikir mi alıyorum ?
Normal CSS ve HTML ile oldukça kolay olduğundan bunu başarmak için chart.js kodunu değiştirmekten kaçınırım. İşte benim çözümüm:
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;
}
Çıktı şuna benzer:
Bu da benim tarafımda çalışıyor ...
<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>
@ Rap-2-h cevabına dayanarak, Burada gösterge tablosunda kullanım için Chart.js üzerinde halka grafikte metin kullanma kodu. Duyarlı seçenek için dinamik yazı tipi boyutuna sahiptir.
HTML:
<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>
Senaryo:
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);
}
});
});
Burada, pencereyi yeniden boyutlandırmak için örnek code.try. http://jsbin.com/wapono/13/edit
Duyarlı olmasını istiyorsanız, göreceli / mutlak konumlandırma ile css kullanabilirsiniz. Ayrıca çoklu hattı kolayca idare edebilir.
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>
Bu, Cmyker'ın Chart.js 2 güncellemesine dayanmaktadır (henüz yorum yapamadığım için başka bir yanıt olarak yayınlanmıştır)
Grafik yüksekliği bunu içermediğinden ortaya doğru şekilde hizalanmadığı için açıklama görüntülendiğinde Chrome'da metin hizalamayla ilgili bir sorun yaşadım. Bu, fontSize ve textY hesaplamalarında hesaba katılarak düzeltildi.
Sayfada bunlardan birden fazla olduğu için belirli bir değer yerine yöntemin içindeki yüzdeyi hesapladım. Varsayımlar, grafiğinizin yalnızca 2 değer içerdiğidir (aksi takdirde yüzdesi nedir? Ve ilkinin yüzdesini göstermek istediğinizdir. Bende de bir sürü başka grafik var, bu yüzden type = donut için bir kontrol yapıyorum. Yüzdeleri göstermek için sadece çörek kullanıyorum, bu yüzden benim için çalışıyor.
Metin rengi, nesnelerin hangi sırayla çalıştığına bağlı olarak biraz çarptı ve özlüyor gibi görünüyor, bu yüzden yeniden boyutlandırırken metnin renginin değişeceğini (bir durumda siyah ve birincil renk ve diğerinde ikincil renk ve beyaz arasında) bir sorunla karşılaştım. Mevcut dolgu stili ne olursa olsun "kaydederim", metni çizerim (birincil verilerin renginde) sonra eski dolgu stilini geri yüklerim. (Eski dolgu stilini korumak gerekli görünmüyor ama asla bilemezsiniz.)
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();
}
}
});
Mayankcpdixit kodunu onAnimationComplete
seçeneğe de yapıştırabilirsiniz :
// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
onAnimationComplete: function() {
ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
}
});
Metin, animasyondan sonra gösterilecek
save
yöntemi kullanarak olabilir
7 jQueryUI Slider ve ChartJs ile bir demo oluşturuyorum (içinde dinamik metinle)
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 ve @Ztuons Ch'nin cevabı, showTooltips
seçeneğin aktif olmasına izin vermez , ancak yapabileceğiniz şey canvas
grafiği oluşturanın arkasında ikinci bir nesne oluşturmak ve katmanlamaktır .
Önemli olan bölüm, div'lerde ve tuval nesnesinin kendisinin üst üste işlenmesi için gerekli olan stildir.
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>
İşte jsfiddle: https://jsfiddle.net/68vxqyak/1/
@Cmyker, chart.js v2 için harika çözüm
Küçük bir geliştirme: Uygun tuval kimliğini kontrol etmek mantıklıdır, aşağıdaki değiştirilmiş parçacığa bakın. Aksi takdirde metin (yani% 75), sayfa içindeki diğer grafik türlerinin ortasında da oluşturulur.
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();
}
}
});
Bir açıklama (bkz: http://www.chartjs.org/docs/latest/configuration/legend.html ) grafiğin yüksekliğini büyüttüğü için, yükseklik değeri yarıçap ile elde edilmelidir.
Alesana'nın çözümü genel olarak benim için çok iyi çalışıyor, ancak diğerleri gibi ben de satır sonlarının nerede oluştuğunu belirleyebilmek istedim. Metin zaten kaydırılmış olduğu sürece satırları '\ n' karakterlerine kaydırmak için bazı basit değişiklikler yaptım . Daha eksiksiz bir çözüm, metinde herhangi bir "\ n" karakteri varsa kaydırmayı zorlar, ancak şu anda bunu yazı tipi boyutlandırma ile çalıştıracak vaktim yok. Değişiklik ayrıca, sarma sırasında yatay olarak biraz daha iyi ortalanır (arkadaki boşlukları önler). Kod aşağıda (henüz yorum gönderemiyorum).
Birisi bu eklentiyi GitHub'a koysa harika olur ...
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;
}
}
}
});
Her şeyden önce, Chart.js'yi seçtiğiniz için tebrikler! Bunu mevcut projelerimden birinde kullanıyorum ve kesinlikle seviyorum - işi mükemmel yapıyor.
Etiketler / araç ipuçları henüz kitaplığın bir parçası olmasa da, şu üç çekme isteğine bir göz atmak isteyebilirsiniz:
Ve, Cracker0dks'in bahsettiği gibi, Chart.js canvas
oluşturma için kullanır , bu yüzden doğrudan onunla etkileşim kurarak kendi araç ipuçlarınızı uygulayabilirsiniz.
Bu yardımcı olur umarım.