Files
2026-01-07 10:13:21 +08:00

9.5 KiB
Raw Permalink Blame History

根目录 > 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 配置
{
  "usingComponents": {
    "ec-canvas": "../../components/ec-canvas/ec-canvas"
  }
}
<!-- 页面 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 对象结构

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 接口

配置项

// 组件配置
Component({
  properties: {
    canvasId: {
      type: String,
      value: 'ec-canvas'
    },
    ec: {
      type: Object,
      value: {}
    }
  }
})

数据模型

组件生命周期

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 初始化

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. 触摸事件处理

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. 基础折线图

// 页面 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. 面积图(带渐变)

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. 动态更新数据

// 更新图表数据
updateChart(newData) {
  if (this.chart) {
    this.chart.setOption({
      series: [{
        data: newData
      }]
    })
  }
}

// 清空图表
clearChart() {
  if (this.chart) {
    this.chart.clear()
  }
}

WXML 模板结构

<!-- 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 样式

/* 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 中设置容器尺寸:

<view style="width: 100%; height: 500rpx;">
  <ec-canvas ec="{{ ec }}"></ec-canvas>
</view>

Q: 如何支持手势缩放?

A: 在 ECharts 配置中启用:

const option = {
  dataZoom: [{
    type: 'inside',
    start: 0,
    end: 100
  }],
  // ... 其他配置
}

Q: 如何导出图表为图片?

A: 使用 Canvas 的 toDataURL 方法:

const canvas = this.chart.canvas
const url = canvas.toDataURL('image/png')

// 预览图片
wx.previewImage({
  urls: [url]
})

Q: 图表性能如何优化?

A: 优化建议:

  1. 减少数据点数量(采样)
  2. 关闭动画效果
  3. 使用轻量级图表类型
  4. 避免频繁更新
// 关闭动画
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 - 价格趋势图 相关资源: ECharts 文档