Charts.js 工具提示在图表上重叠文本

use*_*707 5 javascript z-index tooltip chart.js

由于Charts.js还不支持注释,所以我在绘制图表后添加了数据点的注释。使用 ctx.fillText 如下所示。

        animation: {
            animateScale: true,
            animateRotate: true,
            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.fillStyle = this.chart.config.options.defaultFontColor;
                ctx.textBaseline = 'bottom';

                this.data.datasets.forEach(function (dataset, i) {
                    var meta = chartInstance.controller.getDatasetMeta(i);
                    meta.data.forEach(function (bar, index) {
                        data = dataset.data[index];
                        ctx.fillText(data, bar._model.x, bar._model.y - 5);
                    });
                });
            }
        }
Run Code Online (Sandbox Code Playgroud)

除了现在工具提示显示在新添加的文本下方之外,这非常有效。这并不那么明显,但有时它会重叠在一个不好的地方,这意味着您看不到后面的工具提示。

在此输入图像描述

有没有办法设置 ctx.fillText 或工具提示的 z 索引,以便我可以正确地对它们进行分层?

Shi*_*nta 6

@user3284707实际上你要做的就是在工具提示之前在条形顶部绘制数字,你正在绘制它们onComplete,将它们放在所有东西的顶部。

我使用以下方法绘制这些数字:

Chart.plugins.register({
  beforeDraw: function(chartInstance) {
    if (chartInstance.config.options.showDatapoints) {
      var helpers = Chart.helpers;
      var ctx = chartInstance.chart.ctx;
      var fontColor = helpers.getValueOrDefault(chartInstance.config.options.showDatapoints.fontColor, chartInstance.config.options.defaultFontColor);

      // 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';
      ctx.fillStyle = fontColor;

      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;
          var scaleMax = dataset._meta[Object.keys(dataset._meta)[0]].data[i]._yScale.maxHeight;
          var yPos = (scaleMax - model.y) / scaleMax >= 0.93 ? model.y + 20 : model.y - 5;
          var label = dataset.data[i] || '';
          ctx.fillText(label.toLocaleString(), model.x, yPos);
        }
      });
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

注意beforeDraw那里。

希望这对 3 年后有所帮助,我花了最后 30 分钟试图解决这个问题


use*_*707 1

对于任何感兴趣的人,我设法弄清楚了这一点,我最终查看了 Charts.js 中的工具提示绘制函数,并使用其修改版本作为自定义工具提示,从而在添加注释后绘制工具提示。

首先将其添加到您的选项中

config = {
    options: {
        tooltips: {
            enabled: false,
            custom: customTooltips
        }
Run Code Online (Sandbox Code Playgroud)

然后调用下面的自定义工具提示函数。

var currentX = null;
var currentY = null;

var customTooltips = function (tooltip) {

    var helpers = Chart.helpers;
    var ctx = this._chart.ctx;
    var vm = this._view;

    if (vm == null || ctx == null || helpers == null || vm.opacity === 0) {
        return;
    }

    var tooltipSize = this.getTooltipSize(vm);

    var pt = {
        x: vm.x,
        y: vm.y
    };

    if (currentX == vm.x && currentY == vm.y) {
        return;
    }

    currentX = vm.x;
    currentY = vm.y;

   //  IE11/Edge does not like very small opacities, so snap to 0
    var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;

    // Draw Background
    var bgColor = helpers.color(vm.backgroundColor);
    ctx.fillStyle = bgColor.alpha(opacity * bgColor.alpha()).rgbString();
    helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);
    ctx.fill();

    // Draw Caret
    this.drawCaret(pt, tooltipSize, opacity);

    // Draw Title, Body, and Footer
    pt.x += vm.xPadding;
    pt.y += vm.yPadding;

    // Titles
    this.drawTitle(pt, vm, ctx, opacity);

    // Body
    this.drawBody(pt, vm, ctx, opacity);

    // Footer
    this.drawFooter(pt, vm, ctx, opacity);
};
Run Code Online (Sandbox Code Playgroud)