You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

chartjs-plugin-crosshair在Angular项目中无法生效求助

Angular中chartjs-plugin-crosshair插件失效及多图表同步问题

环境版本

  • chart.js: ^3.9.1
  • chartjs-plugin-crosshair: ^1.2.0

问题现象

在Angular项目中使用chartjs-plugin-crosshair插件时无法正常生效,推测是导入或配置方式有误;同时需要实现四个同类型图表的交互同步,暂未找到可行方案。

当前代码

导入代码

import { Component } from '@angular/core';
import ChartStreaming from 'chartjs-plugin-streaming';
import zoomPlugin from 'chartjs-plugin-zoom';
import annotationPlugin from 'chartjs-plugin-annotation';
import 'chartjs-adapter-moment';
import 'hammerjs';
import Chart from 'chart.js/auto';

import * as CrosshairPlugin from 'chartjs-plugin-crosshair';
Chart.register(CrosshairPlugin);
Chart.register(ChartStreaming, zoomPlugin, annotationPlugin);

图表初始化代码

const ctx = (<HTMLCanvasElement>document.getElementById('MyChart')).getContext('2d');
this.chart = new Chart(ctx!, {
  type: 'line',
  data: {
    labels: this.labels,
    datasets: [
      {
        label: 'Series 1',
        data: this.Serie1,
        backgroundColor: [colors.color1],
        borderColor: [colors.color1],
        borderWidth: 1,
        xAxisID: 'y_axis_1',
        pointRadius: 0,
      },
      {
        label: 'Series 2',
        data: this.Serie2,
        backgroundColor: [colors.color2],
        borderColor: [colors.color2],
        borderWidth: 1,
        xAxisID: 'y_axis_2',
        pointRadius: 0,
      },
    ],
  },
  options: {
    maintainAspectRatio: false,
    indexAxis: 'y',
    scales: {
      yAxes: {
        ticks: {},
        reverse: true,
        type: 'realtime',
        time: {
          unit: 'minute',
          displayFormats: {
            minute: 'HH:mm:ss',
          },
        },
        realtime: {
          frameRate: 60,
          duration: 30000,
          refresh: 2000,
          delay: 4000,
          ttl: 86400000,
          onRefresh: chart => {
            let chartTime: any = new Date();
            let url = 'http://localhost:3000/';
            fetch(url)
              .then(response => response.json())
              .then(Data => {
                this.chart.data.labels.push(chartTime);
                this.chart.data.datasets[0].data.push(Data.data1);
                this.chart.data.datasets[1].data.push(Data.data2);
                this.chart.data.datasets[2].data.push(Data.data3);
                chart.update('quiet');
              })
              .catch(error => console.log(error));
          },
        },
      },
      y_axis_1: {
        grid: {
          lineWidth: 1,
          tickWidth: 1,
        },
        position: 'top',
        min: 0,
        max: 4000,
        ticks: { color: colors.color1 },
        title: {
          display: true,
          text: 'Y Axis 1',
          color: colors.color1,
        },
      },
      y_axis_2: {
        grid: { lineWidth: 1 },
        position: 'top',
        min: 0,
        max: 300,
        ticks: { color: colors.color2 },
        title: {
          display: true,
          text: 'Y Axis 2',
          color: colors.color2,
        }
      },
    },
    plugins: {
      // crosshair: {
      //   line: {
      //     color: "#d1d1d1",
      //     width: 1,
      //   },
      // },
      annotation: {
        annotations: {
          line1: {
            type: 'line',
            scaleID: 'y_axis_1',
            value: 3500,
            borderColor: colors.black,
            borderWidth: 2,
            label: {
              backgroundColor: colors.color1,
              content: '2000',
              display: true,
              position: 'start',
              yAdjust: 50,
              rotation: 'auto',
              font: { size: 12 },
            }
          },
          line2: {
            type: 'line',
            scaleID: 'y_axis_2',
            value: 250,
            borderColor: colors.black,
            borderWidth: 2,
            label: {
              backgroundColor: colors.color2,
              content: '2000',
              display: true,
              position: 'start',
              rotation: 'auto',
              font: { size: 12 },
            }
          },
        }
      },
      tooltip: { mode: 'nearest', intersect: false },
      title: { display: true, text: 'Realtime Chart' },
      legend: { position: 'bottom' },
      zoom: {
        pan: { enabled: true, mode: 'y', modifierKey: 'ctrl' },
        zoom: {
          onZoomComplete: function ({ chart }) { console.log(`I was zoomed!!!`); },
          mode: 'y',
          wheel: { enabled: true, speed: 0.1 },
          drag: { enabled: true },
          pinch: { enabled: true },
        }
      },
    },
  },
  plugins: []
});

解决方案

一、修复crosshair插件失效问题

  1. 修正插件导入方式
    chartjs-plugin-crosshair v1.x版本需要默认导入,修改导入代码:
import { Component } from '@angular/core';
import ChartStreaming from 'chartjs-plugin-streaming';
import zoomPlugin from 'chartjs-plugin-zoom';
import annotationPlugin from 'chartjs-plugin-annotation';
import 'chartjs-adapter-moment';
import 'hammerjs';
import Chart from 'chart.js/auto';

// 改为默认导入
import CrosshairPlugin from 'chartjs-plugin-crosshair';
// 合并注册语句,避免重复调用
Chart.register(CrosshairPlugin, ChartStreaming, zoomPlugin, annotationPlugin);
  1. 启用并完善插件配置
    取消注释crosshair配置,同时删除代码末尾的空plugins: [](该属性会覆盖options中的插件配置):
this.chart = new Chart(ctx!, {
  type: 'line',
  data: { /* 保留原有数据 */ },
  options: {
    maintainAspectRatio: false,
    indexAxis: 'y',
    scales: { /* 保留原有缩放配置 */ },
    plugins: {
      // 启用crosshair配置
      crosshair: {
        line: { color: "#d1d1d1", width: 1 },
        tooltip: { enabled: true, mode: 'nearest', intersect: false },
        // 为后续多图表同步做准备
        sync: { enabled: true, group: 'chart-group-1' },
        mode: 'index' // 适配横向图表的十字线模式
      },
      // 保留annotation、zoom等其他插件配置
      annotation: { /* 原有配置 */ },
      zoom: { /* 原有配置 */ }
    }
  }
  // 删除此处的plugins: []
});

二、实现四个图表的同步交互

  1. 统一图表分组
    给所有需要同步的图表设置相同的crosshair分组名(比如chart-group-1),插件会自动同步十字线hover状态。

  2. 同步缩放与平移
    通过监听图表事件,同步更新其他图表的缩放/平移参数:

// 假设四个图表实例为chart1、chart2、chart3、chart4
const charts = [this.chart1, this.chart2, this.chart3, this.chart4];

// 同步缩放
charts.forEach(targetChart => {
  targetChart.on('zoom', () => {
    charts.forEach(chart => {
      if (chart !== targetChart) {
        chart.scales.yAxes.options.realtime.duration = targetChart.scales.yAxes.options.realtime.duration;
        chart.update('none');
      }
    });
  });
});

// 同步平移
charts.forEach(targetChart => {
  targetChart.on('pan', () => {
    charts.forEach(chart => {
      if (chart !== targetChart) {
        const targetScale = targetChart.scales.yAxes;
        const currentScale = chart.scales.yAxes;
        currentScale.min = targetScale.min;
        currentScale.max = targetScale.max;
        chart.update('none');
      }
    });
  });
});

内容的提问来源于stack exchange,提问作者Danilo Caro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:10:24