วิธีเพิ่มข้อความในแผนภูมิโดนัทโดยใช้ Chart.js


คำตอบ:


40

คุณต้องแก้ไขรหัสเช่น: ใน chart.Doughnut.defaults

labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"

แล้วในฟังก์ชัน drawPieSegments

ctx.fillText(data[0].value + "%", width/2 - 20, width/2, 200);

ดูการดึงนี้: https://github.com/nnnick/Chart.js/pull/35

นี่คือซอhttp://jsfiddle.net/mayankcpdixit/6xV78/การใช้งานแบบเดียวกัน


2
มีใครอีกบ้างที่ไม่พบฟังก์ชัน drawPieSegments นี้?
Yulian

2
มูลค่าการกล่าวขวัญว่ามันใช้ไม่ได้กับ v2 ใช้รหัส jsfiddle ที่รวมไว้เพื่อความสะดวกในการใช้งาน
Alwin Kesler

1
จะเพิ่ม% ในบรรทัดใหม่ได้อย่างไร? ได้รับการสนับสนุนหรือไม่
user7334203

1
ยังคงเป็นวิธีแก้ปัญหา?
ACB

@ ArunC.B - เลื่อนลง
ashleedawg

183

ไม่มีคำตอบอื่น ๆ ปรับขนาดข้อความตามจำนวนข้อความและขนาดของโดนัท นี่คือสคริปต์ขนาดเล็กที่คุณสามารถใช้เพื่อวางข้อความจำนวนเท่าใดก็ได้ที่อยู่ตรงกลางแบบไดนามิกและจะปรับขนาดโดยอัตโนมัติ

ตัวอย่าง: http://jsfiddle.net/kdvuxbtj/

โดนัทที่มีข้อความแบบไดนามิกอยู่ตรงกลาง

จะใช้ข้อความจำนวนเท่าใดก็ได้ในขนาดโดนัทที่พอดีกับโดนัท เพื่อหลีกเลี่ยงการสัมผัสขอบคุณสามารถกำหนดช่องว่างด้านข้างเป็นเปอร์เซ็นต์ของเส้นผ่านศูนย์กลางด้านในของวงกลม หากคุณไม่ได้ตั้งค่าไว้ค่าเริ่มต้นจะเป็น 20 นอกจากนี้คุณยังกำหนดสีแบบอักษรและข้อความด้วย ปลั๊กอินจะดูแลส่วนที่เหลือ

โค้ดปลั๊กอินจะเริ่มต้นด้วยขนาดฟอนต์พื้นฐาน 30px จากนั้นจะตรวจสอบความกว้างของข้อความและเปรียบเทียบกับรัศมีของวงกลมและปรับขนาดตามอัตราส่วนความกว้างของวงกลม / ข้อความ

มีขนาดตัวอักษรขั้นต่ำเริ่มต้นที่ 20px หากข้อความเกินขอบเขตตามขนาดตัวอักษรขั้นต่ำข้อความนั้นจะตัดข้อความ ความสูงของบรรทัดเริ่มต้นเมื่อตัดข้อความคือ 25px แต่คุณสามารถเปลี่ยนแปลงได้ หากคุณตั้งค่าขนาดแบบอักษรขั้นต่ำเริ่มต้นเป็นเท็จข้อความจะเล็กลงเรื่อย ๆ และจะไม่ถูกตัด

นอกจากนี้ยังมีขนาดตัวอักษรสูงสุดเริ่มต้นที่ 75px ในกรณีที่มีข้อความไม่เพียงพอและตัวอักษรจะใหญ่เกินไป

นี่คือรหัสปลั๊กอิน

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);
    }
  }
});

และคุณใช้ตัวเลือกต่อไปนี้ในออบเจ็กต์แผนภูมิของคุณ

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
    }
  }
}

ให้เครดิตกับ@Jenna Sloanสำหรับความช่วยเหลือเกี่ยวกับคณิตศาสตร์ที่ใช้ในการแก้ปัญหานี้


5
ใช้งานได้ดี! ตัวเลือกอื่น ๆ ส่วนใหญ่จะพังเมื่อคำอธิบายแผนภูมิอยู่ทางขวาหรือซ้าย
louisav

