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

Chart.js:图表创建后如何应用更新的默认配置?

Chart.js 主题切换后默认选项不生效的解决办法

问题描述

我给页面添加了深色模式切换按钮,希望Chart.js能同步响应明暗主题切换。为此配置了两组默认选项:

const defaults = {
  scale: {
    border: {
      color: dark ? '#FFFFFF19' : '#00000019',
    },
    grid: {
      color: dark ? '#FFFFFF19' : '#00000019',
    },
  },
}

每次主题切换时,我会更新Chart.defaults,并为每个图表调用chart.update(),但新的默认选项始终不生效。我尝试过'reset'、'none'、'default'和'active'等不同更新模式,问题依旧。完整配置代码如下:

import {
  CategoryScale,
  Chart,
  LineController,
  LineElement,
  LinearScale,
  PointElement,
  TimeScale,
  Title,
  Tooltip,
} from 'chart.js';
import {merge, remove} from 'lodash';

import type {ChartConfiguration, ChartConfigurationCustomTypesPerDataset, ChartItem, ChartType, DefaultDataPoint} from 'chart.js';

Chart.register(Title, Tooltip, CategoryScale, TimeScale, LinearScale, LineController, PointElement, LineElement);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const charts: Array<RmsChart<any, any, any>> = [];

export class RmsChart<
  TType extends ChartType = ChartType,
  TData = DefaultDataPoint<TType>,
  TLabel = unknown,
> extends Chart<TType, TData, TLabel> {
  constructor(item: ChartItem, config: ChartConfiguration<TType, TData, TLabel> | ChartConfigurationCustomTypesPerDataset<TType, TData, TLabel>) {
    super(item, config);
    charts.push(this);
  }

  destroy() {
    super.destroy();
    remove(charts, this);
  }
}

function cssVarColor(variable: string, alpha = 1.0) {
  const cssVar = getComputedStyle(document.documentElement).getPropertyValue(variable);
  if (!cssVar)
    console.warn(`Cannot get css variable ${variable}`);
  const color = cssVar || '0,0,0';
  return `rgba(${color}, ${alpha})`;
}

async function syncThemeColor() {
  await nextTick();
  const defaults = {
    elements: {
      line: {
        backgroundColor: cssVarColor('--v-theme-chart-primary', 0.12),
        borderColor: cssVarColor('--v-theme-chart-primary', 0.6),
      },
      point: {
        backgroundColor: cssVarColor('--v-theme-chart-point'),
        borderColor: cssVarColor('--v-theme-chart-primary'),
      },
    },
    scale: {
      border: {
        color: cssVarColor('--v-theme-chart-grid', 0.1),
      },
      grid: {
        color: cssVarColor('--v-theme-chart-grid', 0.1),
      },
    },
  };
  merge(Chart.defaults, defaults);
  console.log(charts[0].options);
  for (const chart of charts)
    chart.update();
  console.log('syncThemeColor', Chart.defaults);
}

watch(useIsDarkMode(), syncThemeColor, {immediate: true});

核心原因

Chart.js 在初始化图表时,会将全局Chart.defaults深拷贝到每个图表实例的options属性中。后续修改全局默认值,不会自动同步到已创建的图表实例,因此调用chart.update()无法触发样式更新。

解决办法

方法一:直接更新图表实例的选项

跳过修改全局默认值,直接遍历所有图表实例,将主题选项合并到实例自身的options中,再调用update('reset')强制生效:

async function syncThemeColor() {
  await nextTick();
  const themeOptions = {
    elements: {
      line: {
        backgroundColor: cssVarColor('--v-theme-chart-primary', 0.12),
        borderColor: cssVarColor('--v-theme-chart-primary', 0.6),
      },
      point: {
        backgroundColor: cssVarColor('--v-theme-chart-point'),
        borderColor: cssVarColor('--v-theme-chart-primary'),
      },
    },
    scale: {
      border: {
        color: cssVarColor('--v-theme-chart-grid', 0.1),
      },
      grid: {
        color: cssVarColor('--v-theme-chart-grid', 0.1),
      },
    },
  };

  // 遍历图表实例,合并主题选项并更新
  for (const chart of charts) {
    merge(chart.options, themeOptions);
    chart.update('reset'); // 用reset模式强制重新应用所有选项
  }
}

方法二:销毁重建图表(适合复杂场景)

如果你的图表严重依赖全局默认值,可以先更新Chart.defaults,再销毁旧图表、用新默认值重新创建:

async function syncThemeColor() {
  await nextTick();
  const defaults = {
    elements: { /* 主题选项同前 */ },
    scale: { /* 主题选项同前 */ }
  };
  merge(Chart.defaults, defaults);

  // 保存所有图表的DOM元素和配置
  const chartCache = charts.map(chart => ({
    element: chart.canvas,
    config: chart.config
  }));

  // 销毁旧图表
  charts.forEach(chart => chart.destroy());
  charts.length = 0;

  // 用更新后的默认值重建图表
  chartCache.forEach(({element, config}) => {
    new RmsChart(element, config);
  });
}

额外优化:用CSS变量实现无JS更新

Chart.js v3及以上版本支持直接使用CSS变量。只需在图表配置中引用预定义的CSS变量,切换主题时仅修改CSS变量值即可,无需操作Chart实例:

  1. 初始化图表时用CSS变量配置样式:
const chartConfig = {
  options: {
    scale: {
      border: {
        color: 'var(--chart-grid-color)'
      },
      grid: {
        color: 'var(--chart-grid-color)'
      }
    },
    elements: {
      line: {
        backgroundColor: 'var(--chart-line-bg)',
        borderColor: 'var(--chart-line-border)'
      }
    }
  }
};
  1. 在CSS中定义明暗主题变量:
:root {
  --chart-grid-color: rgba(0,0,0,0.1);
  --chart-line-bg: rgba(0,123,255,0.12);
  --chart-line-border: rgba(0,123,255,0.6);
}

.dark-mode {
  --chart-grid-color: rgba(255,255,255,0.1);
  --chart-line-bg: rgba(13,110,253,0.12);
  --chart-line-border: rgba(13,110,253,0.6);
}
  1. 切换主题时只需给根元素添加/移除dark-mode类即可。

内容的提问来源于stack exchange,提问作者Wai Luk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:19:57