Files
JiaZhiQianYan/uni_modules/lime-echart/components/l-echart/l-echart.uvue
2025-06-30 19:02:44 +08:00

373 lines
9.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- #ifdef APP -->
<web-view class="lime-echart" ref="chartRef" @load="loaded" :style="[customStyle]" :webview-styles="[webviewStyles]"
src="/uni_modules/lime-echart/static/uvue.html?v=10112">
</web-view>
<!-- #endif -->
<!-- #ifdef H5 -->
<div class="lime-echart" ref="chartRef"></div>
<!-- #endif -->
<!-- #ifndef H5 || APP-->
<view class="lime-echart">
<canvas style="width:100%; height:100%" v-if="canvasid" :id="canvasid" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
</view>
<!-- #endif -->
</template>
<script lang="uts" setup>
// @ts-nocheck
import { getCurrentInstance, nextTick } from "vue";
import { Echarts } from './uvue';
// #ifdef WEB
import { dispatch } from './canvas';
// #endif
// #ifndef APP || WEB
import { Canvas, setCanvasCreator, dispatch } from './canvas';
import { wrapTouch, convertTouchesToArray, devicePixelRatio, sleep, canIUseCanvas2d, getRect } from './utils';
// #endif
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 instance = getCurrentInstance()!;
const canvasid = `lime-echart-${instance.uid}`
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
// #ifndef APP
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 resizeObserver = new UniResizeObserver((entries : Array<UniResizeObserverEntry>) => {
// const rect = entries[0].target.getBoundingClientRect()
// if((rect.width > 0 || rect.height > 0) && !finished.value) {
// finished.value = true
// trigger()
// emits('finished')
// }
// })
// const stopWatch = watch(():UniElement|null => chartRef.value, (el:UniElement|null) => {
// if(el== null) return
// resizeObserver.observe(el)
// })
const loaded = (event : UniWebViewLoadEvent) => {
event.stopPropagation()
event.preventDefault()
nextTick(()=> {
chartRef.value?.getBoundingClientRectAsync()?.then(res => {
if(res.width > 0 && res.height > 0) {
finished.value = true
trigger()
emits('finished')
} else {
console.warn('【lime-echart】获取尺寸失败请检查代码样式')
}
})
})
}
// #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);
}
// #ifdef APP
function init(callback : ((chart : Echarts) => void) | null) : Promise<Echarts> {
if (callback != null) {
callbackMap.push(callback)
}
return new Promise<Echarts>((resolve) => {
map.push(resolve)
trigger()
})
}
// onUnmounted(()=>{
// stopWatch()
// resizeObserver.disconnect()
// })
// #endif
// #ifndef APP
// #ifndef WEB
let use2dCanvas = canIUseCanvas2d()
const getContext = async () => {
return new Promise((resolve, reject)=>{
uni.createCanvasContextAsync({
id: canvasid,
component: instance.proxy!,
success: (context : CanvasContext) => {
const canvasContext = context.getContext('2d')!;
const canvas = canvasContext.canvas;
let uniCanvas;
const width = canvas.offsetWidth
const height = canvas.offsetHeight
// 处理高清屏逻辑
const dpr = uni.getDeviceInfo().devicePixelRatio ?? 1;
canvas.width = canvas.offsetWidth * dpr;
canvas.height = canvas.offsetHeight * dpr;
canvasContext.scale(dpr, dpr); // 仅需调用一次,当调用 reset 方法后需要再次 scale
if(use2dCanvas) {
uniCanvas = new Canvas(canvasContext, instance.proxy, true, context);
} else {
uniCanvas = new Canvas(canvasContext, instance.proxy, false);
}
resolve({ canvas: uniCanvas, width, height, devicePixelRatio: 1, node: context});
},
fail(err) {
reject(err)
console.log('err', err)
}
})
})
// return getRect(`#${canvasid}`, {context: instance.proxy!, type: use2dCanvas ? 'fields': 'boundingClientRect'}).then(res => {
// if(res) {
// let dpr = uni.getWindowInfo().pixelRatio
// let {width, height, node} = res
// let canvas;
// if(node) {
// const ctx = node.getContext('2d');
// canvas = new Canvas(ctx, instance.proxy, true, node);
// } else {
// const ctx = uni.createCanvasContext(canvasid, instance.proxy);
// canvas = new Canvas(ctx, instance.proxy, false);
// }
// return { canvas, width, height, devicePixelRatio: dpr, node };
// } else {
// return {}
// }
// })
}
// #endif
const getTouch = (e) => {
const touches = e.touches[0]
// #ifdef WEB
const rect = chart!.getZr().dom.getBoundingClientRect();
const touch = {
x: touches.clientX - rect.left,
y: touches.clientY - rect.top
}
// #endif
// #ifndef WEB
const touch = {
x: touches.x,
y: touches.y
}
// #endif
return touch
}
const touchstart = (e) => {
if (chart == null) return
const handler = chart.getZr().handler;
const touch = getTouch(e)
dispatch.call(handler, 'mousedown', touch)
dispatch.call(handler, 'click', touch)
}
const touchmove = (e) => {
if (chart == null) return
const handler = chart.getZr().handler;
const touch = getTouch(e)
dispatch.call(handler, 'mousemove', touch)
// const rect = chart.getZr().dom.getBoundingClientRect()
// handler.dispatch('mousemove', {
// zrX: e.touches[0].clientX - rect.left,
// zrY: e.touches[0].clientY - rect.top
// })
}
const touchend = (e) => {
if (chart == null) return
const handler = chart.getZr().handler;
const touch = {
x: 999999999,
y: 999999999
}
dispatch.call(handler, 'mousemove', touch)
dispatch.call(handler, 'touchend', touch)
}
async 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
}
})
// #ifdef WEB
echarts.env.domSupported = true
echarts.env.hasGlobalWindow = true
echarts.env.node = false
echarts.env.pointerEventsSupported = false
echarts.env.svgSupported = true
echarts.env.touchEventsSupported = true
echarts.env.transform3dSupported = true
echarts.env.transformSupported = true
echarts.env.worker = false
echarts.env.wxa = false
chart = echarts.init(chartRef.value, theme, opts)
// window.addEventListener('touchstart', touchstart)
// window.addEventListener('touchmove', touchmove)
// window.addEventListener('touchend', touchend)
// #endif
// #ifndef WEB
let config = await getContext();
setCanvasCreator(echarts, config)
chart = echarts.init(config.canvas, theme, Object.assign({}, config, opts))
// #endif
if (callback != null && typeof callback == 'function') {
callbackMap.push(callback)
}
return new Promise<Echarts>((resolve) => {
map.push(resolve)
trigger()
})
}
onMounted(() => {
nextTick(() => {
finished.value = true
trigger()
emits('finished')
})
})
onUnmounted(() => {
// #ifdef WEB
// window.removeEventListener('touchstart', touchstart)
// window.removeEventListener('touchmove', touchmove)
// window.removeEventListener('touchend', touchend)
// #endif
})
// #endif
defineExpose({
init,
setOption,
showLoading,
hideLoading,
clear,
dispose,
resize,
canvasToTempFilePath
})
</script>
<style lang="scss">
.lime-echart {
flex: 1;
width: 100%;
}
</style>