|
@@ -1,484 +0,0 @@
|
|
|
-<template>
|
|
|
|
|
- <!-- #ifndef APP-NVUE || WEB -->
|
|
|
|
|
- <view class="lime-echart"
|
|
|
|
|
- :style="[lStyle]"
|
|
|
|
|
- v-if="canvasId"
|
|
|
|
|
- ref="chartContainer"
|
|
|
|
|
- :aria-label="'图表'">
|
|
|
|
|
- <canvas class="lime-echart__canvas"
|
|
|
|
|
- type="2d"
|
|
|
|
|
- :style="[styles]"
|
|
|
|
|
- :id="canvasId"
|
|
|
|
|
- :disable-scroll="isDisableScroll"
|
|
|
|
|
- :canvas-id="canvasId"
|
|
|
|
|
- @touchstart="handleTouchStart"
|
|
|
|
|
- @touchmove="handleTouchMove"
|
|
|
|
|
- @touchend="handleTouchEnd">
|
|
|
|
|
- </canvas>
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- #endif -->
|
|
|
|
|
- <!-- #ifdef WEB -->
|
|
|
|
|
- <div class="lime-echart" ref="chartContainer" :style="[styles, lStyle]"></div>
|
|
|
|
|
- <!-- #endif -->
|
|
|
|
|
- <!-- #ifdef APP-NVUE -->
|
|
|
|
|
- <view class="lime-echart" :style="[lStyle]">
|
|
|
|
|
- <web-view class="lime-echart__canvas"
|
|
|
|
|
- :webview-styles="webviewStyles"
|
|
|
|
|
- :style="[styles]"
|
|
|
|
|
- ref="chartContainer"
|
|
|
|
|
- src="/uni_modules/lime-echart/static/app/uvue.html?v=1"
|
|
|
|
|
- @pagefinish="isInitialized = true"
|
|
|
|
|
- @onPostMessage="handleWebviewMessage"></web-view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <!-- #endif -->
|
|
|
|
|
-</template>
|
|
|
|
|
-
|
|
|
|
|
-<script lang="ts">
|
|
|
|
|
- // @ts-nocheck
|
|
|
|
|
- import { defineComponent, getCurrentInstance, ref, onMounted, nextTick, onBeforeUnmount, watch, computed } from './vue'
|
|
|
|
|
- import echartProps from './props'
|
|
|
|
|
-
|
|
|
|
|
- // #ifndef APP-NVUE || WEB
|
|
|
|
|
- import { Canvas, setCanvasCreator, dispatch } from './canvas';
|
|
|
|
|
- import { wrapTouch, convertTouchesToArray, devicePixelRatio ,sleep, canIUseCanvas2d, getRect, getDeviceInfo } from './utils';
|
|
|
|
|
- // #endif
|
|
|
|
|
- // #ifdef APP-NVUE
|
|
|
|
|
- import { base64ToPath, sleep } from './utils';
|
|
|
|
|
- import { Echarts } from './nvue'
|
|
|
|
|
- // #endif
|
|
|
|
|
- // #ifdef WEB
|
|
|
|
|
- import * as echartsLibrary from '@/uni_modules/lime-echart/static/web/echarts.esm.min.js';
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef APP-VUE
|
|
|
|
|
- import '@/uni_modules/lime-echart/static/app/echarts.min.js';
|
|
|
|
|
- const echartsLibrary = globalThis.echarts
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- export default defineComponent({
|
|
|
|
|
- props: echartProps,
|
|
|
|
|
- emits: ['finished'],
|
|
|
|
|
- setup(props, { emit, expose }) {
|
|
|
|
|
- // #ifndef APP-NVUE || WEB || APP-VUE
|
|
|
|
|
- let echartsLibrary = null
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
- const instance = getCurrentInstance()!;
|
|
|
|
|
- const canvasId = `lime-echart-${instance.uid}`
|
|
|
|
|
- const isInitialized = ref(false)
|
|
|
|
|
- const chartContainer = ref(null)
|
|
|
|
|
-
|
|
|
|
|
- type ChartOptions = Record<string, any>
|
|
|
|
|
- type EChartsInstance = typeof echartsLibrary
|
|
|
|
|
- type EChartsResolveCallback = (value: EChartsInstance) => void
|
|
|
|
|
-
|
|
|
|
|
- const initializationQueue = [] as EChartsResolveCallback[]
|
|
|
|
|
- const callbackQueue = [] as EChartsResolveCallback[]
|
|
|
|
|
-
|
|
|
|
|
- let chartInstance: null | EChartsInstance = null
|
|
|
|
|
-
|
|
|
|
|
- const styles = computed(()=> {
|
|
|
|
|
- if(props.landscape) {
|
|
|
|
|
- return {
|
|
|
|
|
- transform: 'translate(-50%,-50%) rotate(90deg)',
|
|
|
|
|
- top: '50%',
|
|
|
|
|
- left: '50%',
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return {}
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- const checkInitialization = (): boolean => {
|
|
|
|
|
- if(chartInstance) return false
|
|
|
|
|
- console.warn(`组件还未初始化,请先使用 init`)
|
|
|
|
|
- return true
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const setOption = (options: ChartOptions) => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartInstance!.setOption(options);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const hideLoading = () => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartInstance!.showLoading();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const showLoading = () => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartInstance!.hideLoading();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const clear = () => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartInstance!.clear();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const dispose = () => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartInstance!.dispose();
|
|
|
|
|
- }
|
|
|
|
|
- const processInitializationQueue = () => {
|
|
|
|
|
- while (initializationQueue.length > 0) {
|
|
|
|
|
- if (chartInstance != null) {
|
|
|
|
|
- const resolve = initializationQueue.pop() as EChartsResolveCallback
|
|
|
|
|
- resolve(chartInstance!)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (chartInstance != null) {
|
|
|
|
|
- while (callbackQueue.length > 0) {
|
|
|
|
|
- const callback = callbackQueue.pop() as EChartsResolveCallback
|
|
|
|
|
- callback(chartInstance!)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const resize = (dimensions?: { width?: number; height?: number }) => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- // #ifdef APP-NVUE || WEB
|
|
|
|
|
- chartInstance!.resize(dimensions);
|
|
|
|
|
- // #endif
|
|
|
|
|
- // #ifndef APP-NVUE || WEB
|
|
|
|
|
- getRect(`#${canvasId}`, instance.proxy).then(res => {
|
|
|
|
|
- chartInstance!.resize({width: res.width, height: res.height});
|
|
|
|
|
- })
|
|
|
|
|
- // #endif
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef APP-NVUE
|
|
|
|
|
- let chartFile = ref(null);
|
|
|
|
|
- const handleWebviewMessage = (e) => {
|
|
|
|
|
- const detail = e?.detail?.data[0] || null;
|
|
|
|
|
- const data = detail?.data
|
|
|
|
|
- const key = detail?.event
|
|
|
|
|
- const options = data?.options
|
|
|
|
|
- const event = data?.event
|
|
|
|
|
- const file = detail?.file
|
|
|
|
|
- if (key == 'log' && data) {
|
|
|
|
|
- console.log(data)
|
|
|
|
|
- }
|
|
|
|
|
- if(event) {
|
|
|
|
|
- chartInstance.dispatchAction(event.replace(/"/g,''), options)
|
|
|
|
|
- }
|
|
|
|
|
- if(file) {
|
|
|
|
|
- chartFile.value = file
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const canvasToTempFilePath = (options: ChartOptions) => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- chartContainer.value.evalJs(`canvasToTempFilePath()`);
|
|
|
|
|
- watch(chartFile, async (file) =>{
|
|
|
|
|
- if(!file) return
|
|
|
|
|
- const tempFilePath = await base64ToPath(file)
|
|
|
|
|
- options.success({tempFilePath})
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const getContext = () => {
|
|
|
|
|
- if(isInitialized.value) {
|
|
|
|
|
- return Promise.resolve(isInitialized.value)
|
|
|
|
|
- }
|
|
|
|
|
- return new Promise(resolve => {
|
|
|
|
|
- watch(isInitialized, (val) =>{
|
|
|
|
|
- if(!val) return
|
|
|
|
|
- resolve(val)
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- const init = async (echarts, ...args) => {
|
|
|
|
|
- let theme: string | null = null
|
|
|
|
|
- let config:Record<string, any> = {}
|
|
|
|
|
- let callback: Function | null = null;
|
|
|
|
|
-
|
|
|
|
|
- args.forEach(item => {
|
|
|
|
|
- if (typeof item === 'function') {
|
|
|
|
|
- callback = item
|
|
|
|
|
- } else if (typeof item === 'string') {
|
|
|
|
|
- theme = item
|
|
|
|
|
- } else if (typeof item === 'object') {
|
|
|
|
|
- config = item
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- if(props.beforeDelay) {
|
|
|
|
|
- await sleep(props.beforeDelay)
|
|
|
|
|
- }
|
|
|
|
|
- await getContext();
|
|
|
|
|
- chartInstance = new Echarts(chartContainer.value)
|
|
|
|
|
- chartContainer.value.evalJs(`init(null, null, ${JSON.stringify(config)}, ${theme})`)
|
|
|
|
|
- if (callback && typeof callback === 'function') {
|
|
|
|
|
- callbackQueue.push(callback)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return new Promise<EChartsInstance>((resolve) => {
|
|
|
|
|
- nextTick(()=>{
|
|
|
|
|
- initializationQueue.push(resolve)
|
|
|
|
|
- processInitializationQueue()
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // #ifndef APP-NVUE || WEB
|
|
|
|
|
- let canvasNode;
|
|
|
|
|
- const canvasToTempFilePath = (options: ChartOptions) => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- if(canvasNode) {
|
|
|
|
|
- options.success?.({
|
|
|
|
|
- tempFilePath: canvasNode.toDataURL()
|
|
|
|
|
- })
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.canvasToTempFilePath({
|
|
|
|
|
- ...options,
|
|
|
|
|
- canvasId
|
|
|
|
|
- }, instance.proxy);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const getContext = () => {
|
|
|
|
|
- return getRect(`#${canvasId}`, instance.proxy).then(res => {
|
|
|
|
|
- let dpr = devicePixelRatio
|
|
|
|
|
- let {width, height, node} = res
|
|
|
|
|
- let canvas: Canvas | null = null;
|
|
|
|
|
- if(!(width || height)) {
|
|
|
|
|
- return Promise.reject('no rect')
|
|
|
|
|
- }
|
|
|
|
|
- if(node && node.getContext) {
|
|
|
|
|
- const ctx = node.getContext('2d');
|
|
|
|
|
- canvas = new Canvas(ctx, instance.proxy, true, node);
|
|
|
|
|
- canvasNode = node
|
|
|
|
|
- } else {
|
|
|
|
|
- dpr = 1
|
|
|
|
|
- const ctx = uni.createCanvasContext(canvasId, instance.proxy);
|
|
|
|
|
- canvas = new Canvas(ctx, instance.proxy, false);
|
|
|
|
|
- }
|
|
|
|
|
- return { canvas, width, height, devicePixelRatio: dpr, node }
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- const getTouch = (e) => {
|
|
|
|
|
- const touches = e.touches[0]
|
|
|
|
|
- const touch = props.landscape
|
|
|
|
|
- ? {
|
|
|
|
|
- x: touches.y,
|
|
|
|
|
- y: touches.x
|
|
|
|
|
- }
|
|
|
|
|
- : {
|
|
|
|
|
- x: touches.x,
|
|
|
|
|
- y: touches.y
|
|
|
|
|
- }
|
|
|
|
|
- return touch
|
|
|
|
|
- }
|
|
|
|
|
- const handleTouchStart = (e) => {
|
|
|
|
|
- if (chartInstance == null) return
|
|
|
|
|
- const handler = chartInstance.getZr().handler;
|
|
|
|
|
- const touch = getTouch(e)
|
|
|
|
|
- dispatch.call(handler, 'mousedown', touch)
|
|
|
|
|
- dispatch.call(handler, 'click', touch)
|
|
|
|
|
- }
|
|
|
|
|
- const handleTouchMove = (e) => {
|
|
|
|
|
- if (chartInstance == null) return
|
|
|
|
|
- const handler = chartInstance.getZr().handler;
|
|
|
|
|
- const touch = getTouch(e)
|
|
|
|
|
- dispatch.call(handler, 'mousemove', touch)
|
|
|
|
|
- }
|
|
|
|
|
- const handleTouchEnd = (e) => {
|
|
|
|
|
- if (chartInstance == null || !props.autoHideTooltip) return
|
|
|
|
|
- const handler = chartInstance.getZr().handler;
|
|
|
|
|
-
|
|
|
|
|
- const touch = {
|
|
|
|
|
- x: 999999999,
|
|
|
|
|
- y: 999999999
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- dispatch.call(handler, 'mousemove', touch)
|
|
|
|
|
- dispatch.call(handler, 'touchend', touch)
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
- const init = async (echartsLib: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
|
|
|
|
- const library = echartsLib || echartsLibrary
|
|
|
|
|
- if (!library) {
|
|
|
|
|
- console.error('ECharts library is required');
|
|
|
|
|
- return Promise.reject('ECharts library is required');
|
|
|
|
|
- }
|
|
|
|
|
- let theme: string | null = null
|
|
|
|
|
- let config:Record<string, any> = {}
|
|
|
|
|
- let callback: Function | null = null;
|
|
|
|
|
-
|
|
|
|
|
- args.forEach(item => {
|
|
|
|
|
- if (typeof item === 'function') {
|
|
|
|
|
- callback = item
|
|
|
|
|
- } else if (typeof item === 'string') {
|
|
|
|
|
- theme = item
|
|
|
|
|
- } else if (typeof item === 'object') {
|
|
|
|
|
- config = item
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
- if(props.beforeDelay) {
|
|
|
|
|
- await sleep(props.beforeDelay)
|
|
|
|
|
- }
|
|
|
|
|
- let options = await getContext();
|
|
|
|
|
- setCanvasCreator(library, options)
|
|
|
|
|
- chartInstance = library.init(options.canvas, theme, Object.assign({}, options, config))
|
|
|
|
|
- if (callback && typeof callback === 'function') {
|
|
|
|
|
- callbackQueue.push(callback)
|
|
|
|
|
- }
|
|
|
|
|
- return new Promise<EChartsInstance>((resolve) => {
|
|
|
|
|
- initializationQueue.push(resolve)
|
|
|
|
|
- processInitializationQueue()
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef WEB
|
|
|
|
|
- const canvasToTempFilePath = (options: ChartOptions) => {
|
|
|
|
|
- if (checkInitialization()) return
|
|
|
|
|
- options.success?.({
|
|
|
|
|
- tempFilePath: chartInstance._api.getDataURL()
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- const init = async (echarts: EChartsInstance = echartsLibrary, ...args: any[]): Promise<EChartsInstance> => {
|
|
|
|
|
- const library = echarts || echartsLibrary
|
|
|
|
|
- if (!library) {
|
|
|
|
|
- console.error('ECharts library is required');
|
|
|
|
|
- return Promise.reject('ECharts library is required');
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- let theme: string | null = null
|
|
|
|
|
- let config = {}
|
|
|
|
|
- let callback: Function | null = null;
|
|
|
|
|
-
|
|
|
|
|
- args.forEach(item => {
|
|
|
|
|
- if (typeof item === 'function') {
|
|
|
|
|
- callback = item
|
|
|
|
|
- } else if (typeof item === 'string') {
|
|
|
|
|
- theme = item
|
|
|
|
|
- } else if (typeof item === 'object') {
|
|
|
|
|
- config = item
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // Configure ECharts environment
|
|
|
|
|
- library.env.domSupported = true
|
|
|
|
|
- library.env.hasGlobalWindow = true
|
|
|
|
|
- library.env.node = false
|
|
|
|
|
- library.env.pointerEventsSupported = false
|
|
|
|
|
- library.env.svgSupported = true
|
|
|
|
|
- library.env.touchEventsSupported = true
|
|
|
|
|
- library.env.transform3dSupported = true
|
|
|
|
|
- library.env.transformSupported = true
|
|
|
|
|
- library.env.worker = false
|
|
|
|
|
- library.env.wxa = false
|
|
|
|
|
-
|
|
|
|
|
- chartInstance = library.init(chartContainer.value, theme, config)
|
|
|
|
|
-
|
|
|
|
|
- if (callback != null && typeof callback === 'function') {
|
|
|
|
|
- callbackQueue.push(callback)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return new Promise<EChartsInstance>((resolve) => {
|
|
|
|
|
- initializationQueue.push(resolve)
|
|
|
|
|
- processInitializationQueue()
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- onMounted(() => {
|
|
|
|
|
- nextTick(() => {
|
|
|
|
|
- // #ifndef APP-NVUE
|
|
|
|
|
- isInitialized.value = true
|
|
|
|
|
- // #endif
|
|
|
|
|
- emit('finished')
|
|
|
|
|
- processInitializationQueue()
|
|
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- onBeforeUnmount(()=> {
|
|
|
|
|
- clear()
|
|
|
|
|
- dispose()
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef VUE3
|
|
|
|
|
- expose({
|
|
|
|
|
- init,
|
|
|
|
|
- setOption,
|
|
|
|
|
- hideLoading,
|
|
|
|
|
- showLoading,
|
|
|
|
|
- clear,
|
|
|
|
|
- dispose,
|
|
|
|
|
- resize,
|
|
|
|
|
- canvasToTempFilePath
|
|
|
|
|
- })
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
- return {
|
|
|
|
|
- canvasId,
|
|
|
|
|
- chartContainer,
|
|
|
|
|
- styles,
|
|
|
|
|
- // #ifndef WEB || APP-NVUE
|
|
|
|
|
- handleTouchStart,
|
|
|
|
|
- handleTouchMove,
|
|
|
|
|
- handleTouchEnd,
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef APP-NVUE
|
|
|
|
|
- handleWebviewMessage,
|
|
|
|
|
- isInitialized,
|
|
|
|
|
- // #endif
|
|
|
|
|
-
|
|
|
|
|
- // #ifdef VUE2
|
|
|
|
|
- init,
|
|
|
|
|
- setOption,
|
|
|
|
|
- hideLoading,
|
|
|
|
|
- showLoading,
|
|
|
|
|
- clear,
|
|
|
|
|
- dispose,
|
|
|
|
|
- resize,
|
|
|
|
|
- canvasToTempFilePath,
|
|
|
|
|
- // #endif
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-</script>
|
|
|
|
|
-
|
|
|
|
|
-<style>
|
|
|
|
|
- .lime-echart {
|
|
|
|
|
- position: relative;
|
|
|
|
|
- /* #ifndef APP-NVUE */
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- /* #endif */
|
|
|
|
|
- /* #ifdef APP-NVUE */
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- /* #endif */
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- .lime-echart__canvas {
|
|
|
|
|
- /* #ifndef APP-NVUE */
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- /* #endif */
|
|
|
|
|
- /* #ifdef APP-NVUE */
|
|
|
|
|
- flex: 1;
|
|
|
|
|
- /* #endif */
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- /* #ifndef APP-NVUE */
|
|
|
|
|
- .lime-echart__mask {
|
|
|
|
|
- position: absolute;
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
- left: 0;
|
|
|
|
|
- top: 0;
|
|
|
|
|
- z-index: 1;
|
|
|
|
|
- }
|
|
|
|
|
- /* #endif */
|
|
|
|
|
-</style>
|
|
|