如何在Chart.js上显示数据值


117

我想问一下是否可以使用Chart.js 显示数据值?我想打印图形。

感谢您的任何建议。


我的图形工作正常..我只想在LineBar图表中显示数据值..然后我可以打印图形..因为现在我可以通过鼠标事件显示数据值
FuSsA 2015年

Answers:


138

后期编辑: Chart.js有一个官方插件2.7.0+可以执行此操作:https : //github.com/chartjs/chartjs-plugin-datalabels

原始答案:

您可以遍历onAnimationComplete上的点/条并显示值


预习

在此处输入图片说明


的HTML

<canvas id="myChart1" height="300" width="500"></canvas>
<canvas id="myChart2" height="300" width="500"></canvas>

脚本

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
    datasets: [
        {
            fillColor: "#79D1CF",
            strokeColor: "#79D1CF",
            data: [60, 80, 81, 56, 55, 40]
        }
    ]
};

var ctx = document.getElementById("myChart1").getContext("2d");
var myLine = new Chart(ctx).Line(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.points.forEach(function (points) {
                ctx.fillText(points.value, points.x, points.y - 10);
            });
        })
    }
});

var ctx = document.getElementById("myChart2").getContext("2d");
var myBar = new Chart(ctx).Bar(chartData, {
    showTooltips: false,
    onAnimationComplete: function () {

        var ctx = this.chart.ctx;
        ctx.font = this.scale.font;
        ctx.fillStyle = this.scale.textColor
        ctx.textAlign = "center";
        ctx.textBaseline = "bottom";

        this.datasets.forEach(function (dataset) {
            dataset.bars.forEach(function (bar) {
                ctx.fillText(bar.value, bar.x, bar.y - 5);
            });
        })
    }
});

小提琴-http: //jsfiddle.net/uh9vw0ao/


如果我在同一张图表中有两个折线图怎么办?
FuSsA

1
使用上面的方法,它仍然会显示值,但是如果两个点之间的距离太近,则可能会出现重叠。但是,您始终可以采用逻辑来更改值的位置。例如,如果您有彩色打印机,请使用jsfiddle.net/hh719qex。如果只有2个系列,则还可以进行其他操作,例如,如果2个点彼此接近2个,则将textBaseline设置为不同。
土豆皮

4
这是针对v1.0.2的,针对v2.1.3的如何执行?对象结构在更高版本中有所不同。
techie_28 '16

2
@potatopeelings我在onComplete这里使用了回调函数,但是当鼠标悬停在图表的条形图上时也会触发,导致数字由于重绘而闪烁,如果相同onAnimationComplete?我无法使用此回调与我现有图表代码(见var chartBar底部pastebin.com/tT7yTkGh
techie_28

1
我的图表中的条形顶部都需要工具提示和数据。显示工具提示时,工具栏顶部的数据将变为白色,这在我的透明工具提示中可见。我怎样才能解决这个问题?
LJP

82

这是Chart.js 2.3的更新版本

2016年9月23日:修改了我的代码,以适用于v2.3的线型/条型。

重要提示:即使不需要动画,也不要将duration选项更改为0,否则会得到chartInstance.controller为未定义错误。

var chartData = {
    labels: ["January", "February", "March", "April", "May", "June"],
        datasets: [
            {
                fillColor: "#79D1CF",
                strokeColor: "#79D1CF",
                data: [60, 80, 81, 56, 55, 40]
            }
        ]
    };

var opt = {
    events: false,
    tooltips: {
        enabled: false
    },
    hover: {
        animationDuration: 0
    },
    animation: {
        duration: 1,
        onComplete: function () {
            var chartInstance = this.chart,
                ctx = chartInstance.ctx;
            ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, Chart.defaults.global.defaultFontStyle, Chart.defaults.global.defaultFontFamily);
            ctx.textAlign = 'center';
            ctx.textBaseline = 'bottom';

            this.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.controller.getDatasetMeta(i);
                meta.data.forEach(function (bar, index) {
                    var data = dataset.data[index];                            
                    ctx.fillText(data, bar._model.x, bar._model.y - 5);
                });
            });
        }
    }
};
 var ctx = document.getElementById("Chart1"),
     myLineChart = new Chart(ctx, {
        type: 'bar',
        data: chartData,
        options: opt
     });
