Chart.js图表对象随机颜色分配异常问题排查
Chart.js 图表颜色异常问题修复
问题现象
当前使用Chart.js搭建图表时存在两个异常:
- 所有图表系列共用同一颜色
- 每次添加新企业时,所有已存在的图表系列颜色都会被替换为新的随机颜色
问题根源分析
- 颜色生成逻辑位置错误:
colorToUse定义在企业循环外部,导致所有企业复用同一个随机颜色,出现系列同色问题。 - 颜色未持久化缓存:每次调用
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 })); }
关键修改点
- 新增
companyColorCache:专门存储每个企业的唯一颜色,确保颜色持久化不丢失。 - 颜色生成时机调整:仅在企业首次加载时生成颜色,避免重复生成导致颜色重置。
- 提取复用方法:将数据集更新逻辑封装为
updateCompanyDataset,减少重复代码,同时保证颜色复用。
内容的提问来源于stack exchange,提问作者NewProgrammer1500
相关产品推荐
相关产品推荐

