diff --git a/common/changes/@visactor/vchart/feat-add-auto-flow-in-trae_2025-12-23-06-19.json b/common/changes/@visactor/vchart/feat-add-auto-flow-in-trae_2025-12-23-06-19.json deleted file mode 100644 index e41a8f7680..0000000000 --- a/common/changes/@visactor/vchart/feat-add-auto-flow-in-trae_2025-12-23-06-19.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "docs: chore(trae): add Trae jobs: auto-flow, smart changelog, PR pipeline", - "type": "patch", - "packageName": "@visactor/vchart" - } - ], - "packageName": "@visactor/vchart", - "email": "lixuef1313@163.com" -} diff --git a/common/changes/@visactor/vchart/feat-optimiz-heatmap_2025-12-25-07-13.json b/common/changes/@visactor/vchart/feat-optimiz-heatmap_2025-12-25-07-13.json new file mode 100644 index 0000000000..1c7fc7951a --- /dev/null +++ b/common/changes/@visactor/vchart/feat-optimiz-heatmap_2025-12-25-07-13.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "chore(vchart): 热力图矩形单元支持非等宽高;默认形状统一为 rect;修复颜色映射字段访问;新增单测与浏览器示例", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} \ No newline at end of file diff --git a/packages/vchart/__tests__/runtime/browser/test-page/heatmap-rect.ts b/packages/vchart/__tests__/runtime/browser/test-page/heatmap-rect.ts new file mode 100644 index 0000000000..367e8f778d --- /dev/null +++ b/packages/vchart/__tests__/runtime/browser/test-page/heatmap-rect.ts @@ -0,0 +1,36 @@ +import { default as VChart } from '../../../../src/index'; + +/** + * 浏览器示例:热力图矩形单元非等宽高验证 + */ +const run = async () => { + const spec = { + type: 'heatmap', + width: 500, + height: 400, + xField: 'x', + yField: 'y', + valueField: 'v', + animation: false, + tooltip: { visible: true }, + data: { + id: 'data', + values: [ + { x: 'A', y: '1', v: 10 }, + { x: 'A', y: '2', v: 20 }, + { x: 'A', y: '3', v: 30 }, + { x: 'A', y: '4', v: 40 }, + { x: 'B', y: '1', v: 50 }, + { x: 'B', y: '2', v: 60 }, + { x: 'B', y: '3', v: 70 }, + { x: 'B', y: '4', v: 80 } + ] + } + } as any; + + const vchart = new VChart(spec, { dom: 'chart' }); + await vchart.renderAsync(); + (window as any)['vchart'] = vchart; +}; + +run(); diff --git a/packages/vchart/__tests__/unit/chart/heatmap.test.ts b/packages/vchart/__tests__/unit/chart/heatmap.test.ts new file mode 100644 index 0000000000..dbc9d266ae --- /dev/null +++ b/packages/vchart/__tests__/unit/chart/heatmap.test.ts @@ -0,0 +1,68 @@ +import { DataSet, DataView, csvParser } from '@visactor/vdataset'; +import { VChart } from '../../../src/vchart-all'; +import { createCanvas, removeDom } from '../../util/dom'; +import type { IHeatmapChartSpec } from '../../../src'; + +/** + * 热力图 Rect 单元尺寸验证(支持非等宽高) + * - 验证系列默认形状为 'rect' + * - 验证单元图元的 size 返回二维并在 X/Y 轴带宽不等时宽高不同 + */ +describe('heatmap rect cell size', () => { + let canvasDom: HTMLCanvasElement; + let vchart: VChart; + + beforeEach(() => { + canvasDom = createCanvas(); + canvasDom.style.position = 'relative'; + canvasDom.style.width = '500px'; + canvasDom.style.height = '500px'; + canvasDom.width = 500; + canvasDom.height = 500; + }); + + afterEach(() => { + removeDom(canvasDom); + vchart.release(); + }); + + it('rect shape and non-equal size per cell', async () => { + const dataSet = new DataSet(); + dataSet.registerParser('csv', csvParser); + const dataView = new DataView(dataSet); + + // x 两类,y 四类,确保轴带宽不同 + const data = `x,y,v\nA,1,10\nA,2,20\nA,3,30\nA,4,40\nB,1,50\nB,2,60\nB,3,70\nB,4,80`; + dataView.parse(data, { type: 'csv' }); + + vchart = new VChart( + { + type: 'heatmap', + xField: 'x', + yField: 'y', + valueField: 'v', + data: dataView, + animation: false, + tooltip: { visible: false } + } as IHeatmapChartSpec, + { + renderCanvas: canvasDom, + autoFit: true, + animation: false + } + ); + + await vchart.renderAsync(); + + const series = vchart.getChart().getAllSeries()[0]; + expect(series.getDefaultShapeType()).toBe('rect'); + + const datum = (series as any).getViewData().latestData[0]; + const cellMark = (series as any).getActiveMarks()[0]; + const size = cellMark.getAttribute('size', datum); + + expect(Array.isArray(size)).toBe(true); + expect(size.length).toBe(2); + expect(size[0]).not.toBe(size[1]); + }); +}); diff --git a/packages/vchart/src/series/heatmap/heatmap.ts b/packages/vchart/src/series/heatmap/heatmap.ts index 91948feb2d..3ad2f3d783 100644 --- a/packages/vchart/src/series/heatmap/heatmap.ts +++ b/packages/vchart/src/series/heatmap/heatmap.ts @@ -129,12 +129,15 @@ export class HeatmapSeries ex ); } - // 通用的默认颜色映射 用户设置优先级比这个高,会在setStyle中处理 + /** + * 获取默认颜色映射配置 + * 修复字段访问为 this.getFieldValue()[0] + */ getColorAttribute() { return { // TODO: 为热力图实现默认线性颜色 scale scale: this._option.globalScale.getScale('color') ?? this._getDefaultColorScale(), - field: this.getFieldValue[0] + field: this.getFieldValue()[0] }; } @@ -164,8 +167,12 @@ export class HeatmapSeries ex this._cellMark && this._tooltipHelper.activeTriggerSet.mark.add(this._cellMark); } + /** + * 获取系列默认图元形状类型 + * 改为返回 'rect',以与主题保持一致并支持非等宽高的热力图单元 + */ getDefaultShapeType(): string { - return 'square'; + return 'rect'; } getDimensionField(): string[] { diff --git a/packages/vchart/src/theme/builtin/common/series/heatmap.ts b/packages/vchart/src/theme/builtin/common/series/heatmap.ts index ab82e81ea4..6697536abf 100644 --- a/packages/vchart/src/theme/builtin/common/series/heatmap.ts +++ b/packages/vchart/src/theme/builtin/common/series/heatmap.ts @@ -3,7 +3,7 @@ import type { IHeatmapSeriesTheme } from '../../../../series/heatmap/interface'; export const heatmap: IHeatmapSeriesTheme = { cell: { style: { - shape: 'square', + shape: 'rect', fillOpacity: 1 } },