<canvas id="myChart1" height="300" width="500"></canvas>


在条形图上尝试此操作时,出现“未捕获的TypeError:无法读取未定义的属性'0'”。酒吧是否使用“ dataset.metaData [i] ._ model”以外的东西?
克里斯·恩塞尔

实际上是var模型= dataset._meta [i] .data [0] ._ model;
Flanamacca

这也不是全部事实。我仍然有例外。会设法弄清楚。
2016年

var model = dataset._meta [0] .data [i] ._ model; 其实。
brian'7

2
看起来它并不像_meta [0]那么简单。实际上,_meta对象不是数组,它具有以数字为键的单个元素。我无法弄清楚数字背后的原因,因此我只是通过在键列表中查找来获得第一个元素,例如:var model = dataset._meta [Object.keys(dataset._meta)[0]] .data [i] ._ model;
IrishDubGuy '16

34

此动画选项适用于条形图上的2.1.3。

略作修改的@Ross答案

animation: {
duration: 0,
onComplete: function () {
    // render the value of the chart above the bar
    var ctx = this.chart.ctx;
    ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
    ctx.fillStyle = this.chart.config.options.defaultFontColor;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'bottom';
    this.data.datasets.forEach(function (dataset) {
        for (var i = 0; i < dataset.data.length; i++) {
            var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
            ctx.fillText(dataset.data[i], model.x, model.y - 5);
        }
    });
}}

3
我还必须设置hover: {animationDuration: 0}停止在悬停时动画的标签
iamyojimbo

1
另外,请注意,如果要在隐藏图例中的内容时隐藏标签,则需要在forEach循环之前添加以下内容:.filter(dataset => !dataset._meta[0].hidden)
iamyojimbo

1
如果条上方没有足够的空间,此方法将导致值裁剪。
珍妮·安娜

2
不敢相信那是丑陋的^^干得好
La masse

看起来不错,但是在重新绘制工具提示时闪烁。此外,也不会处理组合图表和堆积条形图的累积数据标签上的冲突,这当然需要更多的编码。
dma_k

22

我认为在chartJS v2.x中执行此操作的最佳选择是使用插件,因此选项中没有大量代码。此外,它还可以防止将鼠标悬停在栏上时数据消失。

即简单地使用此代码,该代码注册一个插件,该插件在绘制图表后添加文本。

Chart.pluginService.register({
    afterDraw: function(chartInstance) {
        var ctx = chartInstance.chart.ctx;

        // render the value of the chart above the bar
        ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
        ctx.textAlign = 'center';
        ctx.textBaseline = 'bottom';

        chartInstance.data.datasets.forEach(function (dataset) {
            for (var i = 0; i < dataset.data.length; i++) {
                var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
                ctx.fillText(dataset.data[i], model.x, model.y - 2);
            }
        });
  }
});

Chart.plugins.register({
hasentopf

我不得不用Chart.defaults.global.tooltips.enabled = false;。该解决方案的问题在于该afterDraw函数被调用了数百次,可能会产生CPU开销。不过,这是目前唯一没有眨眼的答案。如果您需要更好的horizontalBar图表渲染,请使用ctx.textAlign = 'left'; ctx.textBaseline = 'middle';ctx.fillText(dataset.data[i], model.x+5, model.y);
KrisWebDev

更加清洁和模块化的解决方案。
hadaytullah

20

基于@Ross针对Chart.js 2.0及更高版本的答案,我不得不进行一些微调,以防止在条形的高度也偏向比例边界时出现这种情况。

例

animation条形图选项的属性:

animation: {
            duration: 500,
            easing: "easeOutQuart",
            onComplete: function () {
                var ctx = this.chart.ctx;
                ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontFamily, 'normal', Chart.defaults.global.defaultFontFamily);
                ctx.textAlign = 'center';
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset) {
                    for (var i = 0; i < dataset.data.length; i++) {
                        var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model,
                            scale_max = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
                        ctx.fillStyle = '#444';
                        var y_pos = model.y - 5;
                        // Make sure data value does not get overflown and hidden
                        // when the bar's value is too close to max value of scale
                        // Note: The y value is reverse, it counts from top down
                        if ((scale_max - model.y) / scale_max >= 0.93)
                            y_pos = model.y + 20; 
                        ctx.fillText(dataset.data[i], model.x, y_pos);
                    }
                });               
            }
        }

