- 微信小程序中使用echarts组件
- 下载echarts
- 文档
- 子组件
- wx-canvas.js
- ec-canvas.js
- ec-canvas.wxml
- ec-canvas.wxss
- ec-canvas.json
- 主页面
- index.js
- index.wxml
- index.wxss
- index.json
- 页面效果
- 案例
- 案例一
- 案例二
- 案例三
微信小程序中使用echarts组件
下载echarts
在echarts官方下载echarts.js引入项目中
文档
子组件
wx-canvas.js
export default class WxCanvas {
constructor(ctx, canvasId, isNew, canvasNode) {
this.ctx = ctx;
this.canvasId = canvasId;
this.chart = null;
this.isNew = isNew
if (isNew) {
this.canvasNode = canvasNode;
}
else {
this._initStyle(ctx);
}
// this._initCanvas(zrender, ctx);
this._initEvent();
}
getContext(contextType) {
if (contextType === '2d') {
return this.ctx;
}
}
// canvasToTempFilePath(opt) {
// if (!opt.canvasId) {
// opt.canvasId = this.canvasId;
// }
// return wx.canvasToTempFilePath(opt, this);
// }
setChart(chart) {
this.chart = chart;
}
addEventListener() {
// noop
}
attachEvent() {
// noop
}
detachEvent() {
// noop
}
_initCanvas(zrender, ctx) {
zrender.util.getContext = function () {
return ctx;
};
zrender.util.$override('measureText', function (text, font) {
ctx.font = font || '12px sans-serif';
return ctx.measureText(text);
});
}
_initStyle(ctx) {
ctx.createRadialGradient = () => {
return ctx.createCircularGradient(arguments);
};
}
_initEvent() {
this.event = {};
const eventNames = [{
wxName: 'touchStart',
ecName: 'mousedown'
}, {
wxName: 'touchMove',
ecName: 'mousemove'
}, {
wxName: 'touchEnd',
ecName: 'mouseup'
}, {
wxName: 'touchEnd',
ecName: 'click'
}];
eventNames.forEach(name => {
this.event[name.wxName] = e => {
const touch = e.touches[0];
this.chart.getZr().handler.dispatch(name.ecName, {
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
};
});
}
set width(w) {
if (this.canvasNode) this.canvasNode.width = w
}
set height(h) {
if (this.canvasNode) this.canvasNode.height = h
}
get width() {
if (this.canvasNode)
return this.canvasNode.width
return 0
}
get height() {
if (this.canvasNode)
return this.canvasNode.height
return 0
}
}
ec-canvas.js
import WxCanvas from './wx-canvas';
import * as echarts from '../../pages/oaManage/generalSituation/utils/echarts.min.js';
let ctx;
function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
Component({
properties: {
canvasId: {
type: String,
value: 'ec-canvas'
},
ec: {
type: Object
},
forceUseOldCanvas: {
type: Boolean,
value: false
}
},
data: {
isUseNewCanvas: false
},
ready: function () {
// Disable prograssive because drawImage doesn't support DOM as parameter
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
echarts.registerPreprocessor(option => {
if (option && option.series) {
if (option.series.length > 0) {
option.series.forEach(series => {
series.progressive = 0;
});
} else if (typeof option.series === 'object') {
option.series.progressive = 0;
}
}
});
if (!this.data.ec) {
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" ' +
'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
return;
}
if (!this.data.ec.lazyLoad) {
this.init();
}
},
methods: {
init: function (callback) {
const version = wx.getSystemInfoSync().SDKVersion
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
const forceUseOldCanvas = this.data.forceUseOldCanvas;
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
this.setData({
isUseNewCanvas
});
if (forceUseOldCanvas && canUseNewCanvas) {
console.warn('开发者强制使用旧canvas,建议关闭');
}
if (isUseNewCanvas) {
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
// 2.9.0 可以使用 <canvas type="2d"></canvas>
this.initByNewWay(callback);
} else {
const isValid = compareVersion(version, '1.9.91') >= 0
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。' +
'参见:https://github.com/ecomfe/echarts-for-weixin' +
'#微信版本要求');
return;
} else {
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
this.initByOldWay(callback);
}
}
},
initByOldWay(callback) {
// 1.9.91 <= version < 2.9.0:原来的方式初始化
ctx = wx.createCanvasContext(this.data.canvasId, this);
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
echarts.setCanvasCreator(() => {
return canvas;
});
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
const canvasDpr = 1
var query = wx.createSelectorQuery().in(this);
query.select('.ec-canvas').boundingClientRect(res => {
if (typeof callback === 'function') {
this.chart = callback(canvas, res.width, res.height, canvasDpr);
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
console.log("this.chart", this.chart)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: res.width,
height: res.height,
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
});
}
}).exec();
},
initByNewWay(callback) {
// version >= 2.9.0:使用新的方式初始化
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({
node: true,
size: true
})
.exec(res => {
const canvasNode = res[0].node
this.canvasNode = canvasNode
const canvasDpr = wx.getSystemInfoSync().pixelRatio
const canvasWidth = res[0].width
const canvasHeight = res[0].height
const ctx = canvasNode.getContext('2d')
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
echarts.setCanvasCreator(() => {
return canvas
})
console.log("this.data.ec", this.data.ec)
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
console.log("this.chart", this.chart)
} else {
this.triggerEvent('init', {
canvas: canvas,
width: canvasWidth,
height: canvasHeight,
dpr: canvasDpr
})
}
})
},
canvasToTempFilePath(opt) {
if (this.data.isUseNewCanvas) {
// 新版
const query = wx.createSelectorQuery().in(this)
query
.select('.ec-canvas')
.fields({
node: true,
size: true
})
.exec(res => {
const canvasNode = res[0].node
opt.canvas = canvasNode
wx.canvasToTempFilePath(opt)
})
} else {
// 旧的
if (!opt.canvasId) {
opt.canvasId = this.data.canvasId;
}
ctx.draw(true, () => {
wx.canvasToTempFilePath(opt, this);
});
}
},
touchStart(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'start');
}
},
touchMove(e) {
if (this.chart && e.touches.length > 0) {
var touch = e.touches[0];
var handler = this.chart.getZr().handler;
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'change');
}
},
touchEnd(e) {
if (this.chart) {
const touch = e.changedTouches ? e.changedTouches[0] : {};
var handler = this.chart.getZr().handler;
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => {},
stopImmediatePropagation: () => {},
stopPropagation: () => {}
});
handler.processGesture(wrapTouch(e), 'end');
}
}
}
});
function wrapTouch(event) {
for (let i = 0; i < event.touches.length; ++i) {
const touch = event.touches[i];
touch.offsetX = touch.x;
touch.offsetY = touch.y;
}
return event;
}
ec-canvas.wxml
<!-- 新的:接口对其了H5 -->
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
<!-- 旧的 -->
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
ec-canvas.wxss
.ec-canvas {
width: 100%;
height: 100%;
}
ec-canvas.json
{
"usingComponents": {
"ec-canvas": "../../components/ec-canvas/ec-canvas"
}
}
主页面
index.js
import * as echarts from './utils/echarts.min.js';
let newArr1 = [{
value: 200,
itemStyle: {
color: 'rgb(75,177,61)'
}
}]
function initChart(canvas, width, height, dpr) {
chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: dpr // new
});
canvas.setChart(chart);
var option = {
xAxis: {
type: 'category',
name: '月份',
nameTextStyle: {
padding: [0, 0, 0, -10]
},
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
},
yAxis: {
type: 'value',
name: '金额',
axisTick: {
show: false,
},
axisLabel: {
color: '#444343',
formatter: function (value, index) {
// value大于1000时除以1000并拼接k,小于1000按原格式显示
if (value >= 10000) {
value = value / 10000 + 'w';
} else if (value < 10000) {
value;
}
return value;
},
},
},
series: [{
data: newArr1,
type: 'bar'
}]
};
chart.setOption(option);
return chart;
}
Page({
data:{
ec: {
onInit: initChart
},
canvasIsShow: false
},
onLoad(){
this.getData()
}
getData(){
let arr = [];
//请求数据
//处理数据
//赋值
newArr1 = arr
this.setData({
canvasIsShow:true
})
}
})
index.wxml
ec-canvas 设置 force-use-old-canvas=“true” ,防止echarts图标不随着页面滑动而滑动
<view class="ec-container" wx:if="{{canvasIsShow }}">
<ec-canvas force-use-old-canvas="true" id="mychart-dom-bar" canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>
</view>
index.wxss
.ec-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 650rpx;
height: 420rpx;
}
ec-canvas {
width: 100%;
height: 100%;
}
index.json
{
"usingComponents": {
"ec-canvas": "/components/ec-canvas/ec-canvas"
}
}
页面效果
案例
可以在尝试在官方的代码编辑器中演示
案例一
option = {
tooltip: {
trigger: 'item',
formatter: " {b}:{c} "
},
color:['#ffb616','#ccc'],
legend: {
orient: 'vertical',
show: false,
x: 'left',
data: ['酒店', '机票']
},
series: [
{
name: '访问来源',
type: 'pie',
radius: ['30%', '40%'],
labelLine: {
normal: {
length: 20,
length2: 70,
lineStyle: {
color: '#333'
}
}
},
label: {
normal: {
// \n\n可让文字居于牵引线上方,很关键
formatter: ' {b}:{c} \n\n',
padding: [0, -70],
rich: {
a: {
color: '#333',
fontSize: 12,
lineHeight: 20
},
b: {
fontSize: 12,
lineHeight: 20,
color: '#333'
}
}
}
},
data: [{
value: 8,
name: '酒店'
}, {
value: 35,
name: '机票'
}]
}
]
};
案例二
option = {
tooltip: {
trigger: 'item',
formatter: "{a} \n {b}: {c} ({d}%)"
},
color: [
'rgb(233, 166, 78)',
'rgb(58, 168, 169)',
'rgb(77, 171, 111)',
'rgb(78, 131, 236)'
],
legend: {
top: '5%',
left: 'center',
selectedMode: false,
data: ['机票', '酒店', '火车', '用车']
},
series: [{
name: '金额',
type: 'pie',
radius: ['30%', '50%'],
avoidLabelOverlap: false,
label: {
normal: {
formatter: ' {b}:{c}',
rich: {
a: {
color: '#333',
fontSize: 12,
lineHeight: 20
},
b: {
fontSize: 12,
lineHeight: 20,
color: '#333'
}
}
}
},
data: [{
value: 0,
name: '机票'
},
{
value: 0,
name: '酒店'
},
{
value: 0,
name: '火车'
},
{
value: 0,
name: '用车'
}
]
}]
};
案例三
option = {
tooltip: {
trigger: 'axis'
},
legend: {
data: ['机票', '酒店', '火车', '用车'],
selectedMode: false,
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
name: '月',
nameTextStyle: {
padding: [0, 0, 0, -13]
},
data: ['1', '2', '3', '4', '5', '6', '7', ]
},
yAxis: {
type: 'value',
name: '金额',
axisTick: {
show: false,
},
axisLabel: {
color: '#444343',
formatter: function (value, index) {
// value大于1000时除以1000并拼接k,小于1000按原格式显示
if (value >= 10000) {
value = value / 10000 + 'w';
} else if (value < 10000) {
value;
}
return value;
},
},
},
series: [{
name: '机票',
type: 'line',
data: [120, 132, 101, 134, 90, 230, 210],
itemStyle: {
normal: {
color: 'rgb(233, 166, 78)', //折点的颜色
lineStyle: {
color: 'rgb(233, 166, 78)', //折线的颜色
}
}
},
},
{
name: '酒店',
type: 'line',
data: [220, 182, 191, 234, 290, 330, 310],
itemStyle: {
normal: {
color: 'rgb(58, 168, 169)', //折点的颜色
lineStyle: {
color: 'rgb(58, 168, 169)', //折线的颜色
}
}
},
},
{
name: '火车',
type: 'line',
data: [150, 232, 201, 154, 190, 330, 410],
itemStyle: {
normal: {
color: 'rgb(77, 171, 111)', //折点的颜色
lineStyle: {
color: 'rgb(77, 171, 111)', //折线的颜色
}
}
},
},
{
name: '用车',
type: 'line',
data: [320, 332, 301, 334, 390, 330, 320],
itemStyle: {
normal: {
color: 'rgb(78, 131, 236)', //折点的颜色
lineStyle: {
color: 'rgb(78, 131, 236)', //折线的颜色
}
}
},
}
]
};