Ale*_*ana 152

没有其他答案根据文本的数量和甜甜圈的大小调整文本的大小.这是一个小脚本,您可以使用它在中间动态放置任意数量的文本,它将自动调整大小. http://jsfiddle.net/nkzyx50o/

甜甜圈与中间的动态文本

它将需要甜甜圈大小的任何数量的文本完美的甜甜圈.为避免接触边缘,您可以将侧边填充设置为圆内部直径的百分比.如果不设置它,它将默认为20.您还可以使用颜色,字体和文本.该插件负责其余部分.

插件代码将以30px的基本字体大小开头.从那里它将检查文本的宽度并将其与圆的半径进行比较,并根据圆/文本宽度比调整其大小.

这是插件代码

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

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

      //Draw text in center
      ctx.fillText(txt, centerX, centerY);
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

并在图表对象中使用以下选项

options: {
  elements: {
      center: {
      text: 'Desktop',
      color: '#36A2EB', //Default black
      fontStyle: 'Helvetica', //Default Arial
      sidePadding: 15 //Default 20 (as a percentage)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

感谢@Jenna斯隆与在此解决方案中使用的数学题.

  • 为了在 ChartJs V3 中实现此功能,您需要使用“chart._metasets[chart._metasets.length-1].data[0].innerRadius”更新对“chart.innerRadius”的所有引用,并将注册更新为“ Chart.register({id:'doughnut-centertext',beforeDraw: function(chart){ ... }})`. 更新的小提琴可以在这里找到:http://jsfiddle.net/danieljoeblack/feq1tpgm/6/ (8认同)
  • 我更新了你的小提琴并添加了最大字体大小:http://jsfiddle.net/nkzyx50o/3059/ (4认同)
  • 可以将文本拆分为多行吗?我的文字有 6 个单词,并且溢出到了剪切的边界之间 (4认同)
  • 很棒!当图例位于右侧或左侧时,大多数其他选项都会中断。 (2认同)
  • 真棒解决方案! (2认同)
  • 很好的答案。实际上是最好的一个。如果您使用的是 webpack,只需导入 Chart 对象并在其上注册此插件即可。 (2认同)
  • 谢谢您,这也适用于我,但是如何添加多行文本? (2认同)
  • 是否可以动态更改文本?我正在使用 Angular,为了检测更改,我必须提供一个全新的 ChartOptions 对象,它也会触发图表动画。因此,如果我想动态刷新中心的文本,我似乎无法在数据更改时显示图表动画。有什么办法解决这个问题吗? (2认同)

Cmy*_*ker 53

这里是清理和上述解决方案的组合示例 - 响应(尝试调整窗口大小),支持动画自对齐,支持工具提示

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
});
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

更新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
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
Run Code Online (Sandbox Code Playgroud)

  • 我得到`Uncaught TypeError:无法读取未定义的属性'extend'任何想法? (3认同)
  • 此外,您可以使用ctx.fillStyle ='black'更改文本颜色; (2认同)

Mat*_*ias 35

我会避免修改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>
Run Code Online (Sandbox Code Playgroud)

CSS:

.donut-inner {
   margin-top: -100px;
   margin-bottom: 100px;
}
.donut-inner h5 {
   margin-bottom: 5px;
   margin-top: 0;
}
.donut-inner span {
   font-size: 12px;
}
Run Code Online (Sandbox Code Playgroud)

输出如下所示:

在此输入图像描述

  • 为什么不?只需将@media-queries添加到您的课程中即可. (4认同)
  • 它不适用于我,我使用响应方式,所以我canot使用固定值.:( (2认同)
  • @Massa您是否尝试过对各种分辨率使用媒体查询?或者修改我写的css使用%而不是px? (2认同)
  • @Mattias这是一个很好的解决方案,但是当图表作为PNG下载时,中心文本不会被导出. (2认同)

may*_*xit 29

您必须修改代码,如:in chart.Doughnut.defaults

labelFontFamily : "Arial",
labelFontStyle : "normal",
labelFontSize : 24,
labelFontColor : "#666"
Run Code Online (Sandbox Code Playgroud)

然后在功能上 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/实现相同的.

  • 无论如何不修改chart.js源代码? (5认同)
  • 有没有其他人找不到这个drawPieSegments功能? (2认同)
  • 值得一提的是它不适用于v2。使用随附的jsfiddle代码以易于使用 (2认同)

小智 16

这也是我最终的工作......

<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" />
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 我使用了你的解决方案,因为它是最快的解决方案,它可以完成它的工作.谢谢! (4认同)

Ztu*_* Ch 11

基于@ rap-2-h的答案,这里是使用Chart.js上的圆环图上的文字在仪表板中使用的代码.它具有动态字体大小的响应选项.

HTML:

<div>text
<canvas id="chart-area" width="300" height="300" style="border:1px solid"/><div>
Run Code Online (Sandbox Code Playgroud)

脚本:

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);
  }
 });
});
Run Code Online (Sandbox Code Playgroud)

这里是示例code.try来调整窗口大小.http://jsbin.com/wapono/13/edit

  • 在需要响应能力的情况下(我的情况),这应该是公认的答案。 (2认同)
  • 如果您有工具提示,则文本在悬停时消失. (2认同)

Ror*_*ory 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();
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

var data = {
  labels: ["Red","Blue"],
  datasets: [
    {
      data: [300, 50],
      backgroundColor: ["#FF6384","#36A2EB"],
    }]
};

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

var myChart = new Chart(document.getElementById('myChart'), {
  type: 'doughnut',
  data: data,
  options: {
  	responsive: true,
    legend: {
      display: true
    }
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
<canvas id="myChart"></canvas>
Run Code Online (Sandbox Code Playgroud)


rap*_*2-h 7

您还可以在onAnimationComplete选项中粘贴mayankcpdixit的代码:

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

动画后将显示文字

  • 好,但文字在悬停时消失 (6认同)

sgr*_*lon 6

我用7 jQueryUI Slider和ChartJs创建了一个demo(里面有动态文本)

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
});
Run Code Online (Sandbox Code Playgroud)

JSFIDDLE中的演示

在此输入图像描述


Day*_*yze 6

如果希望响应,可以将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>
Run Code Online (Sandbox Code Playgroud)