鼠标悬停在图表上时,文本闪烁。.我尝试ctx.save()在最后致电,但没有帮助
techie_28 '16

onComplete当我徘徊在酒吧的这会导致重绘和文字似乎blink.Would这与同执行回调onAnimationComplete呢?我无法用onAnimationComplete我现有的代码回调(见var chartBar在底部引擎收录。 com / tT7yTkGh
techie_28 '16

是否可以在饼图中做同样的事情
Ravi Khambhati

@RaviKhambhati是的,您可以在以下答案中进行检查:stackoverflow.com/a/38797604/6402571
Hung Tran

17

如果您使用的插件为chartjs-plugin-datalabels,则以下代码选项对象将有所帮助

确保您导入import 'chartjs-plugin-datalabels';打字稿文件或<script src="chartjs-plugin-datalabels.js"></script>在javascript文件中添加对它的引用。

options: {
    maintainAspectRatio: false,
    responsive: true,
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
        }
      }]
    },
    plugins: {
      datalabels: {
        anchor: 'end',
        align: 'top',
        formatter: Math.round,
        font: {
          weight: 'bold'
        }
      }
    }
  }

1
您的答案非常简单,对我有用。谢谢。快乐的编码。
万锦Manikanta,

7

按照这个好答案,我将使用以下选项制作条形图:

var chartOptions = {
    animation: false,
    responsive : true,
    tooltipTemplate: "<%= value %>",
    tooltipFillColor: "rgba(0,0,0,0)",
    tooltipFontColor: "#444",
    tooltipEvents: [],
    tooltipCaretSize: 0,
    onAnimationComplete: function()
    {
        this.showTooltip(this.datasets[0].bars, true);
    }
};

window.myBar = new Chart(ctx1).Bar(chartData, chartOptions);

条形图

这仍然使用了工具提示系统及其优势(自动定位,模板化...),但隐藏了装饰(背景色,插入符号等)。


实施可能会因图表类型而异。例如,对于折线图,它this.datasets[0].points.bars。我确实更喜欢此解决方案,因为它使用了工具提示系统。
Telmo Marques's

1
此解决方案适用于早期版本。如何实现最新版本(即2.1.3)。我已经使用了potatopeelings和黄庄回答了动画onComplete回调,但在上空盘旋,这将导致文本重绘和给予不必要的眨眼图表的酒吧effect.I也试了一下甚至引发afterDraw与它是所有same.Strangely它土豆皮提供的小提琴不会发生任何想法吗?
techie_28 '16

6

从chart.js示例(文件Chart.js-2.4.0 / samples / data_labelling.html):

```//定义一个插件来提供数据标签

    Chart.plugins.register({
        afterDatasetsDraw: function(chartInstance, easing) {
            // To only draw at the end of animation, check for easing === 1
            var ctx = chartInstance.chart.ctx;

            chartInstance.data.datasets.forEach(function (dataset, i) {
                var meta = chartInstance.getDatasetMeta(i);
                if (!meta.hidden) {
                    meta.data.forEach(function(element, index) {
                        // Draw the text in black, with the specified font
                        ctx.fillStyle = 'rgb(0, 0, 0)';

                        var fontSize = 16;
                        var fontStyle = 'normal';
                        var fontFamily = 'Helvetica Neue';
                        ctx.font = Chart.helpers.fontString(fontSize, fontStyle, fontFamily);

                        // Just naively convert to string for now
                        var dataString = dataset.data[index].toString();

                        // Make sure alignment settings are correct
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'middle';

                        var padding = 5;
                        var position = element.tooltipPosition();
                        ctx.fillText(dataString, position.x, position.y - (fontSize / 2) - padding);
                    });
                }
            });
        }
    });

```


我通过执行if(chart.config.type ==“ horizo​​ntalBar”)然后在水平条形图上对齐来添加一条线,然后定义一个自定义的垂直填充10以使其居中对齐。
杰夫·比格里

6

我建议使用此插件:https : //github.com/chartjs/chartjs-plugin-datalabels