2
ทางออกที่ยอดเยี่ยม!
JustLooking

3
ฉันอัปเดตซอของคุณและเพิ่มขนาดตัวอักษรสูงสุด: jsfiddle.net/nkzyx50o/3059
Felix Geenen

4
สามารถแบ่งข้อความออกเป็นหลายบรรทัดได้หรือไม่? ข้อความของฉันมี 6 คำและมันล้นอยู่ระหว่างขอบของช่อง
Eric Furspan

2
ขอบคุณสิ่งนี้ใช้ได้กับฉันเช่นกัน แต่ฉันจะเพิ่มข้อความหลายบรรทัดได้อย่างไร
Ashutosh Shrestha

54

นี่คือตัวอย่างการทำความสะอาดและรวมของโซลูชันข้างต้น - ตอบสนอง (พยายามปรับขนาดหน้าต่าง) รองรับการจัดแนวภาพเคลื่อนไหวด้วยตนเอง

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>

อัพเดท 17.06.16:

ฟังก์ชันเดียวกัน แต่สำหรับ chart.js เวอร์ชัน 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>


4
ฉันได้รับUncaught TypeError: Cannot read property 'extend' of undefinedความคิดใด ๆ ?
Max Rose-Collins

2
นอกจากนี้คุณสามารถเปลี่ยนสีข้อความโดยใช้ ctx.fillStyle = 'black';
Adrian Lopez

สิ่งนี้จะยังคงเขียนทับข้อความซ้ำแล้วซ้ำเล่าหากแผนภูมิถูกรีเฟรชโดยการให้
พารามิเตอร์

คุณคิดหาทางออกแล้วหรือยัง?
Cmyker

@Cmyker โซลูชัน CSS / HTML สามารถช่วยได้ แต่จะไม่ส่งออกข้อความกลางเมื่อแผนภูมิถูกส่งออกเป็น PNG มีแนวคิดในการแก้ไขปัญหานี้หรือไม่นี่เป็นวิธีแก้ปัญหาที่สมบูรณ์เพียง แต่ไม่ได้ล้างพื้นที่ตรงกลางเมื่อรีเฟรชแผนภูมิ .
techie_28

38

ฉันจะหลีกเลี่ยงการแก้ไขโค้ด chart.js เพื่อทำสิ่งนี้ให้สำเร็จเพราะมันค่อนข้างง่ายด้วย CSS และ HTML ปกติ นี่คือวิธีแก้ปัญหาของฉัน:

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;
}

ผลลัพธ์มีลักษณะดังนี้:

ป้อนคำอธิบายภาพที่นี่


5
ทำไมจะไม่ล่ะ? เพียงเพิ่ม @ media-queries ในชั้นเรียนของคุณ
Mattias

2
มันไม่ได้ผลสำหรับฉันฉันใช้วิธีตอบสนองดังนั้นฉันจึงไม่สามารถใช้ค่าคงที่ :(
Massa

2
@Massa คุณได้ลองใช้แบบสอบถามสื่อสำหรับความละเอียดต่างๆแล้วหรือยัง? หรือแก้ไข css ที่ฉันเขียนให้ใช้% แทน px?
Mattias

2
@Mattias นี่เป็นทางออกที่ดี แต่ข้อความกลางจะไม่ถูกส่งออกเมื่อดาวน์โหลดแผนภูมิเป็น PNG
techie_28

1
@ techie_28 จุดที่ถูกต้องไม่ได้นำมาพิจารณาเนื่องจากคำถามไม่ได้กล่าวถึงการส่งออกเลย
Mattias

22

สิ่งนี้ก็ใช้ได้เช่นกันในตอนท้ายของฉัน ...

<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>

ป้อนคำอธิบายภาพที่นี่


5
ฉันใช้วิธีแก้ปัญหาของคุณเพราะเป็นวิธีที่เร็วที่สุดและทำงานได้ดี ขอบคุณ!
MDT

@Amrik Singh นี่เป็นทางออกที่ดี แต่ข้อความตรงกลางจะไม่ถูกส่งออกหากดาวน์โหลดแผนภูมิเป็นภาพ PNG
techie_28

ทางออกที่ดีไม่ต้องกังวลมากนัก
Shashank

คุณคือเพื่อนของฉัน! ฉันหาคำตอบไม่ได้ใน angularjs และไม่เคยทำแบบนี้เลย น่าอัศจรรย์.
Nomi Ali

1
การแก้ไขที่น่ารักรวดเร็วและสะอาด
Khaleel

11

อิงตามคำตอบ @ rap-2-h นี่คือรหัสสำหรับใช้ข้อความบนแผนภูมิโดนัทบน Chart.js สำหรับใช้ในแดชบอร์ดเช่น. มีขนาดตัวอักษรแบบไดนามิกสำหรับตัวเลือกที่ตอบสนอง

HTML:

<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>

สคริปต์:

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);
  }
 });
});

