在图例悬停时突出显示线系列

Highlight Line Series on legend hover

非常喜欢chart.js,但我正在努力创建自定义事件(没有太多经验,所以仍在学习)

我试图在图例工具提示悬停时突出显示完整的线条或条形系列,基本上将数据集中的所有元素显示为悬停样式。

我正在尝试通过图例 onHover 回调来执行此操作,但不确定这是否正确? 我设法找到了悬停的数据集,但难以 运行 updateHoverStyle 突出显示该系列。

关于我应该看哪里的任何帮助或指示?

这是我到目前为止所要做的...

legend: {
      labels: {
        usePointStyle: true
      },
      onHover: function(event, legendItem) {
        var me = this;
        var options = me.options || {};
        var hoverOptions = options.hover;
        var index = legendItem.datasetIndex;
        var ci = this.chart;
        var elements = ci.getDatasetMeta(index).data;
        ci.updateHoverStyle(elements, hoverOptions.mode, true)
      }
    }

你当然是在正确的轨道上,但让我用一个条形图的工作示例和一些解释来帮助你。

要实现此行为,您一定要使用图例 onHover 属性(就像您所做的那样)。但是,一旦您更新了悬停样式,您必须重新渲染图表才能使更改生效。这是一个例子。

legend: {
  labels: {
    usePointStyle: true
  },
  onHover: function(event, legendItem) {
    var options = this.options || {};
    var hoverOptions = options.hover || {};
    var ci = this.chart;
    hoveredDatasetIndex = legendItem.datasetIndex;
    ci.updateHoverStyle(ci.getDatasetMeta(hoveredDatasetIndex).data, hoverOptions.mode, true);
    ci.render();
  }
}

有了这个工作,现在我们需要一种方法来在图例项目不再悬停时取消设置或清除悬停样式。否则,每次用户将鼠标悬停在图例项上时,图表中的系列会变得越来越暗,直到它变成黑色。

所以我们需要一些方法来清除悬停样式。如果有传说就好了onMouseLeave属性,可惜……没有。所以为了解决这个问题,我们最终不得不 "trick" chart.js 做我们想做的事。诀窍是使用工具提示 custom 功能。下面是一个例子。

tooltips: {
  mode: 'index',
  intersect: false,
  custom: function(tooltip) {
    if (hoveredDatasetIndex != -1) {
      var options = this.options || {};
      var hoverOptions = options.hover || {};
      var ci = this._chartInstance.chart.controller;
      ci.updateHoverStyle(ci.getDatasetMeta(hoveredDatasetIndex).data, hoverOptions.mode, false);
      hoveredDatasetIndex = -1;
      ci.render();
    }
  }
}

这是在清除悬停样式(通过将 false 传递给 updateHoverStyle 的最后一个参数)。由于我们不在图例的上下文中,我只是使用回调外部的变量来存储之前悬停的数据集索引。

此 'hack' 起作用的原因是每次将鼠标移动到整个图表(但不是图例)上的任何位置时都会调用工具提示回调。所以它代表了除了传说之外的一切。因此,我们可以像使用不存在但方便的图例 onMouseLeave 回调一样使用它。

希望这一切都有意义。这是一个有效的 codepen 来演示完整的解决方案。

您的代码中只缺少一件事:使用 ci.render();

刷新图表
legend: {
      labels: {
        usePointStyle: true
      },
      onHover: function(event, legendItem) {
        var me = this;
        var options = me.options || {};
        var hoverOptions = options.hover;
        var index = legendItem.datasetIndex;
        var ci = this.chart;
        var elements = ci.getDatasetMeta(index).data;
        ci.updateHoverStyle(elements, hoverOptions.mode, true)
        ci.render();  //    <<---- commit changes
      }
    }

但这最终会突出显示所有痕迹:在突出显示悬停的痕迹之前,您必须移除所有其他痕迹的突出显示,bt 循环遍历它们:

legend: {
      labels: {
        usePointStyle: true
      },
      onHover: function(event, legendItem) {
        var me = this;
        var options = me.options || {};
        var hoverOptions = options.hover;
        var index = legendItem.datasetIndex;
        var ci = this.chart;
        for (var i=0; i < ci.datasets.length-1; i++) {
           var elements = ci.getDatasetMeta(i).data;
           ci.updateHoverStyle(elements, hoverOptions.mode, false) ; // <<<--- turn off higlight
        }
        var elements = ci.getDatasetMeta(index).data;
        ci.updateHoverStyle(elements, hoverOptions.mode, true) // <<-- Turn on 
        ci.render();  
      }
    }