在开发项目中,components中创建Echarts文件,放入下载后的js包,并在该目录下创建wx-canvas.js,编写canvas构造函数代码,如下
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
}
}
目录结构如下图
在Echarts文件中,创建ec-canvas.vue文件,创建canvas对象
<template>
<!-- // 多个echarts时将canvasId作为唯一标识,动态获取canvasId用于多个echarts可同时显示 -->
<canvas
type="2d"
class="ec-canvas"
:id="canvasId"
:canvas-id="canvasId"
@touchStart="touchStart"
@touchMove="touchMove"
@touchEnd="touchEnd"
></canvas>
</template>
<script lang="js">
import Taro from "@tarojs/taro";
import WxCanvas from "@/components/Echarts/wx-canvas";
import * as echarts from "@/components/Echarts/echarts.min";
export default {
name: "EcCanvas",
props: {
canvasId: {
type: String,
default: "",
},
chartData: {
type: Array,
default: () => [],
},
option: {
type: Object,
default: () => {}
}
},
data() {
return {
}
},
watch: {
chartData: function() {
console.log('chartData', this.chartData)
this.handleCreate()
},
},
mounted() {
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;
}
}
})
},
methods: {
init(callback) {
this.initByNewWay(callback);
},
// eslint-disable-next-line complexity
handleCreate() {
const option = this.option
const v = this
v.init((canvas, width, height, canvasDpr) => {
const chart = echarts.init(canvas, null, {
width: width,
height: height,
devicePixelRatio: canvasDpr,
})
canvas.setChart(chart);
chart.setOption(option);
chart.on('click', (params) => {
console.log('params', params)
this.$emit('clickEChartItem', params)
});
return chart;
})
},
initByNewWay(callback) {
const query = Taro.createSelectorQuery();
query
.select(`#${this.canvasId}`) // 根据canvasId动态获取不同的echarts图表
.fields({
// node: true, // 飞书里面没有node
dataset: true,
size: true,
})
// eslint-disable-next-line complexity
.exec(res => {
console.log('query res', res)
// eslint-disable-next-line eqeqeq
// if (!res || res.length == 0 || res[0] == null || res[0].node == null) {
// console.error('未获取到canvas的dom节点,请确认在页面渲染完成后或节点,taro中页面渲染完成的生命周期是useReady');
// return
// }
// const canvasNode = res[0].node;
// this.canvasNode = canvasNode;
console.log(11,this.option.height);
const canvasDpr = Taro.getSystemInfoSync().pixelRatio;
const canvasWidth = res[0].width;
const canvasHeight = res[0].height;
// const ctx = canvasNode.getContext("2d");
const ctx = tt.createCanvasContext(this.canvasId)
console.log('ctx', ctx)
// const canvas = new WxCanvas(ctx, this.canvasId, true, canvasNode) // 不给canvasNode也可以
const canvas = new WxCanvas(ctx, this.canvasId, true);
echarts.setCanvasCreator(() => {
return canvas;
});
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
});
},
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,
});
handler.dispatch("mousemove", {
zrX: touch.x,
zrY: touch.y,
});
handler.processGesture(this.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,
});
handler.processGesture(this.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,
});
handler.dispatch("click", {
zrX: touch.x,
zrY: touch.y,
});
handler.processGesture(this.wrapTouch(e), "end");
}
},
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;
},
},
};
</script>
<style>
.ec-canvas {
width: 100%;
height: 100%;
min-height: 208px;
flex: 1;
}
</style>