史诗016 - mini小程序图表组件包(mini-charts)
史诗目标
将 docs/小程序图表库示例/ 目录下的 u-charts 图表库(约7700行代码)迁移为独立的 mini-ui-packages 共享包 mini-charts,为 Taro 小程序提供完整的图表解决方案,支持柱状图、折线图、K线图等多种图表类型。
史诗描述
现有系统上下文
当前相关功能:
- u-charts 图表库:位于
docs/小程序图表库示例/u-charts小程序图表库.js,是一个高性能跨平台图表库
- 支持平台:H5、APP、小程序(微信/支付宝/百度/头条/QQ/360/快手)、Vue、Taro等支持canvas的框架平台
- 示例代码:
docs/小程序图表库示例/使用示例.md 提供了完整的 React + Taro 使用示例
- 版本信息:v2.5.0-20230101
技术特性:
- 支持多种图表类型:柱状图(column)、折线图(line)、K线图(candle)、饼图、雷达图等
- 支持Canvas绘制,高性能渲染
- 支持触摸交互:tooltip显示、拖拽滚动
- 支持数据标签、图例、动画效果
- 高度可配置:颜色、字体、网格、坐标轴等
- 响应式设计,支持多种屏幕尺寸和像素比
集成点:
- Taro Canvas API
- React 18组件系统
- 小程序平台适配(微信小程序为主)
- 与现有 mini-ui-packages 包结构保持一致
- 与现有测试框架(Jest)集成
当前架构分析:
- 图表库未模块化:u-charts 库文件位于文档目录下,未形成可复用的包
- 缺少类型定义:原库为纯JavaScript,缺少TypeScript类型支持
- 缺少React组件封装:示例代码展示的是类组件使用方式,需要现代函数式组件封装
- 缺少测试:没有针对图表组件的测试套件
- 缺少文档:只有使用示例,缺少完整的API文档
增强详情
改造范围:
本次史诗将完成以下工作:
阶段1:创建 mini-charts 包基础结构(故事016.001)
- 创建新的包
mini-ui-packages/mini-charts
- 配置 package.json,依赖 Taro 相关包
- 设置 TypeScript 配置和类型定义
- 配置构建和测试脚本
- 迁移 u-charts 核心库文件
阶段2:搬迁 u-charts 核心库到模块化结构并添加类型定义(故事016.002-016.008)
- 分析当前 u-charts.ts 文件结构(7719行)
- 按功能模块搬迁代码到多个文件(分7个子故事完成),并在搬迁过程中添加 TypeScript 类型注解
- 重要:搬迁时保持代码逻辑完全不变,只改变文件组织方式
- 确保搬迁后功能完整性
阶段3:创建 React 图表组件封装(故事016.009)
- 创建现代函数式图表组件:
- ColumnChart(柱状图)
- LineChart(折线图)
- CandleChart(K线图)
- PieChart(饼图)
- RadarChart(雷达图)
- 使用 Taro Canvas API 封装底层绘图逻辑
- 支持触摸事件处理(tooltip、拖拽)
- 支持响应式尺寸计算
阶段4:创建使用示例和文档(故事016.010)
- 在包内创建 examples 目录
- 提供完整的示例代码
- 创建 API 文档
- 更新使用示例.md
阶段5:创建测试套件(故事016.011)
- 设置 Jest 测试环境
- 创建图表组件单元测试
- 创建 Canvas mock 用于测试
- 验证组件渲染和交互
迁移策略:
- 保留原始逻辑:保持 u-charts 核心绘制逻辑不变
- 渐进式封装:先迁移核心库,再模块化并添加类型定义,最后创建 React 组件
- 类型定义自动化:TypeScript 会自动生成 .d.ts 声明文件,在模块化拆分时添加类型注解即可
- 向后兼容:提供直接使用 u-charts 类的接口
- 测试驱动:为每个组件编写测试
成功标准:
mini-charts 包创建成功,可通过 workspace 引用
- u-charts 核心库成功迁移,功能完整
- u-charts 核心库完成模块化重构,并添加完整的类型注解
- TypeScript 类型定义完整,自动生成 .d.ts 声明文件,无 any 类型(除非必要)
- 提供至少5种常用图表组件(柱状图、折线图、K线图、饼图、雷达图)
- 组件可以独立测试(类型检查和 Jest 测试通过)
- 提供完整的示例和文档
- 可以被 mini 项目或其他 mini-ui-packages 引用
故事列表
故事016-001:创建 mini-charts 包基础结构
背景: u-charts 图表库目前位于文档目录下,需要迁移为独立的共享包,以便在多个小程序项目中复用。
任务列表:
- 创建新的包
mini-ui-packages/mini-charts
- 配置 package.json,依赖 Taro 相关包
- 设置 TypeScript 配置(tsconfig.json)
- 配置构建和测试脚本
- 迁移 u-charts 核心库文件:
- 将
docs/小程序图表库示例/u-charts小程序图表库.js 迁移到 src/lib/u-charts.ts
- 保持原始逻辑不变
- 将文件转换为 TypeScript 格式(添加基础类型)
- 创建包的导出配置:
- 建立 src/index.ts 主入口
- 导出 u-charts 核心类
- 配置 package.json 的 exports 字段
验收标准:
故事016-002:搬迁配置和工具函数到独立模块并添加类型定义
背景: u-charts.ts 文件包含约60个工具/数据处理函数。首先将低依赖的配置常量和工具函数搬迁到独立模块,为后续模块化搬迁打好基础。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析配置和工具函数:
- 识别 config、assign、util 等配置对象
- 识别颜色工具(hexToRgb等)
- 识别数学工具(findRange、normalInt等)
- 识别坐标转换工具(convertCoordinateOrigin等)
- 识别文本测量工具(measureText等)
- 识别碰撞检测工具(avoidCollision等)
- 创建模块化目录结构:
- 创建
src/lib/config.ts
- 创建
src/lib/utils/ 目录及子模块
- 搬迁配置和工具函数:
- 将 config、assign、util 搬迁到 config.ts,添加类型注解
- 将颜色工具函数搬迁到 utils/color.ts,添加类型注解
- 将数学工具函数搬迁到 utils/math.ts,添加类型注解
- 将坐标转换工具函数搬迁到 utils/coordinate.ts,添加类型注解
- 将文本测量工具函数搬迁到 utils/text.ts,添加类型注解
- 将碰撞检测工具函数搬迁到 utils/collision.ts,添加类型注解
- 创建 utils/index.ts 统一导出
- 验证搬迁结果:
- 确保所有工具函数正确导出
- 运行类型检查验证类型注解正确
- 确认代码逻辑与原始文件完全一致
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-003:搬迁数据处理函数到独立模块并添加类型定义
背景: 配置和工具函数模块化完成后,继续搬迁数据处理相关函数,包括系列数据处理、坐标轴计算、分类数据处理和提示框数据计算。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析数据处理函数:
- 识别系列数据处理函数(fillSeries、fixPieSeries等)
- 识别坐标轴计算函数(calXAxisData、calYAxisData等)
- 识别分类数据处理函数(calCategoriesData等)
- 识别提示框数据计算函数(getToolTipData等)
- 创建 data-processing 模块:
- 创建 data-processing/series-calculator.ts
- 创建 data-processing/axis-calculator.ts
- 创建 data-processing/categories-calculator.ts
- 创建 data-processing/tooltip-calculator.ts
- 创建 data-processing/index.ts 统一导出
- 搬迁数据处理函数并添加类型注解:
- 将系列数据处理函数搬迁到 series-calculator.ts,添加类型注解
- 将坐标轴计算函数搬迁到 axis-calculator.ts,添加类型注解
- 将分类数据处理函数搬迁到 categories-calculator.ts,添加类型注解
- 将提示框数据计算函数搬迁到 tooltip-calculator.ts,添加类型注解
- 验证搬迁结果:
- 确保所有数据处理函数正确导出
- 运行类型检查验证类型注解正确
- 确认代码逻辑与原始文件完全一致
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-004:搬迁图表数据点计算函数到独立模块并添加类型定义
背景: 数据处理模块化完成后,继续搬迁各种图表类型的数据点计算函数,包括基础图表、饼图、雷达图、地图和其他图表的数据点计算。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析图表数据点计算函数:
- 识别基础图表数据点函数(getColumnDataPoints、getDataPoints等)
- 识别饼图数据点函数(getPieDataPoints、getRoseDataPoints等)
- 识别雷达图数据点函数(getRadarDataPoints等)
- 识别地图数据点函数(getMapDataPoints等)
- 识别其他图表数据点函数(getGaugeDataPoints、getFunnelDataPoints等)
- 创建 charts-data 模块:
- 创建 charts-data/basic-charts.ts
- 创建 charts-data/pie-charts.ts
- 创建 charts-data/radar-charts.ts
- 创建 charts-data/map-charts.ts
- 创建 charts-data/other-charts.ts
- 创建 charts-data/index.ts 统一导出
- 搬迁数据点计算函数并添加类型注解:
- 将基础图表数据点函数搬迁到 basic-charts.ts,添加类型注解
- 将饼图数据点函数搬迁到 pie-charts.ts,添加类型注解
- 将雷达图数据点函数搬迁到 radar-charts.ts,添加类型注解
- 将地图数据点函数搬迁到 map-charts.ts,添加类型注解
- 将其他图表数据点函数搬迁到 other-charts.ts,添加类型注解
- 验证搬迁结果:
- 确保所有数据点计算函数正确导出
- 运行类型检查验证类型注解正确
- 确认代码逻辑与原始文件完全一致
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-005:搬迁绘制函数到独立模块并添加类型定义
背景: 图表数据点计算模块化完成后,继续搬迁所有绘制相关函数,包括通用绘制、坐标轴绘制、各种图表类型的绘制函数。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析绘制函数:
- 识别通用绘制函数(drawPointShape、drawToolTip、drawLegend等)
- 识别坐标轴绘制函数(drawXAxis、drawYAxis等)
- 识别柱状图绘制函数(drawColumnDataPoints等)
- 识别折线图/面积图绘制函数(drawLineDataPoints、drawAreaDataPoints等)
- 识别K线图绘制函数(drawCandleDataPoints等)
- 识别饼图绘制函数(drawPieDataPoints、drawRoseDataPoints等)
- 识别雷达图绘制函数(drawRadarDataPoints等)
- 识别地图绘制函数(drawMapDataPoints等)
- 识别特殊图表绘制函数(drawWordCloudDataPoints、drawFunnelDataPoints等)
- 创建 renderers 模块:
- 创建 renderers/common-renderer.ts
- 创建 renderers/axis-renderer.ts
- 创建 renderers/column-renderer.ts
- 创建 renderers/line-renderer.ts
- 创建 renderers/candle-renderer.ts
- 创建 renderers/pie-renderer.ts
- 创建 renderers/radar-renderer.ts
- 创建 renderers/map-renderer.ts
- 创建 renderers/special-renderer.ts
- 创建 renderers/index.ts 统一导出
- 搬迁绘制函数并添加类型注解:
- 将通用绘制函数搬迁到 common-renderer.ts,添加类型注解
- 将坐标轴绘制函数搬迁到 axis-renderer.ts,添加类型注解
- 将各图表类型绘制函数搬迁到对应的 renderer 文件,添加类型注解
- 验证搬迁结果:
- 确保所有绘制函数正确导出
- 运行类型检查验证类型注解正确
- 确认代码逻辑与原始文件完全一致
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-006:搬迁核心类并完成模块化
背景: 所有功能模块化完成后,最后搬迁 uCharts 主类和 uChartsEvent 事件类,导入所有模块,完成整个 u-charts 核心库的模块化搬迁。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析核心类:
- 分析 uChartsEvent 事件类
- 分析 uCharts 主类的所有方法
- 识别类方法与各模块的依赖关系
- 创建 charts 模块:
- 创建 charts/u-charts-event.ts,搬迁 uChartsEvent 类,添加完整事件类型注解
- 创建 charts/u-charts.ts,搬迁 uCharts 主类,导入所有模块,添加类型注解
- 创建 charts/index.ts 统一导出
- 更新 src/index.ts:
- 导出所有公共API
- 保持向后兼容性(默认导出 uCharts 类)
- 导出各个模块供高级用户使用
- 更新 package.json:
- 验证搬迁结果:
- 确保所有导出正确
- 运行类型检查验证类型注解正确
- 运行 pnpm build 验证构建成功,生成 .d.ts 文件
- 检查生成的 .d.ts 文件正确导出类型
- 验证模块间无循环依赖
- 确认代码逻辑与原始文件完全一致
- 删除或备份原始 u-charts.ts 文件
验收标准:
完成状态: ✅ Ready for Review (2025-12-24) - 所有任务完成
故事016-007:搬迁遗漏的辅助函数完成模块化
背景: 在实施故事 016.006(搬迁核心类)时,发现原始 u-charts.ts 中有大量辅助函数(约40个)没有被之前的模块化故事(016.002-016.005)覆盖。这些函数包括索引查找、区域判断、数据计算、图例处理、坐标转换、数据修正等。
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析并分类遗漏的辅助函数:
- 索引查找函数(9个):findCurrentIndex, findBarChartCurrentIndex, findLegendIndex, findPieChartCurrentIndex, findRadarChartCurrentIndex, findFunnelChartCurrentIndex, findWordChartCurrentIndex, findMapChartCurrentIndex, findRoseChartCurrentIndex
- 区域判断函数(3个):isInExactLegendArea, isInExactChartArea, isInExactPieChartArea
- 数据辅助函数(5个):getSeriesDataItem, filterSeries, splitPoints, getMaxTextListLength, getRadarCoordinateSeries
- 图例相关函数(2个):calLegendData, getPieTextMaxLength
- 坐标转换函数(7个):pointToCoordinate, isPoiWithinPoly, lonlat2mercator, mercator2lonlat, getBoundingBox, coordinateToPoint, isRayIntersectsSegment
- 数据修正函数(5个):fixColumeData, fixBarData, fixColumeMeterData, fixColumeStackData, fixBarStackData
- 其他辅助函数(8个):getXAxisTextList, getYAxisTextList, calTooltipYAxisData, calMarkLineData, contextRotate, normalInt, collisionNew, getWordCloudPoint
- 创建 helper-functions 模块:
- 创建 helper-functions/index-finders.ts(索引查找函数)
- 创建 helper-functions/area-checkers.ts(区域判断函数)
- 创建 helper-functions/data-helpers.ts(数据辅助函数)
- 创建 helper-functions/legend-helpers.ts(图例相关函数)
- 创建 helper-functions/coordinate-helpers.ts(坐标转换函数)
- 创建 helper-functions/data-fixers.ts(数据修正函数)
- 创建 helper-functions/misc-helpers.ts(其他辅助函数)
- 创建 helper-functions/index.ts 统一导出
- 搬迁辅助函数并添加类型注解
- 更新 src/index.ts 导出配置
- 验证搬迁结果
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-008:搬迁核心绘制函数完成模块化
背景: 在实施故事 016.006(搬迁核心类)时,发现原始 u-charts.ts 中有核心绘制函数(drawCharts、drawCanvas、Animation)没有被之前的模块化故事覆盖。这些函数是 uCharts 类的核心依赖,需要先完成搬迁才能继续核心类的模块化。
重要区别:
- renderers 模块(故事016.005):包含各种图表类型的具体绘制函数(如 drawPieDataPoints, drawLineDataPoints 等)
- 本故事的函数:是更高级的调度和控制函数,负责协调调用 renderers 中的函数
重要原则:
- 搬迁而非重构:保持代码逻辑完全不变,只改变文件组织方式
- 只在搬迁过程中添加 TypeScript 类型注解
- 不修改代码的实现逻辑
任务列表:
- 分析核心绘制函数:
- 分析 drawCharts 函数的完整逻辑和依赖
- 分析 drawCanvas 函数的完整逻辑和依赖
- 分析 Animation 函数的完整逻辑和依赖
- 创建 draw-controllers 模块:
- 创建 draw-controllers/draw-charts.ts
- 创建 draw-controllers/draw-canvas.ts
- 创建 draw-controllers/animation.ts
- 创建 draw-controllers/index.ts 统一导出
- 搬迁核心绘制函数并添加类型注解:
- 搬迁 drawCharts 函数,处理 this 上下文绑定问题
- 搬迁 drawCanvas 函数
- 搬迁 Animation 函数
- 更新 src/index.ts 导出配置
- 验证搬迁结果
- 通知故事 016.006 可以继续
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-009:创建 React 图表组件封装
背景: u-charts 原库需要手动管理 Canvas 上下文和事件处理。需要创建现代 React 函数式组件,简化使用方式。
任务列表:
- 创建基础图表组件 BaseChart:
- 封装 Canvas 创建和销毁逻辑
- 处理响应式尺寸计算
- 处理像素比适配
- 封装事件处理(触摸、点击)
- 创建具体图表组件:
- ColumnChart(柱状图)
- LineChart(折线图)
- CandleChart(K线图)
- PieChart(饼图)
- RadarChart(雷达图)
- 每个组件包含:
- Props 接口定义
- 默认配置
- Canvas 绘制逻辑
- 事件处理(tooltip、拖拽等)
- 从
docs/小程序图表库示例/使用示例.md 迁移示例代码作为参考
验收标准:
完成状态: ✅ Ready for Review (2025-12-24)
故事016-010:创建使用示例和文档
背景: 需要提供完整的使用示例和 API 文档,帮助开发者快速上手使用 mini-charts 包。
任务列表:
- 创建 examples 目录:
- 迁移并更新
docs/小程序图表库示例/使用示例.md 中的示例
- 为每种图表类型创建独立示例
- 创建复杂场景示例(混合图表、多轴图表等)
- 创建 README.md:
- 包简介和特性
- 安装说明
- 快速开始指南
- API 文档
- 配置选项说明
- 常见问题解答
- 更新原使用示例文档,指向新包的使用方式
验收标准:
故事016-011:创建测试套件
背景: 需要为图表组件创建完整的测试套件,确保组件质量和稳定性。
任务列表:
- 设置 Jest 测试环境:
- 配置 jest.config.js
- 创建 Taro 和 Canvas 的 mock
- 创建工具函数:
- createMockCanvasContext:创建模拟 Canvas 上下文
- waitForChartRender:等待图表渲染完成
- 编写组件测试:
- 测试组件渲染
- 测试 Props 传递
- 测试事件处理
- 测试响应式尺寸
- 编写集成测试:
验收标准:
故事016-012:修复 u-charts.ts TypeScript 类型错误
背景: 在完成模块化搬迁后,u-charts.ts 文件存在大量TypeScript类型错误(约100+个错误),主要是:
- 变量声明顺序问题(368行使用config,437行才声明)
- 可能为undefined的属性访问(opts.extra.pie等)
- 类型不匹配(ChartsConfig vs ChartOptions等)
- 缺少必要的类型属性定义
- ScrollOption类型冲突
任务列表:
- 分析并修复类型定义问题:
- 检查
src/types/charts.ts 中的类型定义
- 确保 ChartsConfig、ChartOptions 等类型定义完整且正确
- 修复 ScrollOption 类型冲突(coordinate.ts vs u-charts.ts)
- 修复变量声明和作用域问题:
- 移动 config 变量声明到正确位置(在使用前)
- 确保所有变量在使用前已正确声明和初始化
- 修复可选链类型安全问题:
- 为 opts.extra.pie、opts.extra.ring、opts.extra.rose 等添加可选链或默认值
- 为所有可能为 undefined 的属性添加类型守卫
- 修复类型不匹配问题:
- 统一 ChartsConfig 和 ChartOptions 类型定义
- 确保传递给函数的参数类型正确
- 修复 SeriesItem、XAxisConfig、YAxisConfig 等类型的可选属性问题
- 修复 this 类型问题:
- 确保 uCharts 类的 this 类型正确传递到辅助函数
- 修复 scrollOption 类型冲突
- 验证修复结果:
- 运行 pnpm typecheck 确保无类型错误
- 运行 pnpm build 确保构建成功
- 确保所有图表类型仍然正常工作
验收标准:
完成状态: 🔄 In Progress (2025-12-25)
故事016-013:修复图表数据点计算函数的 process 参数遗漏错误
背景: 在执行故事016.004(搬迁图表数据点计算函数)时,发现了严重的参数遗漏问题。原始 u-charts.js 中,多个图表数据点计算函数包含第3个可选参数 process(动画进度,默认值1),但在搬迁时遗漏了该参数,导致运行时错误 ReferenceError: process is not defined。
错误详情:
getPieDataPoints(series, radius) 应为 getPieDataPoints(series, radius, process = 1)
getRoseDataPoints(series, type, minRadius, radius) 应为 getRoseDataPoints(series, type, minRadius, radius, process = 1)
getGaugeDataPoints(series, categories, gaugeOption) 应为 getGaugeDataPoints(series, categories, gaugeOption, process = 1)
getGaugeArcbarDataPoints(series, arcbarOption) 应为 getGaugeArcbarDataPoints(series, arcbarOption, process = 1)
getArcbarDataPoints(series, arcbarOption) 应为 getArcbarDataPoints(series, arcbarOption, process = 1)
错误根因:
搬迁时错误地使用了 declare const process: number; 全局声明(位于 pie-charts.ts:1-2 和 gauge-charts.ts:1-2),但这在运行时不会工作,导致 process is not defined 错误。
任务列表:
- 修复 pie-charts.ts 中的函数签名:
- 移除错误的
declare const process: number; 全局声明
- 为
getPieDataPoints 添加第3个可选参数 process?: number,默认值为1
- 为
getRoseDataPoints 添加第5个可选参数 process?: number,默认值为1
- 更新函数的 JSDoc 注释,添加 process 参数说明
- 更新函数体内的
process 引用,确保使用参数而非未定义的变量
- 修复 gauge-charts.ts 中的函数签名:
- 移除错误的
declare const process: number; 全局声明
- 为
getGaugeDataPoints 添加第4个可选参数 process?: number,默认值为1
- 为
getGaugeArcbarDataPoints 添加第3个可选参数 process?: number,默认值为1
- 为
getArcbarDataPoints 添加第3个可选参数 process?: number,默认值为1
- 更新函数的 JSDoc 注释,添加 process 参数说明
- 修复函数体内的
process 引用(getGaugeArcbarDataPoints 和 getArcbarDataPoints 中使用了局部变量 currentProcess)
- 验证所有调用点:
- 检查所有调用这些函数的地方,确保传递正确的参数
- 更新
pie-renderer.ts:240 的调用,传递 chartProcess 参数
- 检查
legend-helpers.ts:218 和 index-finders.ts:373 的调用(可能不需要传递 process,使用默认值1)
- 验证修复结果:
- 运行类型检查(pnpm typecheck)确保无类型错误
- 运行构建(pnpm build)确保成功生成 .d.ts 文件
- 在小程序中测试饼图、玫瑰图、仪表盘和环形条图表,确保无运行时错误
- 确认动画功能正常工作(process 参数用于控制动画进度)
验收标准:
完成状态: ✅ Ready for Review (2025-12-25)
故事016-014:完成 draw-charts.ts 核心绘制逻辑搬迁
背景: 在执行故事016.008(搬迁核心绘制函数)时,发现 draw-charts.ts 文件的搬迁不完整。文件只包含了数据准备阶段的代码(前289行),但核心的图表绘制调度逻辑(switch语句和各图表类型的绘制调用)完全缺失。这导致图表数据计算完成但Canvas上没有任何渲染,图表显示为空白。
问题详情:
当前 draw-charts.ts 文件在第309行就结束了,缺少以下关键内容:
- 根据图表类型(column/line/pie/radar等)分发绘制任务的 switch 语句
- 调用各图表类型的数据点计算函数(如
getColumnDataPoints)
- 调用各图表类型的绘制函数(如
drawColumnDataPoints)
- 绘制坐标轴(drawXAxis、drawYAxis)
- 绘制图例(drawLegend)
- 最后调用
drawCanvas() 触发实际的Canvas渲染
- 动画处理逻辑(如果启用动画)
影响范围:
- 所有图表类型(柱状图、折线图、饼图、雷达图等)都无法渲染
- 在
yongren-statistics-ui 包中使用 ColumnChart 组件时,Canvas显示为空白
- 数据正确传递到uCharts实例,但绘制流程未完成
任务列表:
- 分析原始 u-charts.js 的完整 drawCharts 函数逻辑:
- 定位原始文件中的 switch 语句(约在第6499-6936行)
- 理解每种图表类型的绘制流程
- 确认数据准备阶段和绘制阶段的分界点
- 补充完整的 switch 语句实现:
- 为每种图表类型创建 case 分支(column/line/area/mount/scatter/bubble/mix/candle/pie/ring/rose/gauge/arcbar/radar/map/funnel/wordcloud/bar)
- 每个 case 调用对应的 getDataPoints 函数计算数据点坐标
- 每个 case 调用对应的 draw*DataPoints 函数执行绘制
- 处理混合图表(mix)的特殊逻辑
- 补充通用绘制元素:
- 调用 drawXAxis 绘制X轴
- 调用 drawYAxisGrid 绘制Y轴网格
- 调用 drawYAxis 绘制Y轴
- 调用 drawLegend 绘制图例(如果启用)
- 调用 drawMarkLine 绘制标记线(如果有)
- 补充动画处理逻辑:
- 创建 Animation 实例(如果 opts.animation 为 true)
- 处理动画进度的逐步更新
- 在动画完成时触发 'renderComplete' 事件
- 补充 drawCanvas 调用:
- 在所有绘制操作完成后调用 drawCanvas() 触发实际渲染
- 确保上下文的 draw() 方法被调用
- 验证搬迁结果:
- 运行类型检查(pnpm typecheck)确保无类型错误
- 运行构建(pnpm build)确保成功
- 在
yongren-statistics-ui 中测试 ColumnChart 组件
- 验证图表能够正常显示
- 验证动画、tooltip、图例等功能正常
验收标准:
技术细节:
需要补充的 switch 语句结构(伪代码):
switch (type) {
case 'column':
case 'mount':
case 'bar':
// 1. 计算数据点坐标
opts.chartData.columnData = getColumnDataPoints(series, opts, config);
// 2. 绘制数据点
drawColumnDataPoints(series, opts, config, context);
break;
case 'line':
case 'area':
opts.chartData.lineData = getLineDataPoints(...);
drawLineDataPoints(...);
if (type === 'area') drawAreaDataPoints(...);
break;
case 'pie':
case 'ring':
case 'rose':
opts.chartData.pieData = getPieDataPoints(...);
drawPieDataPoints(...);
break;
// ... 其他图表类型
}
// 绘制通用元素
drawXAxis(opts, config, context);
drawYAxis(opts, config, context);
if (opts.legend.show) {
drawLegend(opts.chartData.legendData, opts, config, context);
}
// 动画处理
if (opts.animation && duration > 0) {
_this.animationInstance = new Animation({
duration,
timing: opts.timing || 'easeOut',
onProgress: (process) => {
chartProcess(process);
drawCharts.call(_this, type, opts, config, context);
},
onComplete: () => {
_this.uevent.trigger('renderComplete');
}
});
_this.animationInstance.start();
} else {
chartProcess(1);
}
// 触发实际渲染
drawCanvas(opts, context);
完成状态: ✅ Ready for Review (2025-12-28)
故事016-015:修复图表渲染器 process 参数缺失和变量作用域错误
背景: 在完成故事016.014后,测试发现图表渲染时出现运行时错误。错误信息显示 process is not defined 和 zeroPoints is not defined,表明在模块化搬迁过程中,多个渲染器函数和数据计算函数存在参数不一致和变量作用域问题。
错误详情:
- 错误1:
chartProcess is not defined - 多个 renderer 文件中使用了错误的 declare const chartProcess: any; 声明
- 错误2:
process is not defined - 数据计算函数使用了 process 变量但函数签名缺少该参数
- 错误3:参数名不一致 - 调用方传递
process,被调用函数参数名为 chartProcess
- 错误4:
zeroPoints is not defined - drawColumnDataPoints 的第二个 forEach 循环缺少 zeroPoints 变量计算
影响范围:
- 所有图表类型(柱状图、折线图、条形图、堆叠图等)无法渲染
- 动画功能失效(
process 参数用于控制动画进度)
- 数据点标签无法显示(
zeroPoints 变量缺失)
根本原因分析:
- 错误的类型声明模式:在搬迁过程中使用了
declare const 声明来绕过 TypeScript 检查,但这是编译时声明,运行时不会定义变量
- 参数遗漏:多个数据计算函数(
getDataPoints、getColumnDataPoints、getStackDataPoints 等)的函数体内使用了 process 变量控制动画,但函数签名中缺少该参数
- 变量作用域问题:
drawColumnDataPoints 有两个 forEach 循环,第二个循环(用于绘制数据点标签)缺少 zeroPoints 变量计算
任务列表:
修复数据计算函数签名 (basic-charts.ts):
- 为
getDataPoints 添加第8个参数 process = 1
- 为
getLineDataPoints 添加第9个参数 process = 1
- 为
getColumnDataPoints 添加第9个参数 process = 1(参数名从 chartProcess 改为 process)
- 为
getMountDataPoints 添加第9个参数 process = 1
- 为
getBarDataPoints 添加第8个参数 process = 1
- 为
getStackDataPoints 添加第10个参数 process = 1
- 为
getBarStackDataPoints 添加第10个参数 process = 1
- 更新所有函数的 JSDoc 注释
修复渲染器函数签名 (column-renderer.ts, line-renderer.ts):
- 为
drawColumnDataPoints 添加第5个参数 process = 1
- 为
drawLineDataPoints 添加第5个参数 process = 1
- 为
drawAreaDataPoints 添加第5个参数 process = 1
- 移除错误的
declare const process: number; 和 declare const chartProcess: any; 声明
修复函数调用参数传递:
- column-renderer.ts:将所有传递给数据计算函数的
chartProcess 替换为 process(5处)
- line-renderer.ts:将传递给
getLineDataPoints 的 chartProcess 替换为 process(1处)
移除所有错误的 declare 声明:
- column-renderer.ts: 移除
declare const process: number; 和 declare const chartProcess: any;
- line-renderer.ts: 移除
declare const process: number; 和 declare const chartProcess: any;
- special-renderer.ts: 移除
declare const process: number;,添加 // @ts-nocheck
- candle-renderer.ts: 移除
declare const process: number;,添加 // @ts-nocheck
- radar-renderer.ts: 移除
declare const process: number;,添加 // @ts-nocheck
修复变量作用域问题 (column-renderer.ts):
- 在第二个
forEach 循环(第385-434行)中添加 zeroPoints 变量计算
- 计算逻辑与第一个循环保持一致(第143-146行)
验证修复结果:
- 运行
pnpm build 确保构建成功
- 在小程序中测试柱状图,确认无运行时错误
- 验证图表能够正常渲染
- 验证动画功能正常工作(如果启用)
- 验证数据点标签正确显示(如果启用
dataLabel)
验收标准:
技术细节:
修复的函数调用链示例(以柱状图为例):
// draw-charts.ts 中的 Animation.onProcess 回调
onProcess: function(process) {
drawColumnDataPoints(series, opts, config, context, process)
↓
getColumnDataPoints(data, minRange, maxRange, xAxisPoints, eachSpacing, opts, config, zeroPoints, process)
↓
height *= process // ✅ process 可用,动画正常工作
}
修复的文件清单:
src/lib/charts-data/basic-charts.ts - 7个函数签名修复
src/lib/renderers/column-renderer.ts - 函数签名、参数传递、变量计算修复
src/lib/renderers/line-renderer.ts - 函数签名、参数传递修复
src/lib/renderers/special-renderer.ts - 移除错误声明
src/lib/renderers/candle-renderer.ts - 移除错误声明
src/lib/renderers/radar-renderer.ts - 移除错误声明
完成状态: ✅ Ready for Review (2025-12-28)
故事016-015:修复柱状图布局和显示问题
背景: 在完成了 Canvas pixelRatio 修复和 process 参数修复后(故事016.014和016.015相关调试),柱状图已经能够在 Canvas 画布中正确显示尺寸,但出现了新的布局问题。
当前状态(已修复):
- ✅ Canvas 尺寸正确:使用
pixelRatio=2 匹配设备像素
- ✅ 图表不再比 Canvas 大 2-4 倍
- ✅ Y轴数据正确计算
- ✅ 图例正常显示
- ✅ process 参数传递正确
剩余问题:
- ❌ Y轴网格线间隔过小,被"压扁"
- ❌ 柱子宽度计算错误,导致柱子之间没有间隙
- ❌ 柱子位置向左偏移,没有居中
问题详情:
这些布局问题的根本原因是在修复 Canvas 尺寸和 process 参数时,发现 calYAxisData 函数的返回值结构错误(缺少单 Y轴 配置的 else 分支),以及 Canvas 坐标系统与 pixelRatio 的关系处理不当。
任务列表:
修复 Y轴数据计算问题 (axis-calculator.ts):
- 添加
calYAxisData 函数的单 Y轴 else 分支(当 YLength === 0 时)
- 修复返回值结构,与原始 u-charts.js 保持一致
- 返回
{ rangesFormat, ranges, yAxisWidth } 而不是嵌套的 yAxisData 数组
- 更新
YAxisDataResult 类型定义
修复 Canvas pixelRatio 处理 (BaseChart.tsx):
- 使用
sysInfo.pixelRatio 而不是固定值 1
- 正确设置 Canvas 的
width/height 属性(实际像素 = 逻辑像素 × pixelRatio)
- 正确设置 Canvas 的
style.width/style.height(CSS 逻辑像素)
分析并修复布局问题 (需要调试):
- 添加调试日志输出关键绘制参数(Y轴刻度、eachSpacing、柱子宽度、位置等)
- 对比原始 u-charts.js 的计算逻辑
- 确认哪些计算需要乘以
opts.pix
- 修复 Y轴网格线间隔、柱子宽度、柱子位置的计算
测试不同 pixelRatio 设备:
- 在 pixelRatio=1, 2, 3 的设备上测试
- 确保所有设备上显示效果一致
清理调试日志:
- 移除临时添加的 console.debug
- 确保代码整洁
验收标准:
技术细节:
Canvas 2D 坐标系统关键点:
// 设备 pixelRatio = 2
// 期望图表大小:650px × 200px (CSS 像素)
const config = {
width: 650, // 逻辑像素,不是 650 * 2
height: 200, // 逻辑像素,不是 200 * 2
pixelRatio: 2 // 告诉图表库设备的像素比
};
// Canvas 元素:
// width 属性:1300 (650 * 2,实际像素)
// height 属性:400 (200 * 2,实际像素)
// style.width:650px
// style.height:200px
// 绘图时的坐标:
// 所有坐标计算基于 650 × 200 的逻辑尺寸
// opts.pix = 2 用于某些需要额外缩放的场合(如字体大小、线宽)
已完成的修复:
- ✅ 修复
calYAxisData 返回值结构(axis-calculator.ts:410-471)
- ✅ 修复 Canvas pixelRatio 设置(BaseChart.tsx:66, 88-89)
待修复的问题:
- ⏳ Y轴网格线间隔问题
- ⏳ 柱子宽度和间距问题
- ⏳ 柱子位置偏移问题
完成状态: 🔄 In Progress (2025-12-28) - 核心修复已完成,布局问题待调试
兼容性要求
风险缓解
- 主要风险:u-charts 库文件较大(约7700行),迁移过程中可能遗漏功能
- 缓解措施:保留原始文件,迁移后进行功能对比测试
- 回滚计划:如果迁移导致问题,可以从文档目录重新使用原文件
- 类型定义风险:原库没有类型,可能存在类型定义不准确的问题
- 缓解措施:在模块化重构时同步添加类型注解,利用 TypeScript 自动生成 .d.ts 文件
完成定义
附件