You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
8.4 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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>