基于Highcharts的17个月图表年份计算问题(TypeScript)
Highcharts柱状图Tooltip年份计算错误修复
问题背景
现有一个涵盖17个月的Highcharts柱状图,包含回溯12个月与前瞻6个月的数据。当前为5月,回溯12个月的起点为5月,前瞻6个月的终点为11月。需要在tooltip中为每个月份显示对应年份,且并列的两列中,左侧列需显示对应年份的前一年(如左柱显示2022、右柱显示2023),但当前年份计算逻辑始终有误。
现有代码
private getSeriesDataFromGraphData(graphData: GetPreviousYearGraphData[]): Highcharts.PointOptionsObject[] { return graphData.map(({y, b2b, b2c, normal}) => ({y, b2b, b2c, normal})); } // Using the search-filters does not affect this graph. This graph is only affected when filtering between brands. private renderOrderAmountCompareOnBrand( strCurrencyCode: string, arrCategories: string[], arrPrevSeriesDataStock: GetPreviousYearGraphData[], arrPrevSeriesDataPre: GetPreviousYearGraphData[], arrSeriesDataStock: GetPreviousYearGraphData[], arrSeriesDataPre: GetPreviousYearGraphData[] ) { // Get the series data for each set of graph data const prevSeriesDataStock = this.getSeriesDataFromGraphData(arrPrevSeriesDataStock); const prevSeriesDataPre = this.getSeriesDataFromGraphData(arrPrevSeriesDataPre); const seriesDataStock = this.getSeriesDataFromGraphData(arrSeriesDataStock); const seriesDataPre = this.getSeriesDataFromGraphData(arrSeriesDataPre); this.OrderAmountComparedOnBrandChart = Highcharts.chart('claimsOrderAmountPerSalesChannel', { chart: { type: 'column' }, title: { text: 'Order amount compared on brand' }, xAxis: { categories: arrCategories }, yAxis: { allowDecimals: false, min: 0, title: { text: 'Brand order statistics' } }, tooltip: { formatter: function () { let strStyling = "display: flex; justify-content: space-between; gap: 20px;"; let startDate: Date = new Date(); startDate.setMonth(startDate.getMonth() - 12); let year = startDate.getFullYear(); if (!this.series.name.includes('Previous year')) { year += 1; } const GetPreviousYearGraphData = this.point as GetPreviousYearGraphData; return ` <b>${this.point.category} | ${this.series.name} | ${year}</b><br><br> <div style="${strStyling}"> <span><b>Sales staff:</b></span> ${Highcharts.numberFormat(GetPreviousYearGraphData.normal || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>B2B:</b></span> ${Highcharts.numberFormat(GetPreviousYearGraphData.b2b || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>B2C:</b></span> ${Highcharts.numberFormat(GetPreviousYearGraphData.b2c || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>Total:</b></span> ${Highcharts.numberFormat(this.y || 0, 0)} ${strCurrencyCode ?? ''} </div> `; }, useHTML: true }, plotOptions: { column: { stacking: 'normal', dataLabels: { enabled: false } } }, series: [ { name: 'Stock Previous year', data: prevSeriesDataStock, stack: 'Stock1' }, { name: 'Pre Previous year', data: prevSeriesDataPre, stack: 'Stock1' }, { name: 'Stock', data: seriesDataStock, stack: 'Stock' }, { name: 'Pre', data: seriesDataPre, stack: 'Stock' } ] as SeriesOptionsType[] } as Options ); }
问题分析
当前代码仅基于当前日期减12个月的固定逻辑计算年份,再通过系列名称判断是否加1,完全没有结合数据点对应的具体月份位置(回溯/前瞻期),无法适配跨年度的月份区间(比如回溯12个月包含去年5月到今年4月,前瞻6个月是今年5月到11月),导致年份显示与实际月份不匹配。
解决方案
结合当前月份、数据点索引、系列类型三个维度精准计算年份,修改后的tooltip formatter代码如下:
tooltip: { formatter: function () { let strStyling = "display: flex; justify-content: space-between; gap: 20px;"; const currentDate = new Date(); const currentYear = currentDate.getFullYear(); const currentMonth = currentDate.getMonth(); // 0代表1月,4代表5月 const pointIndex = this.point.index; const isPreviousYearSeries = this.series.name.includes('Previous year'); let targetYear: number; // 前12个数据点:回溯12个月(去年5月到今年4月) if (pointIndex < 12) { const targetMonthOffset = currentMonth + pointIndex; // 若偏移后月份超过12,说明是今年的月份,否则是去年的 targetYear = currentYear - (targetMonthOffset >= 12 ? 0 : 1); } else { // 后6个数据点:前瞻6个月(今年5月到11月) targetYear = currentYear; } // 前一年系列统一减1,实现左柱显示前一年的需求 if (isPreviousYearSeries) { targetYear -= 1; } const pointData = this.point as GetPreviousYearGraphData; return ` <b>${this.point.category} | ${this.series.name} | ${targetYear}</b><br><br> <div style="${strStyling}"> <span><b>Sales staff:</b></span> ${Highcharts.numberFormat(pointData.normal || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>B2B:</b></span> ${Highcharts.numberFormat(pointData.b2b || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>B2C:</b></span> ${Highcharts.numberFormat(pointData.b2c || 0, 0)} ${strCurrencyCode ?? ''}<br> </div> <div style="${strStyling}"> <span><b>Total:</b></span> ${Highcharts.numberFormat(this.y || 0, 0)} ${strCurrencyCode ?? ''} </div> `; }, useHTML: true },
逻辑说明
- 回溯期(前12个点):通过月份偏移量判断是否跨年度,动态计算基础年份
- 前瞻期(后6个点):直接使用当前年份
- 所有含“Previous year”的系列年份减1,满足左柱显示前一年的要求
- 适配任意当前月份,无需硬编码年份值
内容的提问来源于stack exchange,提问作者Mathias Kristensen
相关产品推荐
相关产品推荐