只需将插件导入js文件即可将标签添加到图表中,例如:

import 'chartjs-plugin-datalabels'

可以使用以下文档进行微调:https : //chartjs-plugin-datalabels.netlify.com/options.html


2
最简单的一种,不需要“代码”,只需使用标准的“选项”对象进行自定义即可。注意:最低要求的Charts.js版本是2.7.0,我从CDN引用了2.5.0,并且图表上没有变化...
GBU

@GBU选项属性是什么?
Bhimbim

5

编辑了@ajhuddy的答案。仅用于条形图。我的版本添加:

  • 淡入动画以获取值。
  • 如果条形过高,可通过将值放置在条形内来防止剪切。
  • 没有眨眼。

例

缺点:将鼠标悬停在其中具有值的条形上方时,该值可能看起来有些参差不齐。我还没有找到一种解决方案可以禁用悬停效果。根据您自己的设置,可能还需要调整。

组态:

bar: {
  tooltips: {
    enabled: false
  },
  hover: {
    animationDuration: 0
  },
  animation: {
    onComplete: function() {
      this.chart.controller.draw();
      drawValue(this, 1);
    },
    onProgress: function(state) {
      var animation = state.animationObject;
      drawValue(this, animation.currentStep / animation.numSteps);
    }
  }
}

帮手:

// Font color for values inside the bar
var insideFontColor = '255,255,255';
// Font color for values above the bar
var outsideFontColor = '0,0,0';
// How close to the top edge bar can be before the value is put inside it
var topThreshold = 20;

var modifyCtx = function(ctx) {
  ctx.font = Chart.helpers.fontString(Chart.defaults.global.defaultFontSize, 'normal', Chart.defaults.global.defaultFontFamily);
  ctx.textAlign = 'center';
  ctx.textBaseline = 'bottom';
  return ctx;
};

var fadeIn = function(ctx, obj, x, y, black, step) {
  var ctx = modifyCtx(ctx);
  var alpha = 0;
  ctx.fillStyle = black ? 'rgba(' + outsideFontColor + ',' + step + ')' : 'rgba(' + insideFontColor + ',' + step + ')';
  ctx.fillText(obj, x, y);
};

var drawValue = function(context, step) {
  var ctx = context.chart.ctx;

  context.data.datasets.forEach(function (dataset) {
    for (var i = 0; i < dataset.data.length; i++) {
      var model = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._model;
      var textY = (model.y > topThreshold) ? model.y - 3 : model.y + 20;
      fadeIn(ctx, dataset.data[i], model.x, textY, model.y > topThreshold, step);
    }
  });
};

Janne,谢谢您的解决方案,它看起来很棒。但是我遇到的情况是我的值实际上有点大(5个十进制数字),并且当屏幕尺寸很小或我有很多图表时,这些数字彼此重叠。有什么办法使这项工作具有责任感吗?就像在条形图下面的标签一样,在没有空格的情况下使数字旋转?
Phiter '16

@PhiterFernandes我认为应该可以通过在ModifyCtx函数中检查当前屏幕尺寸并使用ctx.rotate来旋转。但是我不确定如何将值大小与可用空间进行比较以确定何时旋转。
珍妮·安娜拉

ModifyCtx函数只能运行一次,而不能调整大小,对吗?我将看一下chart.js源代码,看看它们在x轴上旋转标签的位置。如果我看到一些东西,我会尝试做些事情并在这里告诉你,好吗?=)
Phiter '16

我在版本2.3.0的第7075行中找到了一些东西calculateTickRotation,它在Scale函数中。我会分析的。
Phiter '16

5

根据我的经验,一旦您添加了chartjs-plugin-datalabels插件(请确保将<script>标签放置在页面上的chart.js标记之后),您的图表就会开始显示值。

如果您随后选择,则可以对其进行自定义以满足您的需求。此处清楚地记录了自定义文档,但基本上,格式类似于此假设示例:

var myBarChart = new Chart(ctx, {
    type: 'bar',
    data: yourDataObject,
    options: {
        // other options
        plugins: {
            datalabels: {
                anchor :'end',
                align :'top',
                // and if you need to format how the value is displayed...
                formatter: function(value, context) {
                    return GetValueFormatted(value);
                }
            }
        }
    }
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.