นี่คือโค้ดตัวอย่างลองปรับขนาดหน้าต่าง http://jsbin.com/wapono/13/edit


1
นี่ควรเป็นคำตอบที่ยอมรับได้ในกรณีที่ต้องการการตอบสนอง (กรณีของฉัน)
Greg Blass

2
หากคุณมีคำแนะนำเครื่องมือข้อความจะหายไปเมื่อวางเมาส์เหนือ
Yulian

ข้อผิดพลาด"jQuery.Deferred ข้อยกเว้น: ไม่ได้กำหนดแผนภูมิ"
Kiquenet

11

คุณสามารถใช้ css กับการวางตำแหน่งสัมพัทธ์ / สัมบูรณ์หากคุณต้องการให้ตอบสนอง นอกจากนี้ยังสามารถจัดการหลายบรรทัดได้อย่างง่ายดาย

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>

ทางออกที่สวยงาม :)
Manza

Super Work ครับคุณทำให้วันของฉัน
DVP SmartCreators Inc เราทำใน

8

สิ่งนี้อ้างอิงจากการอัปเดตของ Cmyker สำหรับ Chart.js 2 (โพสต์เป็นคำตอบอื่นเนื่องจากฉันยังไม่สามารถแสดงความคิดเห็นได้)

ฉันมีปัญหากับการจัดแนวข้อความบน Chrome เมื่อคำอธิบายแผนภูมิแสดงขึ้นเนื่องจากความสูงของแผนภูมิไม่รวมสิ่งนี้จึงไม่ได้จัดแนวตรงกลางอย่างถูกต้อง แก้ไขสิ่งนี้โดยการบัญชีสำหรับสิ่งนี้ในการคำนวณ fontSize และ textY

ฉันคำนวณเปอร์เซ็นต์ภายในวิธีการแทนที่จะเป็นค่าที่ตั้งไว้เนื่องจากฉันมีหลายค่าในหน้านี้ สมมติฐานก็คือแผนภูมิของคุณมีเพียง 2 ค่าเท่านั้น (มิฉะนั้นเปอร์เซ็นต์คืออะไรและค่าแรกคือค่าที่คุณต้องการแสดงเปอร์เซ็นต์สำหรับฉันมีแผนภูมิอื่น ๆ อีกจำนวนมากดังนั้นฉันจึงตรวจสอบ type = donut ฉันใช้โดนัทเพื่อแสดงเปอร์เซ็นต์เท่านั้นจึงเหมาะกับฉัน

สีข้อความดูเหมือนจะตีและพลาดไปเล็กน้อยขึ้นอยู่กับสิ่งที่สั่งซื้อใน ฯลฯ ดังนั้นฉันจึงประสบปัญหาเมื่อปรับขนาดว่าข้อความจะเปลี่ยนสี (ระหว่างสีดำกับสีหลักในกรณีหนึ่งและสีรองและสีขาวในอีกกรณีหนึ่ง) ฉัน "บันทึก" ไม่ว่ารูปแบบการเติมที่มีอยู่จะเป็นอย่างไรวาดข้อความ (เป็นสีของข้อมูลหลัก) จากนั้นเรียกคืนรูปแบบการเติมแบบเก่า (การรักษารูปแบบการเติมแบบเก่าดูเหมือนจะไม่จำเป็น แต่คุณไม่มีทางรู้)

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();
    }
  }
});


7

คุณยังสามารถวางโค้ดของ mayankcpdixit ในonAnimationCompleteตัวเลือก:

