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

Chart.js图表对象随机颜色分配异常问题排查

Chart.js 图表颜色异常问题修复

问题现象

当前使用Chart.js搭建图表时存在两个异常:

  • 所有图表系列共用同一颜色
  • 每次添加新企业时,所有已存在的图表系列颜色都会被替换为新的随机颜色

问题根源分析

  1. 颜色生成逻辑位置错误:colorToUse 定义在企业循环外部,导致所有企业复用同一个随机颜色,出现系列同色问题。
  2. 颜色未持久化缓存:每次调用onCompanyChange时,会重新为所有企业生成颜色,而非仅为新增企业分配新颜色,导致添加新企业时所有系列颜色重置。

修复方案

核心思路是为每个企业绑定唯一且持久化的颜色,仅在企业首次加载时生成颜色并缓存,后续操作复用该颜色。

修改后的完整代码

// 新增颜色缓存Map,绑定企业ID与对应颜色
companyColorCache = new Map<number, string>();
allInterventionStats = new Map<number, InterventionData[]>();

async onCompanyChange(companies: Company[]) {
    // 处理新增企业:加载数据+分配并缓存颜色+生成数据集
    for (const company of companies) {
      if (!this.companyDataCache.get(company.Id)) {
        const interventionStats = await this.adminToolsService.getInterventionUsefulnessData(company.Id).toPromise();
        this.allInterventionStats.set(company.Id, interventionStats);
        
        // 首次加载时生成唯一颜色并缓存
        const randomColor = () => Math.floor(Math.random() * 255);
        const companyColor = `rgb(${randomColor()}, ${randomColor()}, ${randomColor()})`;
        this.companyColorCache.set(company.Id, companyColor);
        
        // 生成并缓存该企业的图表数据集
        this.updateCompanyDataset(company.Id, companyColor);
      }
    }

    this.selectedCompanies = companies;
    
    // 复用已有颜色,更新当前选中企业的数据集(适配toggle值变化)
    for (const company of companies) {
      const color = this.companyColorCache.get(company.Id);
      if (color) {
        this.updateCompanyDataset(company.Id, color);
      }
    }
    
    this.setupChart();
}

// 提取数据集更新逻辑为独立方法,复用代码
updateCompanyDataset(companyId: number, color: string) {
    const interventionStats = this.allInterventionStats.get(companyId);
    if (!interventionStats) return;
    
    const filteredData: InterventionData[] = interventionStats.filter(x => this.selectedToggleValue === '2' ? x.IsBody : !x.IsBody);
    const dataForGraph = this.calculationMonths.map(month => filteredData.find(x => month.isSame(x.Period)) || null);
    if (!dataForGraph) return;
    
    const company = this.companies.find(x => x.Id === companyId);
    if (!company) return;
    
    const datasets: ChartDataset[] = [
        {
          data: dataForGraph.map(x => x !== null ? x.AverageConversationEval : null),
          fill: false,
          borderColor: color,
          backgroundColor: color,
          label: company.Name,
          cubicInterpolationMode: 'monotone',
          spanGaps: true,
          segment: {
            borderDash: (ctx) => {
              return ctx.p0.skip || ctx.p1.skip ? [this.dashLength, this.dashSpace] : undefined;
            },
          }
        },
    ];
    this.companyDataCache.set(companyId, datasets);
}

setupChart() {
    if (!this.selectedCompanies.length) {
      const companyItem = this.companies.find(item => item.Id === -1);
      this.selectedCompanies = [companyItem];
    }

    const datasets: ChartDataset[] = flatten(
      this.selectedCompanies.map(dropdownItem => this.companyDataCache.get(dropdownItem.Id) || []));

    const lowerBound = 1;
    const upperBound = 5;

    const chartData: ChartData = {
      labels: this.createChartLabels(),
      datasets
    };

    this.legend = datasets
      .filter((dataset, index) => datasets
        .findIndex(x => x.label === dataset.label && x.backgroundColor === dataset.backgroundColor) === index)
      .map(dataset => ({
        text: dataset.label,
        fillStyle: dataset.backgroundColor as string,
        strokeStyle: dataset.borderColor as string
      }));
}

关键修改点

  1. 新增companyColorCache:专门存储每个企业的唯一颜色,确保颜色持久化不丢失。
  2. 颜色生成时机调整:仅在企业首次加载时生成颜色,避免重复生成导致颜色重置。
  3. 提取复用方法:将数据集更新逻辑封装为updateCompanyDataset,减少重复代码,同时保证颜色复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 13:01:41