381 lines
8.4 KiB
Vue
381 lines
8.4 KiB
Vue
<template>
|
||
<view class="canvasId-wk">
|
||
<!-- #ifdef H5 || APP -->
|
||
|
||
<canvas
|
||
:style="{
|
||
width: w,
|
||
height: h
|
||
}"
|
||
v-if="cid"
|
||
class="ec-canvas"
|
||
:id="cid"
|
||
:canvasId="cid"
|
||
@touchstart="touchStart"
|
||
@touchmove="touchMove"
|
||
@touchend="touchEnd"
|
||
@error="$emit('error',$event)"
|
||
></canvas>
|
||
<!-- #endif -->
|
||
<!-- #ifndef MP-WEIXIN || H5 || APP || MP-ALIPAY -->
|
||
|
||
<canvas
|
||
:style="{
|
||
width: w,
|
||
height: h
|
||
}"
|
||
v-if="canvasId"
|
||
class="ec-canvas"
|
||
id="ec-canvas"
|
||
canvasId="ec-canvas"
|
||
@touchstart="touchStart"
|
||
@touchmove="touchMove"
|
||
@touchend="touchEnd"
|
||
@error="$emit('error',$event)"
|
||
></canvas>
|
||
<!-- #endif -->
|
||
<!-- #ifdef MP-WEIXIN || MP-ALIPAY-->
|
||
|
||
<canvas
|
||
:style="{
|
||
width: w,
|
||
height: h
|
||
}"
|
||
v-if="canvasId"
|
||
type="2d"
|
||
class="ec-canvas"
|
||
id="ec-canvas"
|
||
canvasId="ec-canvas"
|
||
@touchstart="touchStart"
|
||
@touchmove="touchMove"
|
||
@touchend="touchEnd"
|
||
@error="$emit('error',$event)"
|
||
></canvas>
|
||
<!-- #endif -->
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
|
||
/**
|
||
* Echart图表
|
||
* @param {Number|String} width = [] 默认100%,纯数字时,单位为rpx
|
||
* @param {Number|String} height = [] 默认500,纯数字时,单位为rpx,不允许百分比。
|
||
* @param {Object} echarts = [] 默认null,百度echart.js插件,默认可以使用本库自带,详见文档。
|
||
* @param {Function} init 图表初始化后执行触发事件返回{width,height,chart}
|
||
* @param {Function} error 出错时触发。
|
||
*/
|
||
|
||
import WxCanvas from '@/tm-vuetify/tool/function/uni-echarts-canvas.js';
|
||
import * as echarts from '@/tm-vuetify/tool/function/echarts.min.js';
|
||
function wrapTouch(e) {
|
||
for (let i = 0; i < e.mp.touches.length; i += 1) {
|
||
const touch = e.mp.touches[i];
|
||
touch.offsetX = touch.x;
|
||
touch.offsetY = touch.y;
|
||
}
|
||
return e;
|
||
}
|
||
|
||
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;
|
||
}
|
||
export default {
|
||
name:"tm-echarts",
|
||
props: {
|
||
width: {
|
||
type: String | Number,
|
||
default: '100%'
|
||
},
|
||
height: {
|
||
type: String | Number,
|
||
default: '500'
|
||
},
|
||
canvasId: {
|
||
type: String,
|
||
default: 'ec-canvas'
|
||
},
|
||
lazyLoad: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
disableTouch: {
|
||
type: Boolean,
|
||
default: false
|
||
},
|
||
throttleTouch: {
|
||
type: Boolean,
|
||
default: false
|
||
}
|
||
},
|
||
data() {
|
||
return {
|
||
echarts,
|
||
cid:'ec-canvas'
|
||
};
|
||
},
|
||
created() {
|
||
this.cid = this.$tm.guid();
|
||
},
|
||
destroyed() {
|
||
try{
|
||
this.echarts=null;
|
||
this.chart.clear()
|
||
this.chart = null;
|
||
|
||
}catch(e){
|
||
//TODO handle the exception
|
||
}
|
||
},
|
||
computed: {
|
||
w: function() {
|
||
if (this.width == 0 || this.width == '') {
|
||
return '100%';
|
||
}
|
||
let reg = /(vw|vh|rem|em|\%|upx|rpx|auto|px)/g;
|
||
if (reg.test(this.width)) {
|
||
return this.width;
|
||
}
|
||
return this.width + 'rpx';
|
||
},
|
||
h: function() {
|
||
let reg = /(vw|vh|rem|em|\%|upx|rpx|auto|px)/g;
|
||
if (reg.test(this.height)) {
|
||
return this.height;
|
||
}
|
||
return this.height + 'rpx';
|
||
}
|
||
|
||
},
|
||
|
||
mounted() {
|
||
if (!this.echarts) {
|
||
console.warn('未引用echarts');
|
||
return;
|
||
}
|
||
if (!this.lazyLoad) {
|
||
this.$nextTick(function() {
|
||
try{
|
||
this.init();
|
||
}catch(e){
|
||
//TODO handle the exception
|
||
console.error("echarts错误提醒:",e)
|
||
}
|
||
});
|
||
}
|
||
},
|
||
methods: {
|
||
//初始化
|
||
init() {
|
||
// #ifdef MP-WEIXIN
|
||
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;
|
||
}
|
||
// #endif
|
||
let canvasId = this.canvasId;
|
||
// #ifdef H5 || APP-PLUS || APP-VUE
|
||
canvasId = this.cid;
|
||
// #endif
|
||
// #ifndef MP-WEIXIN || MP-ALIPAY
|
||
|
||
this.ctx = uni.createCanvasContext(canvasId, this);
|
||
const canvas = new WxCanvas(this.ctx, canvasId, false);
|
||
|
||
this.echarts.setCanvasCreator(() => canvas);
|
||
const query = uni.createSelectorQuery().in(this);
|
||
query.select(`#${canvasId}`)
|
||
.boundingClientRect(res => {
|
||
if (!res) {
|
||
setTimeout(() => this.init(), 100);
|
||
return;
|
||
}
|
||
const { width, height } = res;
|
||
const canvasDpr = uni.getSystemInfoSync().pixelRatio
|
||
this.chart = this.echarts.init(canvas, null, {
|
||
width: width,
|
||
height: height
|
||
});
|
||
|
||
canvas.setChart(this.chart);
|
||
|
||
const { handler } = this.chart.getZr();
|
||
this.handler = handler;
|
||
this.processGesture = handler.proxy.processGesture || (() => {});
|
||
|
||
this.$emit('init', {
|
||
width: res.width,
|
||
height: res.height,
|
||
chart: this.chart
|
||
});
|
||
})
|
||
.exec();
|
||
// #endif
|
||
|
||
// #ifdef MP-WEIXIN || MP-ALIPAY
|
||
|
||
const query = uni.createSelectorQuery().in(this)
|
||
query
|
||
.select('.ec-canvas')
|
||
.fields({ node: true, size: true })
|
||
.exec(res => {
|
||
const canvasNode = res[0].node
|
||
this.canvasNode = canvasNode
|
||
|
||
const canvasDpr = uni.getSystemInfoSync().pixelRatio
|
||
const canvasWidth = res[0].width
|
||
const canvasHeight = res[0].height
|
||
|
||
const ctx = canvasNode.getContext('2d')
|
||
|
||
const canvas = new WxCanvas(ctx, canvasId, true,canvasNode);
|
||
this.echarts.setCanvasCreator(() => {
|
||
return canvas
|
||
})
|
||
this.chart = this.echarts.init(canvas, null, {
|
||
width: canvasWidth,
|
||
height: canvasHeight,
|
||
devicePixelRatio:canvasDpr
|
||
});
|
||
canvas.setChart(this.chart);
|
||
const { handler } = this.chart.getZr();
|
||
this.handler = handler;
|
||
this.processGesture = handler.proxy.processGesture || (() => {});
|
||
this.$emit('init', {
|
||
width: canvasWidth,
|
||
height: canvasHeight,
|
||
chart: this.chart
|
||
});
|
||
|
||
})
|
||
|
||
// #endif
|
||
},
|
||
//配置图表数据
|
||
setOption(dJson) {
|
||
if (!this.chart){
|
||
uni.$tm.toast("chart未初始化")
|
||
return false;
|
||
}
|
||
this.chart.setOption({...dJson},{notMerge:true});
|
||
return true;
|
||
},
|
||
//获取图表对象。
|
||
getChart(FunName,arg){
|
||
if (!this.chart){
|
||
uni.$tm.toast("chart未初始化")
|
||
return false;
|
||
}
|
||
return this.chart;
|
||
},
|
||
resize(){
|
||
|
||
let t = this;
|
||
return new Promise((res,rej)=>{
|
||
if (!t.chart){
|
||
uni.$tm.toast("chart未初始化")
|
||
rej(false);
|
||
return false;
|
||
}
|
||
let canvasId = t.canvasId;
|
||
// #ifdef H5 || APP-PLUS || APP-VUE
|
||
canvasId = t.cid;
|
||
// #endif
|
||
|
||
const query = uni.createSelectorQuery().in(t);
|
||
query.select(`.canvasId-wk`)
|
||
.boundingClientRect(op => {
|
||
const { width, height } = op;
|
||
t.chart.resize({width:width,height:height})
|
||
res(true);
|
||
}).exec()
|
||
})
|
||
},
|
||
canvasToTempFilePath(opt) {
|
||
const { canvasId } = this;
|
||
this.ctx.draw(true, () => {
|
||
wx.canvasToTempFilePath({
|
||
canvasId,
|
||
...opt
|
||
});
|
||
});
|
||
},
|
||
touchStart(e) {
|
||
const { disableTouch, chart } = this;
|
||
if (disableTouch || !chart || !e.mp.touches.length) return;
|
||
const touch = e.mp.touches[0];
|
||
this.handler.dispatch('mousedown', {
|
||
zrX: touch.x,
|
||
zrY: touch.y
|
||
});
|
||
this.handler.dispatch('mousemove', {
|
||
zrX: touch.x,
|
||
zrY: touch.y
|
||
});
|
||
this.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', {
|
||
zrX: touch.x,
|
||
zrY: touch.y
|
||
});
|
||
this.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', {
|
||
zrX: touch.x,
|
||
zrY: touch.y
|
||
});
|
||
this.handler.dispatch('click', {
|
||
zrX: touch.x,
|
||
zrY: touch.y
|
||
});
|
||
this.processGesture(wrapTouch(e), 'end');
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.ec-canvas {
|
||
width: 100%;
|
||
height: 375rpx;
|
||
}
|
||
</style>
|