Chart.js v2:如何让工具提示总是出现在饼图上?

IT技术 javascript jquery charts pie-chart chart.js
2021-01-18 02:37:06

在 Stack Overflow 中发现了类似的问题,但所有这些问题都在一两年前得到解决。现在 Chart.js 已经出现在第 2 版中,而且很多文档都发生了变化。有人可以帮我展示一个带有标签的饼图示例 - 或者饼图及其所有段的工具提示都可见吗?

更新

感谢@potatopeelings,他的回答非常适合 Chart.js v2.1。

虽然我最初在这里询问如何在饼图上永久显示工具提示,但我找到了一个更好的解决方案:将值显示为百分比标签!现在在 Chart.js v2.1 中为饼图启用了它。在图表选项中:

animation: {
  duration: 0,
  onComplete: function () {
    var self = this,
        chartInstance = this.chart,
        ctx = chartInstance.ctx;

    ctx.font = '18px Arial';
    ctx.textAlign = "center";
    ctx.fillStyle = "#ffffff";

    Chart.helpers.each(self.data.datasets.forEach(function (dataset, datasetIndex) {
        var meta = self.getDatasetMeta(datasetIndex),
            total = 0, //total values to compute fraction
            labelxy = [],
            offset = Math.PI / 2, //start sector from top
            radius,
            centerx,
            centery, 
            lastend = 0; //prev arc's end line: starting with 0

        for (var val of dataset.data) { total += val; } 

        Chart.helpers.each(meta.data.forEach( function (element, index) {
            radius = 0.9 * element._model.outerRadius - element._model.innerRadius;
            centerx = element._model.x;
            centery = element._model.y;
            var thispart = dataset.data[index],
                arcsector = Math.PI * (2 * thispart / total);
            if (element.hasValue() && dataset.data[index] > 0) {
              labelxy.push(lastend + arcsector / 2 + Math.PI + offset);
            }
            else {
              labelxy.push(-1);
            }
            lastend += arcsector;
        }), self)

        var lradius = radius * 3 / 4;
        for (var idx in labelxy) {
          if (labelxy[idx] === -1) continue;
          var langle = labelxy[idx],
              dx = centerx + lradius * Math.cos(langle),
              dy = centery + lradius * Math.sin(langle),
              val = Math.round(dataset.data[idx] / total * 100);
          ctx.fillText(val + '%', dx, dy);
        }

    }), self);
  }
},
5个回答

ChartJs 版本 > 2.1.5 的解决方案:

Chart.pluginService.register({
  beforeRender: function (chart) {
    if (chart.config.options.showAllTooltips) {
        // create an array of tooltips
        // we can't use the chart tooltip because there is only one tooltip per chart
        chart.pluginTooltips = [];
        chart.config.data.datasets.forEach(function (dataset, i) {
            chart.getDatasetMeta(i).data.forEach(function (sector, j) {
                chart.pluginTooltips.push(new Chart.Tooltip({
                    _chart: chart.chart,
                    _chartInstance: chart,
                    _data: chart.data,
                    _options: chart.options.tooltips,
                    _active: [sector]
                }, chart));
            });
        });

        // turn off normal tooltips
        chart.options.tooltips.enabled = false;
    }
},
  afterDraw: function (chart, easing) {
    if (chart.config.options.showAllTooltips) {
        // we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
        if (!chart.allTooltipsOnce) {
            if (easing !== 1)
                return;
            chart.allTooltipsOnce = true;
        }

        // turn on tooltips
        chart.options.tooltips.enabled = true;
        Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
            tooltip.initialize();
            tooltip.update();
            // we don't actually need this since we are not animating tooltips
            tooltip.pivot();
            tooltip.transition(easing).draw();
        });
        chart.options.tooltips.enabled = false;
    }
  }
});
谢谢!在 2.4.0 中它已更改为 Chart.plugins.register
2021-03-16 02:37:06
@Fl0R1D3R - 有没有办法让工具提示“面向另一边”?目前,它们面向中心,这是小图表的问题:\ 希望有想法。
2021-03-17 02:37:06
我只想添加一个可以帮助他人的改进。添加检查数字是否小于 0。 if(chart.data.datasets[0].data[j] > 0){ chart.pluginTooltips.push(new Chart.Tooltip({ .... }, chart) ); }
2021-04-10 02:37:06
我将如何为每个工具提示添加事件处理程序?
2021-04-10 02:37:06

