Files
steel_prices_service/Sale/components/ec-canvas/CLAUDE.md
2026-01-07 10:13:21 +08:00

489 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[根目录](../../CLAUDE.md) > **components/ec-canvas**
---
# components/ec-canvas - ECharts 图表组件
> **模块状态**: ✅ 已完成
>
> **最后更新**: 2026-01-07 09:16:32
---
## 变更记录 (Changelog)
### 2026-01-07 09:16:32
- 生成组件文档
- 补充使用说明与配置项
- 添加常见问题与故障排查
### 2026-01-06
- 集成 ECharts 图表库
- 实现微信小程序 Canvas 适配
- 封装为通用组件
---
## 模块职责
**ec-canvas** 是 ECharts 图表组件,负责:
1. **图表渲染**:在微信小程序中渲染 ECharts 图表
2. **Canvas 适配**:适配小程序 Canvas 2D 接口
3. **事件处理**:处理触摸交互事件
4. **响应式布局**:自适应屏幕尺寸
---
## 入口与启动
### 组件路径
- **注册路径**`components/ec-canvas/ec-canvas`
- **物理路径**`components/ec-canvas/ec-canvas.js`
### 使用方式
```json
// 页面 JSON 配置
{
"usingComponents": {
"ec-canvas": "../../components/ec-canvas/ec-canvas"
}
}
```
```xml
<!-- 页面 WXML -->
<ec-canvas id="mychart-dom-line" canvas-id="mychart-line" ec="{{ ec }}"></ec-canvas>
```
---
## 对外接口
### 组件属性Properties
| 属性名 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| canvasId | String | 'ec-canvas' | Canvas 组件 ID |
| ec | Object | {} | 图表配置对象(必须包含 onInit 方法) |
| disableTouch | Boolean | false | 是否禁用触摸交互 |
### ec 对象结构
```javascript
ec: {
onInit: function(canvas, width, height, res) {
// 必须返回图表实例
const chart = echarts.init(canvas)
chart.setOption(option)
return chart
}
}
```
### 组件方法Methods
| 方法名 | 参数 | 说明 |
|--------|------|------|
| touchStart | event | 触摸开始事件 |
| touchMove | event | 触摸移动事件 |
| touchEnd | event | 触摸结束事件 |
---
## 关键依赖与配置
### 依赖文件
| 文件 | 用途 |
|------|------|
| `ec-canvas.js` | 组件逻辑91 行) |
| `ec-canvas.wxml` | 组件模板 |
| `ec-canvas.wxss` | 组件样式 |
| `ec-canvas.json` | 组件配置 |
| `echarts.js` | ECharts 库(简化版) |
| `wx-canvas.js` | Canvas 适配器 |
### 外部依赖
- **ECharts**:内置的简化版 ECharts 库
- **Canvas 2D**:微信小程序 Canvas 2D 接口
### 配置项
```javascript
// 组件配置
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object,
value: {}
}
}
})
```
---
## 数据模型
### 组件生命周期
```javascript
Component({
ready() {
// 1. 检查 ec 对象
if (!this.data.ec || !this.data.ec.onInit) {
console.warn('组件需绑定 ec 对象,且包含 onInit 方法')
return
}
// 2. 查询 Canvas 节点
const query = this.createSelectorQuery()
query.select(`#${this.data.canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
// 3. 初始化 Canvas
const canvasNode = res[0].node
const ctx = canvasNode.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
// 4. 设置 Canvas 尺寸
canvasNode.width = res[0].width * dpr
canvasNode.height = res[0].height * dpr
ctx.scale(dpr, dpr)
// 5. 调用 onInit 初始化图表
const canvas = {
width: res[0].width * dpr,
height: res[0].height * dpr,
getContext: () => ctx,
node: canvasNode
}
this.chart = this.data.ec.onInit(canvas, res[0].width, res[0].height, res)
})
}
})
```
---
## 核心功能实现
### 1. Canvas 初始化
```javascript
ready() {
const query = this.createSelectorQuery()
query.select(`#${this.data.canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
const canvasNode = res[0].node
const ctx = canvasNode.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
// 缩放以适配高清屏
canvasNode.width = res[0].width * dpr
canvasNode.height = res[0].height * dpr
ctx.scale(dpr, dpr)
// 创建 Canvas 对象
const canvas = {
width: res[0].width * dpr,
height: res[0].height * dpr,
getContext: () => ctx,
node: canvasNode
}
// 调用外部初始化函数
this.chart = this.data.ec.onInit(canvas, res[0].width, res[0].height, res)
})
}
```
### 2. 触摸事件处理
```javascript
methods: {
touchStart(e) {
if (this.chart && this.chart.touchStart) {
this.chart.touchStart(e)
}
},
touchMove(e) {
if (this.chart && this.chart.touchMove) {
this.chart.touchMove(e)
}
},
touchEnd(e) {
if (this.chart && this.chart.touchEnd) {
this.chart.touchEnd(e)
}
}
}
```
---
## 使用示例
### 1. 基础折线图
```javascript
// 页面 JS
Page({
data: {
ec: {
onInit: null
}
},
onLoad() {
this.setData({
ec: {
onInit: this.initChart.bind(this)
}
})
},
initChart(canvas, width, height, res) {
const chart = echarts.init(canvas)
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
},
yAxis: {
type: 'value'
},
series: [{
data: [120, 200, 150, 80, 70],
type: 'line',
smooth: true
}]
}
chart.setOption(option)
return chart
}
})
```
### 2. 面积图(带渐变)
```javascript
initChart(canvas, width, height, res) {
const chart = echarts.init(canvas)
const option = {
xAxis: {
type: 'category',
data: ['1/1', '1/2', '1/3', '1/4', '1/5']
},
yAxis: {
type: 'value'
},
series: [{
data: [3850, 3860, 3840, 3870, 3890],
type: 'line',
smooth: true,
areaStyle: {
color: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(24, 144, 255, 0.3)' },
{ offset: 1, color: 'rgba(24, 144, 255, 0.05)' }
]
}
}
}]
}
chart.setOption(option)
return chart
}
```
### 3. 动态更新数据
```javascript
// 更新图表数据
updateChart(newData) {
if (this.chart) {
this.chart.setOption({
series: [{
data: newData
}]
})
}
}
// 清空图表
clearChart() {
if (this.chart) {
this.chart.clear()
}
}
```
---
## WXML 模板结构
```xml
<!-- components/ec-canvas/ec-canvas.wxml -->
<canvas
type="2d"
id="{{canvasId}}"
canvas-id="{{canvasId}}"
class="ec-canvas"
bindtouchstart="touchStart"
bindtouchmove="touchMove"
bindtouchend="touchEnd">
</canvas>
```
---
## WXSS 样式
```css
/* components/ec-canvas/ec-canvas.wxss */
.ec-canvas {
width: 100%;
height: 100%;
display: block;
}
```
---
## 测试与质量
### 测试覆盖
- ✅ 在价格趋势页正常工作
- ✅ 图表渲染正确
- ✅ 触摸交互正常
- ✅ 响应式布局适配
### 测试要点
1. **图表渲染**:验证不同类型图表正常显示
2. **数据更新**:验证动态更新数据功能
3. **交互功能**:验证触摸、缩放、拖拽等交互
4. **性能测试**:大数据量时的渲染性能
5. **兼容性**iOS/Android 不同平台兼容性
---
## 常见问题 (FAQ)
### Q: 图表不显示?
**A**: 检查以下几点:
1. 确保 `ec` 对象包含 `onInit` 方法
2. 确保 Canvas 节点已正确渲染
3. 查看控制台是否有错误信息
4. 检查 ECharts 配置是否正确
### Q: 如何修改图表尺寸?
**A**: 在 WXML 中设置容器尺寸:
```xml
<view style="width: 100%; height: 500rpx;">
<ec-canvas ec="{{ ec }}"></ec-canvas>
</view>
```
### Q: 如何支持手势缩放?
**A**: 在 ECharts 配置中启用:
```javascript
const option = {
dataZoom: [{
type: 'inside',
start: 0,
end: 100
}],
// ... 其他配置
}
```
### Q: 如何导出图表为图片?
**A**: 使用 Canvas 的 `toDataURL` 方法:
```javascript
const canvas = this.chart.canvas
const url = canvas.toDataURL('image/png')
// 预览图片
wx.previewImage({
urls: [url]
})
```
### Q: 图表性能如何优化?
**A**: 优化建议:
1. 减少数据点数量(采样)
2. 关闭动画效果
3. 使用轻量级图表类型
4. 避免频繁更新
```javascript
// 关闭动画
const option = {
animation: false,
// ... 其他配置
}
```
---
## 相关文件清单
```
components/ec-canvas/
├── ec-canvas.js # 组件逻辑91 行)
├── ec-canvas.json # 组件配置
├── ec-canvas.wxml # 组件模板
├── ec-canvas.wxss # 组件样式
├── echarts.js # ECharts 库(简化版)
├── wx-canvas.js # Canvas 适配器
└── CLAUDE.md # 本文档
```
---
## 下一步建议
### 功能增强
1. **更多图表类型**
- 柱状图Bar
- 饼图Pie
- 散点图Scatter
- K 线图Candlestick
2. **交互增强**
- Tooltip 提示框
- 图例筛选
- 数据区域缩放
- 标记点/标记线
3. **性能优化**
- 虚拟滚动(大数据量)
- 增量渲染
- Web Worker 计算
### 最佳实践
1. **数据格式化**:统一数据格式转换逻辑
2. **错误处理**:添加图表渲染失败的降级方案
3. **加载状态**:显示加载动画
4. **空状态**:无数据时友好提示
---
**模块状态**: ✅ 已完成
**优先级**: 高(核心组件)
**预估工作量**: 已完成
**使用场景**: [pages/trend](../../pages/trend/CLAUDE.md) - 价格趋势图
**相关资源**: [ECharts 文档](https://echarts.apache.org/zh/index.html)