【问题标题】:How to add text inside the doughnut chart using Chart.js?如何使用 Chart.js 在圆环图中添加文本?
【发布时间】:2014-01-24 20:26:15
【问题描述】:

如何在圆环图中渲染文本,我用的是ChartJs。

【问题讨论】:

    标签: javascript chart.js


    【解决方案1】:

    我知道答案是旧的,但也许有人会派上用场。 最简单的方法是使用onAnimationProgress 事件。

    像这样。

    var myDoughnutChart = new Chart(ctx).Doughnut(data, {
        onAnimationProgress: function() {
            
          const dataset = this.data.datasets[0];
          const model = dataset._meta[Object.keys(dataset._meta)[0]]?.data[0]?._model;
          if (!model) { return; }
          // model.x and model.y is the center of the chart
          this.ctx.fillText('00%', model.x, model.y); 
        }
    });
    

    【讨论】:

      【解决方案2】:

      Alesana 的解决方案总体上对我来说非常有效,但和其他人一样,我希望能够指定换行符发生的位置。我做了一些简单的修改,在 '\n' 字符处换行,只要文本已经被换行。如果有任何 '\n' 字符,更完整的解决方案将强制换行文本,但我现在没有时间来调整字体大小。换行时,更改的水平中心也更好一些(避免尾随空格)。代码如下(我还不能发布 cmets)。

      如果有人把这个插件放到 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;
            }
          }
        }
      });
      

      【讨论】:

        【解决方案3】:

        其他答案都没有根据文本数量和甜甜圈的大小调整文本大小。这是一个小脚本,您可以使用它在中间动态放置任意数量的文本,它会自动调整大小。

        示例: http://jsfiddle.net/kdvuxbtj/

        它可以在甜甜圈中包含任何数量的文本,大小都非常适合甜甜圈。为避免接触边缘,您可以将侧边距设置为圆内部直径的百分比。如果你不设置它,它将默认为 20。你也可以设置颜色、字体和文本。该插件负责其余的工作。

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

        它的默认最小字体大小为 20 像素。如果文本超出最小字体大小的范围,它将换行。环绕文本时的默认行高为 25px,但您可以更改它。如果将默认最小字体大小设置为 false,则文本将无限小且不会换行。

        它还有一个默认的最大字体大小为 75 像素,以防文本不够,字体太大。

        这是插件代码

        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 以帮助解决此解决方案中使用的数学问题。

        【讨论】:

        • 效果很好!当图例在右侧或左侧时,大多数其他选项都会中断。
        • 很棒的解决方案!
        • 优秀的答案。实际上最好的一个。如果您使用的是 webpack,只需导入 Chart 对象并在其上注册此插件即可。
        • 我更新了你的小提琴并添加了最大字体大小:jsfiddle.net/nkzyx50o/3059
        • 可以将文本拆分成多行吗?我的文字有 6 个单词,并且在切口边界之间溢出
        【解决方案4】:

        这也适用于我...

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

        【讨论】:

        • 我使用了您的解决方案,因为它是最快的解决方案,并且可以完成工作。谢谢!
        • @Amrik Singh 这确实是一个很好的解决方案,但是如果将图表下载为 PNG 图像,则中心文本不会被导出。
        • 不错的解决方案,不需要太多麻烦。
        • 你是我的兄弟!我无法在 angularjs 中找到解决方案,而且从来没有这样做过。太棒了。
        • 可爱、快速、干净的修复
        【解决方案5】:

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

        DEMO IN JSFIDDLE

        【讨论】:

          【解决方案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>
          

          【讨论】:

          • 漂亮的解决方案:)
          • 超级工作兄弟,你让我开心
          • 从2021 开始,使用v3 的chart.js(测试版),这对我来说是开箱即用的
          • 我认为它也适用于移动设备(因为它不使用任何固定值)。至少使用谷歌浏览器和移动模拟是有效的
          【解决方案7】:

          @Cmyker,chart.js v2 的绝佳解决方案

          一个小改进:检查适当的画布 id 是有意义的,请参阅下面修改后的 sn-p。否则,文本(即 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)放大了图表高度,因此高度的值应通过半径获得。

          【讨论】:

            【解决方案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();
                }
              }
            });
            

            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
                }
              }
            });
            <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.bundle.js"></script>
            <canvas id="myChart"></canvas>

            【讨论】:

              【解决方案9】:

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

              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>

              【讨论】:

              • 我得到Uncaught TypeError: Cannot read property 'extend' of undefined 任何想法?
              • 另外,您可以使用 ctx.fillStyle = 'black'; 更改文本颜色;
              • 如果通过提供新的数据参数刷新图表,这会一次又一次地覆盖文本
              • 你找到解决办法了吗?
              • @Cmyker CSS/HTML 解决方案可能会有所帮助,但是当图表导出为 PNG 时,它不会导出中心文本。有什么想法可以纠正这个问题吗?这是一个完整的解决方案,只是不清楚图表刷新时的中心区域。
              【解决方案10】:

              我会避免修改 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;
              }
              

              输出如下:

              【讨论】:

              • 为什么不呢?只需将@media-queries 添加到您的课程中即可。
              • 它对我不起作用,我使用的是响应式方式,所以我不能使用固定值。 :(
              • @Massa 您是否尝试过针对各种分辨率使用媒体查询?还是修改我写的css用%代替px?
              • @Mattias 这是一个不错的解决方案,但是当图表下载为 PNG 时,中心文本不会被导出。
              • @techie_28 有效点,没有考虑到这一点,因为问题根本没有提到导出。
              【解决方案11】:

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

              【讨论】:

                【解决方案12】:

                基于@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

                【讨论】:

                • 如果需要响应(我的情况),这应该是公认的答案。
                • 如果您有工具提示,则文本会在悬停时消失。
                • 错误 "jQuery.Deferred 异常:未定义图表"
                【解决方案13】:

                您也可以将 mayankcpdixit 的代码粘贴到 onAnimationComplete 选项中:

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

                动画后会显示文字

                【讨论】:

                • 很好,但是悬停时文字消失了
                • 正确,文字在悬停时消失... :( 如果文字没有消失就好了,知道该怎么做吗?谢谢
                • @MDT @maud 可以使用save 方法
                【解决方案14】:

                您必须像这样修改代码: 在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/。

                【讨论】:

                • 还有其他人找不到这个drawPieSegments函数吗?
                • 值得一提的是它不适用于 v2。使用包含的 jsfiddle 代码以便于使用
                • 如何在新行中添加 %?支持吗?
                • 这仍然是解决方案?
                • @ArunC.B - 向下滚动↴
                【解决方案15】:

                首先,感谢您选择 Chart.js!我在我目前的一个项目中使用它,我非常喜欢它——它完美地完成了这项工作。

                虽然标签/工具提示还不是库的一部分,但您可能想看看这三个拉取请求:

                而且,正如Cracker0dks 所提到的,Chart.js 使用canvas 进行渲染,因此您也可以通过直接与其交互来实现自己的工具提示。

                希望这会有所帮助。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2017-03-27
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-11-18
                  • 1970-01-01
                  • 2017-10-07
                  相关资源
                  最近更新 更多