// ...
var myDoughnutChart = new Chart(ctx).Doughnut(data, {
    onAnimationComplete: function() {
        ctx.fillText(data[0].value + "%", 100 - 20, 100, 200);
    }
});

ข้อความจะแสดงหลังภาพเคลื่อนไหว


6
ดี แต่ข้อความหายไปเมื่อเลื่อน
rnaud

1
ถูกต้องข้อความหายไปเมื่อโฮเวอร์ ... :( จะดีมากที่ข้อความไม่หายไปมีความคิดอย่างไรขอบคุณ
MDT

@MDT @maud อาจใช้saveวิธีการ
techie_28

7

ฉันสร้างการสาธิตด้วย 7 jQueryUI Slider และ ChartJs (พร้อมข้อความไดนามิกภายใน)

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
});

สาธิตใน JSFIDDLE

ป้อนคำอธิบายภาพที่นี่


3

คำตอบของ @ rap-2-h และ @Ztuons Ch ไม่อนุญาตให้ใช้งานshowTooltipsตัวเลือกได้ แต่สิ่งที่คุณทำได้คือสร้างและวางเลเยอร์canvasวัตถุที่สองไว้ด้านหลังวัตถุที่แสดงผลแผนภูมิ

ส่วนที่สำคัญคือการจัดแต่งทรงผมที่จำเป็นใน divs และสำหรับออบเจ็กต์ canvas เองเพื่อให้แสดงผลทับกัน

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>

นี่คือ jsfiddle: https://jsfiddle.net/68vxqyak/1/


1

@Cmyker ทางออกที่ยอดเยี่ยมสำหรับ chart.js v2.0

การปรับปรุงเล็กน้อย: ควรตรวจสอบรหัสพื้นที่ที่เหมาะสมดูตัวอย่างข้อมูลที่แก้ไขด้านล่าง มิฉะนั้นข้อความ (เช่น 75%) จะแสดงอยู่ตรงกลางของแผนภูมิประเภทอื่น ๆ ในหน้าด้วย

  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();
      }
    }
  });

เนื่องจากคำอธิบายแผนภูมิ (ดู: http://www.chartjs.org/docs/latest/configuration/legend.html ) ขยายความสูงของแผนภูมิจึงควรหาค่าความสูงตามรัศมี


1

วิธีแก้ปัญหาของ Alesana ทำงานได้ดีมากสำหรับฉันโดยทั่วไป แต่ก็เหมือนกับคนอื่น ๆ ฉันต้องการระบุตำแหน่งที่เกิดการแบ่งบรรทัด ฉันทำการแก้ไขง่ายๆเพื่อตัดบรรทัดที่อักขระ "\ n" ตราบใดที่ข้อความนั้นถูกรวมไว้แล้ว โซลูชันที่สมบูรณ์กว่านี้จะบังคับให้มีการตัดหากมีอักขระ "\ n" ในข้อความ แต่ฉันไม่มีเวลาในขณะนี้เพื่อให้ใช้งานได้กับการปรับขนาดแบบอักษร การเปลี่ยนแปลงนี้ยังเน้นแนวนอนที่ดีขึ้นเล็กน้อยเมื่อทำการตัด (หลีกเลี่ยงช่องว่างต่อท้าย) โค้ดด้านล่าง (ฉันยังโพสต์ความคิดเห็นไม่ได้)

คงจะดีไม่น้อยถ้ามีคนเอา Plug-in นี้มาใส่ 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;
      }
    }
  }
});

0

ก่อนอื่นความรุ่งโรจน์ในการเลือก Chart.js! ฉันใช้มันในโครงการปัจจุบันของฉันและฉันชอบมันมาก - มันทำงานได้อย่างสมบูรณ์แบบ

แม้ว่าป้ายกำกับ / คำแนะนำเครื่องมือจะยังไม่ได้เป็นส่วนหนึ่งของไลบรารี แต่คุณอาจต้องการดูคำขอดึงสามรายการนี้:

และตามที่Cracker0dksกล่าวไว้ Chart.js ใช้canvasสำหรับการแสดงผลดังนั้นคุณสามารถใช้คำแนะนำเครื่องมือของคุณเองได้เช่นกันโดยการโต้ตอบกับมันโดยตรง

หวังว่านี่จะช่วยได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.