新手开发支付宝小程序用 Echarts 做图表报错怎么办 本文用实际案例手把手教你解决数据可视化集成难题
前言:先别慌,这个问题太常见了
我做过不少小程序,每次看到开发者朋友因为 Echarts 报错来问我,心里都特别有共鸣——当年我也折腾了好几天。支付宝小程序和微信不一样,它的沙箱环境、组件体系、甚至代码规范都有自己的一套逻辑,直接套 Echarts 官方教程,10 个有 8 个会栽跟头。
别急,今天咱们就从一个真实项目出发,把最常见的坑一个一个填平。
一、你的 Echarts 到底能不能用?
先给一个明确的回答:能用,但路径和普通网页不一样。
支付宝小程序不支持 document、window、canvas 2d 的某些 API,直接用 echarts 官方 npm 包会直接报:
❌
Cannot find module 'echarts'
❌canvas is not defined
❌Document is not defined
这时候如果你不管三七二十一直接 npm install echarts,大概率会卡住。
✅ 正确姿势:用 ec-canvas 组件
Echarts 官方团队专门出了适配小程序的组件库:ec-canvas。它把 Echarts 的核心逻辑包了一层,屏蔽了 document、window 这些浏览器专属 API,专门给小程序用。
安装方法:
# 进入你的小程序项目根目录,执行:
npm install ec-canvas --save
安装完后,你需要在 project.config.json 里打开 npm 编译:
{
"miniprogramRoot": "miniprogram/",
"npm": {
"miniprogramNpmDistDir": "./"
}
}
然后 右键项目 → 勾选”使用 npm 模块”,微信开发者工具(支付宝开发者工具同理)会自动构建 npm,把 ec-canvas 复制到 miniprogram_npm 目录。
这一步非常重要,很多新手栽在这里——npm 安装完不构建,直接用,100% 报错。
二、第一个报错:ec-canvas 组件找不到
这是最常见的错误之一。你可能这样引入:
<view class="chart-container">
<ec-canvas id="mychart-dom-line" canvas-id="mychart-line"></ec-canvas>
</view>
然后控制台报:
❌
<ec-canvas>组件未找到,请检查路径
原因有两种:
原因 1:没有正确复制 ec-canvas 到项目
构建 npm 之后,你需要在项目的 miniprogram_npm 目录下能看到 ec-canvas 文件夹。如果没有,说明构建失败。
检查一下你的 package.json 里有没有 ec-canvas:
{
"dependencies": {
"ec-canvas": "^1.1.0"
}
}
如果没有,重新安装:
npm install ec-canvas --save
然后重新构建 npm。
原因 2:组件路径配置错误
在 JSON 里注册组件时,路径要写对:
{
"usingComponents": {
"ec-canvas": "../../miniprogram_npm/ec-canvas/ec-canvas"
}
}
注意,这个路径是相对于当前页面的路径。如果你把 ec-canvas 整个文件夹复制到小程序根目录,路径可以简化为:
{
"usingComponents": {
"ec-canvas": "ec-canvas/ec-canvas"
}
}
三、第二个报错:wx.createCanvasContext is not a function
这个报错说明 ec-canvas 组件虽然找到了,但底层调用小程序 API 时出了问题。
在支付宝小程序里,wx 命名空间不存在,应该用 my:
// ❌ 错误写法
const ctx = wx.createCanvasContext('mychart-line')
// ✅ 正确写法(支付宝)
const ctx = my.createCanvasContext('mychart-line')
但 ec-canvas 组件内部是硬编码了 wx. 的,这就尴尬了。
解决方案:替换源码
打开 ec-canvas 目录下的 ec-canvas.js,找到所有 wx. 替换成 my.:
// 批量替换(在 ec-canvas.js 中)
// 搜索:wx.
// 替换为:my.
一共大概有十几处,主要包括:
wx.createCanvasContext→my.createCanvasContextwx.createSelectorQuery→my.createSelectorQuerywx.getSystemInfoSync→my.getSystemInfoSyncwx.createAnimation→my.createAnimation
替换完之后,重新构建,基本就能跑起来了。
💡 提醒:每次
npm install之后如果重新拉取ec-canvas,这些修改会丢失。建议把这个修改过的版本单独保存一份,或者 fork 一份到自己的 npm 包管理起来。
四、第三个报错:图表渲染不出来,一片空白
这个坑比报错还难受——控制台没报错,但页面就是白茫茫一片。
主要原因有三个:
原因 1:canvas 尺寸没有正确设置
ec-canvas 默认不会自动获取容器宽度,你需要在 WXML 里给 canvas 指定宽高:
<ec-canvas
id="mychart-line"
canvas-id="mychart-line"
style="width: 100%; height: 400rpx;">
</ec-canvas>
或者在 JS 里通过 canvas-id 和 CSS 控制尺寸:
.chart-container {
width: 100%;
height: 400rpx;
}
原因 2:初始化时机问题
ec-canvas 组件需要在页面 onLoad 之后、组件渲染完成之后才能初始化。如果在 data 里直接写 init,可能会因为 canvas 还没准备好就调用 initChart,导致报错。
正确做法是用回调:
// pages/chart/chart.js
Page({
data: {
ec: {
onInit: function (canvas, width, height) {
// 这里才能安全调用 echarts.init
const echarts = require('echarts');
const chart = echarts.init(canvas, null, {
width: width,
height: height
});
canvas.setChart(chart);
chart.setOption({
xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed'] },
yAxis: { type: 'value' },
series: [{ data: [820, 932, 901], type: 'line' }]
});
return chart;
}
}
}
})
<!-- pages/chart/chart.wxml -->
<ec-canvas id="mychart-line" canvas-id="mychart-line" ec="{{ec}}"></ec-canvas>
原因 3:echarts 版本和 ec-canvas 不兼容
ec-canvas 1.x 版本对 Echarts 5.x 支持不太好。建议用:
# 安装稳定版本
npm install echarts@4.9.0 --save
npm install ec-canvas@1.1.0 --save
五、完整实战:做一个折线图
现在我们把上面的坑全部填平,做一个完整的折线图。
第一步:初始化项目
# 创建支付宝小程序项目(或使用已有项目)
mkdir my-echarts-demo && cd my-echarts-demo
npm init -y
npm install echarts@4.9.0 ec-canvas@1.1.0 --save
第二步:配置 project.config.json
{
"miniprogramRoot": "miniprogram/",
"npm": {
"miniprogramNpmDistDir": "./"
},
"setting": {
"urlCheck": false,
"es6": true,
"enhance": true
}
}
第三步:修改 ec-canvas 源码(wx → my)
打开 miniprogram_npm/ec-canvas/ec-canvas.js,执行以下替换(可以用 VSCode 全局替换):
| 查找 | 替换为 |
|---|---|
wx.createCanvasContext |
my.createCanvasContext |
wx.createSelectorQuery |
my.createSelectorQuery |
wx.getSystemInfoSync |
my.getSystemInfoSync |
wx.createAnimation |
my.createAnimation |
wx.showToast |
my.showToast |
wx.hideToast |
my.hideToast |
第四步:创建图表页面
新建 pages/chart/chart.js:
// pages/chart/chart.js
const echarts = require('echarts');
Page({
data: {
ec: {
lazyLoad: false,
onInit: function (canvas, width, height) {
const chart = echarts.init(canvas, null, {
width: width,
height: height
});
canvas.setChart(chart);
chart.setOption({
title: {
text: '本周销售趋势',
left: 'center',
textStyle: { fontSize: 14 }
},
tooltip: {
trigger: 'axis'
},
xAxis: {
type: 'category',
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
axisLabel: { fontSize: 10 }
},
yAxis: {
type: 'value',
axisLabel: { fontSize: 10 }
},
series: [
{
name: '销售额',
type: 'line',
smooth: true,
data: [120, 132, 101, 134, 90, 230, 210],
itemStyle: { color: '#1677ff' },
areaStyle: {
color: {
type: 'linear',
x: 0, y: 0, x2: 0, y2: 1,
colorStops: [
{ offset: 0, color: 'rgba(22,119,255,0.3)' },
{ offset: 1, color: 'rgba(22,119,255,0.02)' }
]
}
}
}
]
});
return chart;
}
}
}
})
创建 pages/chart/chart.wxml:
<!-- pages/chart/chart.wxml -->
<view class="chart-page">
<view class="chart-title">📊 数据概览</view>
<view class="chart-container">
<ec-canvas
id="sales-line"
canvas-id="sales-line"
ec="{{ec}}">
</ec-canvas>
</view>
</view>
创建 pages/chart/chart.json:
{
"usingComponents": {
"ec-canvas": "../../miniprogram_npm/ec-canvas/ec-canvas"
},
"navigationBarTitleText": "数据可视化"
}
创建 pages/chart/chart.wxss(支付宝用 wxss):
.chart-page {
padding: 20rpx;
}
.chart-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 20rpx;
color: #333;
}
.chart-container {
width: 100%;
height: 400rpx;
background: #fff;
border-radius: 16rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
}
第五步:运行效果
运行后你应该能看到一个平滑的折线图,带渐变色填充,效果如下:
本周销售趋势
250 ┤ ╭─╮
200 ┤ ╭──╯ ╰╮
150 ┤ ╭─╯ ╰──╮
100 ┤──╯ ╰──
└──────────────────
周一 周二 周三 周四 周五 周六 周日
六、进阶:多图并存和动态数据
实际项目里往往不止一个图。下面是带动态数据的柱状图:
// pages/chart/chart.js 扩展
const echarts = require('echarts');
Page({
data: {
ecBar: {
onInit: function (canvas, width, height) {
const chart = echarts.init(canvas, null, {
width: width,
height: height
});
canvas.setChart(chart);
chart.setOption({
title: { text: '商品销量TOP5', left: 'center', textStyle: { fontSize: 14 } },
grid: { top: 60, bottom: 40, left: 50, right: 30 },
xAxis: { type: 'value', axisLabel: { fontSize: 10 } },
yAxis: {
type: 'category',
data: ['A商品', 'B商品', 'C商品', 'D商品', 'E商品'],
axisLabel: { fontSize: 10 }
},
series: [{
type: 'bar',
data: [320, 280, 250, 180, 150],
itemStyle: {
color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
{ offset: 0, color: '#1677ff' },
{ offset: 1, color: '#69b1ff' }
]),
borderRadius: [0, 8, 8, 0]
}
}]
});
return chart;
}
}
},
// 动态更新数据
updateData(newData) {
const canvas = this.selectComponent('#barChart');
const chart = canvas.chart;
chart.setOption({
series: [{ data: newData }]
});
}
})
<ec-canvas id="barChart" canvas-id="bar-chart" ec="{{ecBar}}"></ec-canvas>
七、常见坑总结表
| 报错信息 | 原因 | 解决方案 |
|---|---|---|
Cannot find module 'ec-canvas' |
npm 未构建 | 右键 → 使用 npm 模块 |
wx.createCanvasContext is not a function |
微信 API 不兼容支付宝 | 替换 ec-canvas.js 中所有 wx. 为 my. |
| 图表空白 | canvas 尺寸未设置 | 给 ec-canvas 设置固定高度 |
echarts.init is not a function |
echarts 未正确引入 | 检查 require 路径和版本 |
| 图表不更新 | 没有调用 setOption |
用 selectComponent 获取实例后调用 |
八、如果还遇到问题
最后说几句真心话:
Echarts 在小程序里跑通确实要跨好几道坎,但这只是第一步。一旦组件跑起来,后面写图表配置项和写网页版一模一样,没有任何区别。
如果按上面的步骤还是跑不起来,大概率是某个环节漏了。建议按这个顺序排查:
miniprogram_npm/ec-canvas目录是否存在?wx是否全部替换成my?ec-canvas是否在 JSON 里正确注册?- canvas 是否有明确的高度?
onInit回调是否正确返回 chart 实例?
排查完这五点,99% 的问题都能解决。
祝你一次跑通,少走弯路 🙌
