Skip to content

Commit

Permalink
refactor: 支持新版 canvas, 修复安卓机无法滑动问题 (#101)
Browse files Browse the repository at this point in the history
* 不再支持旧版canvas, 支持2d, 修复安卓机无法滑动问题

eslint

* v1.0.0

---------

Co-authored-by: maoyuan.chai <[email protected]>
  • Loading branch information
dockfries and maoyuan.chai committed Apr 12, 2024
1 parent 91b9ea5 commit 741695b
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 123 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ module.exports = {
'no-console': 0,
'prefer-rest-params': 0,
'class-methods-use-this': 0,
'no-underscore-dangle': 0
'no-underscore-dangle': 0,
'no-plusplus': 0
},
globals: {
wx: true,
Expand Down
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,6 @@ typings/
.vscode

#others
dist/
dist/

package-lock.json
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ export default {
| onInit | Function | null | 初始化函数 |
| lazyLoad | Boolean | false | 懒加载 |
| disableTouch | Boolean | false | 禁用触摸事件 |
| throttleTouch| Boolean | false | 节流触摸事件 |


## FAQ
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "mpvue-echarts",
"version": "0.3.2",
"version": "1.0.0",
"description": "适用于 Mpvue 的 ECharts 组件",
"main": "src/echarts.vue",
"typings": "types/index.d.ts",
"scripts": {
"lint": "eslint --format node_modules/eslint-friendly-formatter --ext .js,.vue src",
"lint": "eslint --format node_modules/eslint-friendly-formatter --ext .js,.vue src --fix",
"test": "echo \"Error: no test specified\" && exit 1"
},
"files": [
Expand Down
232 changes: 142 additions & 90 deletions src/echarts.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,19 @@
<template>
<canvas
v-if="canvasId"
class="ec-canvas"
:id="canvasId"
:canvasId="canvasId"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@error="error">
<canvas v-if="_canvasId" class="ec-canvas" type="2d" :id="_canvasId" :canvasId="_canvasId" @touchstart="touchStart"
@touchmove="touchMove" @touchend="touchEnd">
</canvas>
</template>

<script>
import WxCanvas from './wx-canvas';
function wrapTouch(e) {
for (let i = 0; i < e.mp.touches.length; i += 1) {
const touch = e.mp.touches[i];
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 e;
return event;
}
export default {
Expand Down Expand Up @@ -48,121 +41,180 @@ export default {
type: Boolean,
default: false,
},
throttleTouch: {
type: Boolean,
default: false,
},
},
onReady() {
if (!this.echarts) {
console.warn('组件需绑定 echarts 变量,例:<ec-canvas id="mychart-dom-bar" '
+ 'canvas-id="mychart-bar" :echarts="echarts"></ec-canvas>');
console.warn('组件需绑定 echarts 变量');
return;
}
if (!this.lazyLoad) this.init();
},
data() {
return {
tryQuery: 0,
};
},
computed: {
_canvasId() {
return this.canvasId.toLocaleLowerCase();
},
},
methods: {
init(callback) {
const version = wx.version.version.split('.').map(n => parseInt(n, 10));
const isValid = version[0] > 1 || (version[0] === 1 && version[1] > 9)
|| (version[0] === 1 && version[1] === 9 && version[2] >= 91);
if (!isValid) {
console.error('微信基础库版本过低,需大于等于 1.9.91。'
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
return;
}
const { canvasId } = this;
this.ctx = wx.createCanvasContext(canvasId);
const canvas = new WxCanvas(this.ctx, canvasId);
this.echarts.setCanvasCreator(() => canvas);
const query = wx.createSelectorQuery();
query.select(`#${canvasId}`).boundingClientRect((res) => {
if (!res) {
setTimeout(() => this.init(), 50);
return;
}
const { width, height } = res;
if (typeof callback === 'function') {
this.chart = callback(canvas, width, height);
} else if (typeof this.onInit === 'function') {
this.chart = this.onInit(canvas, width, height);
}
if (!this.chart) {
return;
}
const { handler } = this.chart.getZr();
this.handler = handler;
this.processGesture = handler.proxy.processGesture || (() => {});
}).exec();
query
.select(`#${this._canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
if (!res[0] || !res[0].node) {
setTimeout(() => {
this.tryQuery++;
if (this.tryQuery >= 10) {
this.tryQuery = 0;
console.warn('canvas 节点始终未找到');
return;
}
this.init(callback);
}, 100);
return;
}
const canvasNode = res[0].node;
this.canvasNode = canvasNode;
console.log('canvas 节点', 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.canvasId, true, canvasNode);
if (this.echarts.setPlatformAPI) {
this.echarts.setPlatformAPI({
createCanvas: () => canvas,
loadImage: (src, onload, onerror) => {
if (canvasNode.createImage) {
const image = canvasNode.createImage();
image.onload = onload;
image.onerror = onerror;
image.src = src;
return image;
}
console.error('加载图片依赖 `Canvas.createImage()` API,要求小程序基础库版本在 2.7.0 及以上。');
return null;
// PENDING fallback?
},
});
} else {
this.echarts.setCanvasCreator(() => canvas);
}
if (typeof callback === 'function') {
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr);
} else if (typeof this.onInit === 'function') {
this.chart = this.onInit(canvas, canvasWidth, canvasHeight, canvasDpr);
} else {
this.$emit('init', {
canvas,
canvasWidth,
canvasHeight,
canvasDpr,
});
}
});
},
canvasToTempFilePath(opt) {
const { canvasId } = this;
this.ctx.draw(true, () => {
wx.canvasToTempFilePath({
canvasId,
...opt,
const query = wx.createSelectorQuery();
query
.select(`#${this._canvasId}`)
.fields({ node: true, size: true })
.exec((res) => {
if (!res[0] || !res[0].node) {
setTimeout(() => {
this.tryQuery++;
if (this.tryQuery >= 10) {
this.tryQuery = 0;
console.warn('canvas 节点始终未找到');
return;
}
this.canvasToTempFilePath(opt);
}, 100);
return;
}
const canvasNode = res[0].node;
wx.canvasToTempFilePath({
...opt,
canvas: canvasNode,
});
});
});
},
touchStart(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
const touch = e.mp.touches[0];
this.handler.dispatch('mousedown', {
if (this.disableTouch || !this.chart || !e.touches.length) return;
const touch = e.touches[0];
const { handler } = this.chart.getZr();
handler.dispatch('mousedown', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => { },
stopImmediatePropagation: () => { },
stopPropagation: () => { },
});
this.handler.dispatch('mousemove', {
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => { },
stopImmediatePropagation: () => { },
stopPropagation: () => { },
});
this.processGesture(wrapTouch(e), 'start');
handler.processGesture(wrapTouch(e), 'start');
},
touchMove(e) {
const {
disableTouch, throttleTouch, chart, lastMoveTime,
} = this;
if (disableTouch || !chart || !e.mp.touches.length) return;
if (throttleTouch) {
const currMoveTime = Date.now();
if (currMoveTime - lastMoveTime < 240) return;
this.lastMoveTime = currMoveTime;
}
const touch = e.mp.touches[0];
this.handler.dispatch('mousemove', {
if (this.disableTouch || !this.chart || !e.touches.length) return;
const touch = e.touches[0];
const { handler } = this.chart.getZr();
handler.dispatch('mousemove', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => { },
stopImmediatePropagation: () => { },
stopPropagation: () => { },
});
this.processGesture(wrapTouch(e), 'change');
handler.processGesture(wrapTouch(e), 'change');
},
touchEnd(e) {
const { disableTouch, chart } = this;
if (disableTouch || !chart) return;
const touch = e.mp.changedTouches ? e.mp.changedTouches[0] : {};
this.handler.dispatch('mouseup', {
if (this.disableTouch || !this.chart) return;
const touch = e.changedTouches ? e.changedTouches[0] : {};
const { handler } = this.chart.getZr();
handler.dispatch('mouseup', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => { },
stopImmediatePropagation: () => { },
stopPropagation: () => { },
});
this.handler.dispatch('click', {
handler.dispatch('click', {
zrX: touch.x,
zrY: touch.y,
preventDefault: () => { },
stopImmediatePropagation: () => { },
stopPropagation: () => { },
});
this.processGesture(wrapTouch(e), 'end');
handler.processGesture(wrapTouch(e), 'end');
},
},
};
</script>

Expand Down
Loading

0 comments on commit 741695b

Please sign in to comment.