Chart.js를 사용하여 도넛 차트 내부에 텍스트를 추가하는 방법은 무엇입니까?


답변:


38

다음과 같이 코드를 수정해야합니다. 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

179

다른 답변은 텍스트 양과 도넛 크기에 따라 텍스트 크기를 조정하지 않습니다. 다음은 중간에 임의의 양의 텍스트를 동적으로 배치하는 데 사용할 수있는 작은 스크립트이며 자동으로 크기가 조정됩니다.

예 : http://jsfiddle.net/kdvuxbtj/

중간에 동적 텍스트가있는 도넛

도넛에 딱 맞는 크기의 도넛에 텍스트 양이 필요합니다. 가장자리에 닿지 않도록 원 안쪽 지름의 백분율로 측면 패딩을 설정할 수 있습니다. 설정하지 않으면 기본값은 20입니다. 색상, 글꼴 및 텍스트도 있습니다. 플러그인이 나머지를 처리합니다.

플러그인 코드는 30px의 기본 글꼴 크기로 시작합니다. 거기에서 텍스트의 너비를 확인하고 원의 반경과 비교하고 원 / 텍스트 너비 비율에 따라 크기를 조정합니다.

기본 최소 글꼴 크기는 20px입니다. 텍스트가 최소 글꼴 크기에서 경계를 초과하면 텍스트를 래핑합니다. 텍스트 줄 바꿈시 기본 줄 높이는 25px이지만 변경할 수 있습니다. 기본 최소 글꼴 크기를 false로 설정하면 텍스트가 무한히 작아지고 줄 바꿈되지 않습니다.

또한 텍스트가 충분하지 않고 글자가 너무 큰 경우 기본 최대 글꼴 크기는 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

4
텍스트를 여러 줄로 분할 할 수 있습니까? 내 텍스트에 6 개의 단어가 있고 컷 아웃 경계 사이로 넘쳐납니다
Quanda

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>


3
나는 Uncaught TypeError: Cannot read property 'extend' of undefined어떤 아이디어를 얻었 습니까?
Max Rose-Collins

2
또한 ctx.fillStyle = 'black'을 사용하여 텍스트 색상을 변경할 수 있습니다.
Adrian Lopez

이 차트는 새로운 데이터 PARAMS 제공함으로써 갱신되는 경우 또 다시 텍스트를 통해 작성에 유지
techie_28을

이에 대한 해결책을 찾았습니까?
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
반응 형 방식을 사용하여 저에게는 작동하지 않으므로 고정 값을 사용할 수 없습니다. :(
마사

2
@Massa는 다양한 해상도에 대한 미디어 쿼리를 사용해 보셨습니까? 또는 px 대신 %를 사용하도록 작성한 CSS를 수정합니까?
Mattias 2015

2
@Mattias 이것은 좋은 솔루션 이었지만 차트를 PNG로 다운로드 할 때 중앙 텍스트가 내보내지지 않습니다.
techie_28

1
@ techie_28 유효한 포인트, 질문에 내보내기에 대해 전혀 언급하지 않았기 때문에 고려하지 않았습니다.
Mattias

21

이것은 또한 내 끝에서 작동합니다 ...

<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 2016-12-05

넌 내 친구 야! 나는 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);
  }
 });
});

여기 샘플 code.try 창 크기를 조정하십시오. http://jsbin.com/wapono/13/edit


1
응답 성이 필요한 경우 (내 경우) 허용되는 답변이어야합니다.
Greg Blass 2015

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>

아름다운 솔루션 :
만자

Super Work bro you made my day
DVP SmartCreators Inc 우리는

8

이것은 Chart.js 2에 대한 Cmyker의 업데이트를 기반으로합니다. (아직 댓글을 달 수 없으므로 다른 답변으로 게시 됨)

차트 높이에 이것을 포함하지 않아서 중간에 올바르게 정렬되지 않았기 때문에 범례가 표시 될 때 Chrome에서 텍스트 정렬에 문제가있었습니다. fontSize 및 textY 계산에서이를 고려하여이 문제를 해결했습니다.

페이지에 여러 개가 있으므로 설정된 값이 아닌 메서드 내부에서 백분율을 계산했습니다. 차트에는 2 개의 값만 있다고 가정합니다 (그렇지 않으면 백분율은 무엇입니까? 첫 번째는 백분율을 표시하려는 차트입니다. 다른 차트도 여러 개 있으므로 유형 = 도넛을 확인합니다. 나는 도넛을 사용하여 백분율을 표시하기 때문에 나를 위해 작동합니다.

텍스트 색상은 어떤 순서로 실행되는지 등에 따라 약간 맞고 놓치는 것처럼 보이므로 크기를 조정할 때 텍스트 색상이 변경되는 문제가 발생했습니다 (한 경우에는 검은 색과 기본 색상, 다른 경우에는 보조 색상과 흰색). 기존 채우기 스타일이 무엇이든 "저장"하고 텍스트 (기본 데이터 색상)를 그린 다음 이전 채우기 스타일을 복원합니다. (이전 채우기 스타일을 유지하는 것은 필요하지 않은 것 같지만 알 수 없습니다.)

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

onAnimationComplete옵션에 mayankcpdixit의 코드를 붙여 넣을 수도 있습니다.

// ...
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 및 ChartJ (동적 텍스트 포함)로 데모를 만듭니다.

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차트를 렌더링하는 개체 뒤에 두 번째 개체를 만들고 레이어를 만드는 것입니다 .

중요한 부분은 div와 캔버스 객체 자체에 필요한 스타일링으로 서로 위에 렌더링되도록하는 것입니다.

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를위한 훌륭한 솔루션

약간의 개선 사항 : 적절한 캔버스 ID를 확인하는 것이 좋습니다. 아래 수정 된 스 니펫을 참조하세요. 그렇지 않으면 텍스트 (예 : 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 참조 )는 차트 높이를 확대하므로 높이 값은 반경으로 구해야합니다.


0

우선, Chart.js 선택에 대한 찬사! 현재 프로젝트 중 하나에서 사용하고 있으며 정말 마음에 듭니다. 완벽하게 작동합니다.

레이블 / 툴팁은 아직 라이브러리의 일부가 아니지만 다음 세 가지 풀 요청을 살펴볼 수 있습니다.

그리고 Cracker0dks가 언급했듯이 Chart.js는canvas 렌더링에 하므로 직접 상호 작용하여 자신의 툴팁을 구현할 수도 있습니다.

도움이 되었기를 바랍니다.


0

Alesana의 솔루션은 일반적으로 저에게 매우 잘 작동하지만 다른 사람들과 마찬가지로 줄 바꿈이 발생하는 위치를 지정할 수 있기를 원했습니다. 텍스트가 이미 줄 바꿈되어있는 한 '\ n'문자로 줄 바꿈하기 위해 몇 가지 간단한 수정을했습니다 . 더 완벽한 솔루션은 텍스트에 '\ n'문자가있는 경우 줄 바꿈을 강제 할 수 있지만 글꼴 크기 조정으로 작업 할 시간이 없습니다. 변경 사항은 또한 래핑 할 때 수평 중심에 약간 더 잘 맞춰집니다 (후행 공백 방지). 코드는 다음과 같습니다 (아직 코멘트를 게시 할 수 없습니다).

누군가이 플러그인을 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;
      }
    }
  }
});
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.