WebApp【公共组件库】@前端(For Git Submodule)
Tevin
2022-08-26 4b774f04653a89513bc8f847920529c08507f564
plugins/echarts/CECharts.weapp.vue
New file
@@ -0,0 +1,208 @@
/**
 * CECharts
 * @author Tevin
 */
<template>
    <view class="c-echarts">
        <canvas
            class="c-echarts-canvas"
            type="2d"
            :id="canvasId"
            :canvasId="canvasId"
            @touchstart="evt => disableTouch ? null : touchStart(evt)"
            @touchmove="evt => disableTouch ? null : touchMove(evt)"
            @touchend="evt => disableTouch ? null : touchEnd(evt)"
        ></canvas>
    </view>
</template>
<script>
import WxCanvas from './wxCanvas';
import * as echarts from './echarts';
import './cECharts.scss';
let canvasCount = 0;
const 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;
};
export default {
    name: 'CECharts',
    components: {},
    props: {
        canvasId: {
            type: String,
            default: () =>
                'ec-canvas-' + ++canvasCount + '-' + parseInt(Math.random() * 10000),
        },
        disableTouch: {
            type: Boolean,
            default: false,
        },
        onReady: Function,
    },
    data() {
        return {};
    },
    methods: {
        init(callback) {
            // 基础库必须 2.9.0 以上,使用 <canvas type="2d"></canvas>,不支持旧版
            const query = wx.createSelectorQuery();
            query
                .select('#' + this.canvasId)
                .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.canvasId, true, canvasNode);
                    echarts.setCanvasCreator(() => {
                        return canvas;
                    });
                    if (typeof callback === 'function') {
                        callback(canvas, canvasWidth, canvasHeight, canvasDpr);
                    } else {
                        this.triggerEvent('init', {
                            canvas: canvas,
                            width: canvasWidth,
                            height: canvasHeight,
                            dpr: canvasDpr,
                        });
                    }
                });
        },
        canvasToTempFilePath(opt) {
            const query = wx.createSelectorQuery().in(this);
            query
                .select('#' + this.canvasId)
                .fields({ node: true, size: true })
                .exec(res => {
                    const canvasNode = res[0].node;
                    opt.canvas = canvasNode;
                    wx.canvasToTempFilePath(opt);
                });
        },
        touchStart(e) {
            if (this.chart && e.touches.length > 0) {
                const touch = e.touches[0];
                const 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) {
                const touch = e.touches[0];
                const 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] : {};
                const 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');
            }
        },
    },
    mounted() {
        // 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;
                }
            }
        });
        setTimeout(() => {
            this.init((canvas, width, height, dpr) => {
                this.chart = echarts.init(canvas, null, {
                    width: width,
                    height: height,
                    devicePixelRatio: dpr, // 像素
                });
                canvas.setChart(this.chart);
                this.onReady && this.onReady(this.chart);
                this.chart.setOption({
                    tooltip: {
                        backgroundColor: 'rgba(50,50,50,0.7)',
                        textStyle: {
                            color: '#ffffff',
                        },
                        // 重新修正浮窗位置
                        position: (pos, params, dom, rect, size) => {
                            const [pX, pY] = pos;
                            const [contX, contY] = size.contentSize;
                            const [viewX, viewY] = size.viewSize;
                            const contentPoint = {};
                            // 鼠标在左侧时 tooltip 显示到右侧
                            if (pX < viewX / 2) {
                                contentPoint.right = Math.max(viewX - pX - contX, 0);
                            }
                            // 鼠标在右侧时 tooltip 显示到左侧。
                            else {
                                contentPoint.left = Math.max(pX - contX, 0);
                            }
                            // 限制不超过底部边界
                            if (pY + contY <= viewY) {
                                contentPoint.top = pY;
                            } else {
                                contentPoint.top = viewY - contY;
                            }
                            return contentPoint;
                        },
                    },
                });
            });
        }, 100);
    },
};
</script>