l-echart.uvue 5.48 KB
<template>
	<!-- #ifdef APP -->
	<web-view class="lime-echart" ref="chartRef" @loaded="loaded" :style="[customStyle]"
		:webview-styles="[webviewStyles]" src="/uni_modules/lime-echart/static/uvue.html?v=1011">
	</web-view>
	<!-- #endif -->
	<!-- #ifdef H5 -->
	<div class="lime-echart" ref="chartRef"></div>
	<!-- #endif -->
</template>

<script lang="uts" setup>
	// @ts-nocheck
	import { Echarts } from './uvue';
	type EchartsResolve = (value : Echarts) => void
	defineOptions({
		name: 'l-echart'
	})
	const emits = defineEmits(['finished'])
	const props = defineProps({
		// #ifdef APP
		webviewStyles: {
			type: Object
		},
		customStyle: {
			type: Object
		},
		// #endif
		// #ifndef APP
		webviewStyles: {
			type: Object
		},
		customStyle: {
			type: [String, Object]
		},
		// #endif
		isDisableScroll: {
			type: Boolean,
			default: false
		},
		isClickable: {
			type: Boolean,
			default: true
		},
		enableHover: {
			type: Boolean,
			default: false
		},
		beforeDelay: {
			type: Number,
			default: 30
		}
	})

	const finished = ref(false)
	const map = [] as EchartsResolve[]
	const callbackMap = [] as EchartsResolve[]
	// let context = null as UniWebViewElement | null
	let chart = null as Echarts | null
	let chartRef = ref<UniWebViewElement | null>(null)
	
	const trigger = () => {
		// #ifdef APP
		if (finished.value) {
			if (chart == null) {
				chart = new Echarts(chartRef.value!)
			}
			while (map.length > 0) {
				const resolve = map.pop() as EchartsResolve
				resolve(chart!)
			}
		}
		// #endif
		// #ifdef H5
		while (map.length > 0) {
			if(chart != null){
				const resolve = map.pop() as EchartsResolve
				resolve(chart!)
			}
		}
		// #endif
		
		if(chart != null){
			while(callbackMap.length > 0){
				const callback = callbackMap.pop() as EchartsResolve
				callback(chart!)
			}
		}
	}
	
	// #ifdef APP
	const loaded = (event : WebViewLoadedEvent) => {
		event.stopPropagation()
		event.preventDefault()
		finished.value = true
		trigger()
		emits('finished')
	}
	// #endif
	
	
	const _next = () : boolean => {
		if (chart == null) {
			console.warn(`组件还未初始化,请先使用 init`)
			return true
		}
		return false
	}
	const setOption = (option : UTSJSONObject) => {
		if (_next()) return
		chart!.setOption(option);
	}
	const showLoading = () => {
		if (_next()) return
		chart!.showLoading();
	}
	const hideLoading = () => {
		if (_next()) return
		chart!.hideLoading();
	}
	const clear = () => {
		if (_next()) return
		chart!.clear();
	}
	const dispose = () => {
		if (_next()) return
		chart!.dispose();
	}
	const resize = (size : UTSJSONObject) => {
		if (_next()) return
		chart!.resize(size);
	}
	const canvasToTempFilePath = (opt : UTSJSONObject) => {
		if (_next()) return
		chart!.canvasToTempFilePath(opt);
	}
	// function init() : Promise<Echarts> {
	// 	return new Promise((resolve) => {
	// 		map.push(resolve)
	// 		trigger()
	// 	})
	// }
	// #ifdef APP
	function init(callback : ((chart : Echarts) => void) | null) : Promise<Echarts> {
		// if (chart !== null && callback != null) {
		// 	callback(chart!)
		// } else {
		// 	console.warn('echarts 未加载完成,您可以延时一下')
		// }
		if(callback!=null){
			callbackMap.push(callback)
		}
		return new Promise<Echarts>((resolve) => {
			map.push(resolve)
			trigger()
		})
	}
	// #endif
	// #ifdef H5
	const touchstart = (e) => {
		if(chart == null) return
		const handler = chart.getZr().handler;
		const rect = chart.getZr().dom.getBoundingClientRect()
		handler.dispatch('mousedown', {
			zrX: e.touches[0].clientX - rect.left,
			zrY: e.touches[0].clientY - rect.top
		})
		handler.dispatch('click', {
			zrX: e.touches[0].clientX - rect.left,
			zrY: e.touches[0].clientY - rect.top
		})
	}
	const touchmove = (e) => {
		if(chart == null) return
		const handler = chart.getZr().handler;
		const rect = chart.getZr().dom.getBoundingClientRect()
		handler.dispatch('mousemove', {
			zrX: e.touches[0].clientX - rect.left,
			zrY: e.touches[0].clientY - rect.top
		})
	}
	const mouseup = (e) => {
		if(chart == null) return
		const handler = chart.getZr().handler;
		handler.dispatch('mousemove', {
			zrX: 999999999,
			zrY: 999999999
		})
		handler.dispatch('mouseup', {
			zrX: 999999999,
			zrY: 999999999
		})
	}
	function init(echarts: any, ...args: any[]): Promise<Echarts>{
		if(echarts == null){
			console.error('请确保已经引入了 ECharts 库');
			return Promise.reject('请确保已经引入了 ECharts 库');
		}
		let theme:string|null=null
		let opts={}
		let callback:Function|null=null;
		
		args.forEach(item =>{
			if(typeof item === 'function') {
				callback = item
			} else if(['string'].includes(typeof item)){
				theme = item
			} else if(typeof item === 'object'){
				opts = item
			}
		})
		chart = echarts.init(chartRef.value, theme, opts)
		window.addEventListener('touchstart', touchstart)
		window.addEventListener('touchmove', touchmove)
		window.addEventListener('touchend', mouseup)
		
		if(callback!=null && typeof callback == 'function'){
			callbackMap.push(callback)
		}
		return new Promise<Echarts>((resolve) => {
			map.push(resolve)
			trigger()
		})
	}
	onMounted(()=>{
		finished.value = true
		trigger()
		emits('finished')
	})
	onUnmounted(()=>{
		window.removeEventListener('touchstart', touchstart)
		window.removeEventListener('touchmove', touchmove)
		window.removeEventListener('touchend', mouseup)
	})
	// #endif
	
	defineExpose({
		init,
		setOption,
		showLoading,
		hideLoading,
		clear,
		dispose,
		resize,
		canvasToTempFilePath
	})
</script>
<style lang="scss">
	.lime-echart {
		flex: 1;
	}
</style>