使用新的 Chart.js 2.1,您可以编写一个插件来执行此操作并通过options属性对其进行控制


预览

在此处输入图片说明


脚本

注意在初始化图表之前需要注册插件

Chart.pluginService.register({
    beforeRender: function (chart) {
        if (chart.config.options.showAllTooltips) {
            // create an array of tooltips
            // we can't use the chart tooltip because there is only one tooltip per chart
            chart.pluginTooltips = [];
            chart.config.data.datasets.forEach(function (dataset, i) {
                chart.getDatasetMeta(i).data.forEach(function (sector, j) {
                    chart.pluginTooltips.push(new Chart.Tooltip({
                        _chart: chart.chart,
                        _chartInstance: chart,
                        _data: chart.data,
                        _options: chart.options,
                        _active: [sector]
                    }, chart));
                });
            });

            // turn off normal tooltips
            chart.options.tooltips.enabled = false;
        }
    },
    afterDraw: function (chart, easing) {
        if (chart.config.options.showAllTooltips) {
            // we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
            if (!chart.allTooltipsOnce) {
                if (easing !== 1)
                    return;
                chart.allTooltipsOnce = true;
            }

            // turn on tooltips
            chart.options.tooltips.enabled = true;
            Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
                tooltip.initialize();
                tooltip.update();
                // we don't actually need this since we are not animating tooltips
                tooltip.pivot();
                tooltip.transition(easing).draw();
            });
            chart.options.tooltips.enabled = false;
        }
    }
});

接着

new Chart(ctx, {
    type: 'pie',
    data: data,
    options: {
        showAllTooltips: true
        ...

使用较旧的 2.x 版本,您应该能够将相同的(或类似的,我不确定早期的数据结构)移动到 options.animation.onComplete


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

我正在使用 charts.js 2.2.1,如果您更改 _options : chart.options_options : chart.options.tooltips-
2021-03-15 02:37:06
我收到错误消息:Chart.Tooltip.positioners[opts.position] 不是函数(版本 2.4.0)
2021-03-19 02:37:06
当多个数据为 0 数据时,不显示所有工具提示。链接jsfiddle.net/q15ta78q/43它应该显示,红色 - 0,绿色 -0,但它只显示绿色 - 0。如何处理这种情况?有一个悬而未决的问题,如果你能回答它就太好了。问题:stackoverflow.com/questions/37790727/...
2021-03-20 02:37:06
@potatopeelings 有没有办法用 angularchart 做同样的事情
2021-04-03 02:37:06
@potatopeelings - 有没有办法让工具提示“面向另一边”?目前,它们面向中心,这是小图表的问题:\ 希望有想法。
2021-04-13 02:37:06

我正在寻找类似的解决方案并遇到了这个 chartjs 插件Chart.PieceLabel.js它具有显示标签、值和百分比等模式的配置。

这个插件在循环中泛滥。它有效,但滞后很多。
2021-03-15 02:37:06
这正是我要找的,tnx!
2021-03-24 02:37:06

根据github页面上chart.js的已关闭问题,不建议永久显示工具提示。

关闭此问题的此评论提供了更多详细信息:

https://github.com/chartjs/Chart.js/issues/1861#issuecomment-442852768

这是永久数据标签的推荐插件:

https://github.com/chartjs/chartjs-plugin-datalabels

如果你来到这里是因为你正在寻找一种方法让饼图看起来总是像我一样悬停。这是帮助我的解决方案:https : //nobal.in/technology/chart-js/how-to-highlight-selected-in-pie-doughnut/

我只需要一种方法来以编程方式放大饼图的一部分,就是这样