zhzf/client/src/components/PublicChart/index-20240627.vue

278 lines
6.4 KiB
Vue
Raw Normal View History

2025-02-21 11:25:09 +08:00
<template>
<div class="echarts" />
</template>
<script setup>
import { onMounted } from 'vue'
import * as echarts from 'echarts'
import theme from './theme/vab-echarts-theme.json'
import debounce from 'lodash/debounce'
import { addListener, removeListener } from 'resize-detector'
import { useThemeStore } from '@/stores/modules/theme'
const INIT_TRIGGERS = ['theme', 'initOptions', 'autoResize']
const REWATCH_TRIGGERS = ['manualUpdate', 'watchShallow']
const themeStore = useThemeStore()
const props = defineProps({
option: {
type: Object,
default: () => {},
},
theme: {
type: [String, Object],
default: () => {},
},
initOptions: {
type: Object,
default: () => {},
},
group: {
type: String,
default: '',
},
autoResize: {
type: Boolean,
default: true,
},
watchShallow: {
type: Boolean,
default: false,
},
manualUpdate: {
type: Boolean,
default: false,
},
})
const state = reactive({
chart: null,
lastArea: 0,
manualOptions: {},
})
const { chart, lastArea, manualOptions } = toRefs(state)
const { option, theme, group, initOptions, autoResize, watchShallow, manualUpdate } = toRefs(props)
// watch: {
// group(group) {
// chart.value.group = group
// },
// themeStore: {
// handler(data) {
// console.log(data)
// },
// deep: true,
// immediate: true,
// },
// },
onMounted(() => {
initOptionsWatcher()
INIT_TRIGGERS.forEach((prop) => {
this.$watch(
prop,
() => {
this.refresh()
},
{ deep: true }
)
})
REWATCH_TRIGGERS.forEach((prop) => {
this.$watch(prop, () => {
initOptionsWatcher()
this.refresh()
})
})
if (option.value) {
echarts.registerTheme('vab-echarts-theme', theme)
init()
}
})
const activated = () => {
if (autoResize.value) {
chart.value && chart.value.resize()
}
}
const destroyed = () => {
if (chart.value) {
this.destroy()
}
}
const mergeOptions = (option, notMerge, lazyUpdate) => {
if (manualUpdate.value) {
manualOptions.value = option
}
if (!chart.value) {
init(option)
} else {
delegateMethod('setOption', option, notMerge, lazyUpdate)
}
}
const appendData = (params) => {
delegateMethod('appendData', params)
}
const resize = (option) => {
delegateMethod('resize', option)
}
const dispatchAction = (payload) => {
delegateMethod('dispatchAction', payload)
}
const convertToPixel = (finder, value) => {
return delegateMethod('convertToPixel', finder, value)
}
const convertFromPixel = (finder, value) => {
return delegateMethod('convertFromPixel', finder, value)
}
const containPixel = (finder, value) => {
return delegateMethod('containPixel', finder, value)
}
const showLoading = (type, option) => {
delegateMethod('showLoading', type, option)
}
const hideLoading = () => {
delegateMethod('hideLoading')
}
const getDataURL = (option) => {
return delegateMethod('getDataURL', option)
}
const getConnectedDataURL = (option) => {
return delegateMethod('getConnectedDataURL', option)
}
const clear = () => {
delegateMethod('clear')
}
const dispose = () => {
delegateMethod('dispose')
}
const delegateMethod = (name, ...args) => {
if (!chart.value) {
init()
}
return chart.value[name](...args)
}
const delegateGet = (methodName) => {
if (!chart.value) {
init()
}
return chart.value[methodName]()
}
const getArea = () => {
return this.$el.offsetWidth * this.$el.offsetHeight
}
const init = (option) => {
if (chart.value) {
return
}
const newchart = echarts.init(this.$el, theme.value, initOptions.value)
if (group.value) {
newchart.group = group.value
}
newchart.setOption(option || manualOptions.value || option.value || {}, true)
Object.keys(this.$attrs).forEach((event) => {
const handler = this.$attrs[event]
if (event.indexOf('zr:') === 0) {
newchart.getZr().on(event.slice(3), handler)
} else {
newchart.on(event, handler)
}
})
if (autoResize.value) {
lastArea.value = getArea()
this.__resizeHandler = debounce(
() => {
if (lastArea.value === 0) {
this.mergeOptions({}, true)
this.resize()
this.mergeOptions(option.value || manualOptions.value || {}, true)
} else {
this.resize()
}
lastArea.value = getArea()
},
100,
{ leading: true }
)
addListener(this.$el, this.__resizeHandler)
}
Object.defineProperties(this, {
width: {
configurable: true,
get: () => {
return this.delegateGet('getWidth')
},
},
height: {
configurable: true,
get: () => {
return this.delegateGet('getHeight')
},
},
isDisposed: {
configurable: true,
get: () => {
return !!this.delegateGet('isDisposed')
},
},
computedOptions: {
configurable: true,
get: () => {
return this.delegateGet('getOption')
},
},
})
chart.value = chart
}
const initOptionsWatcher = () => {
if (this.__unwatchOptions) {
this.__unwatchOptions()
this.__unwatchOptions = null
}
if (!manualUpdate.value) {
this.__unwatchOptions = this.$watch(
'option',
(val, oldVal) => {
if (!chart.value && val) {
init()
} else {
chart.value.setOption(val, val !== oldVal)
}
},
{ deep: !this.watchShallow }
)
}
}
const destroy = () => {
if (autoResize.value) {
removeListener(this.$el, this.__resizeHandler)
}
this.dispose()
chart.value = null
}
const refresh = () => {
if (chart.value) {
this.destroy()
init()
}
}
const connect = (group) => {
if (typeof group !== 'string') {
group = group.map((chart) => chart.chart)
}
echarts.connect(group)
}
const disconnect = (group) => {
echarts.disConnect(group)
}
const getMap = (mapName) => {
return echarts.getMap(mapName)
}
// graphic: echarts.graphic,
</script>
<style>
.echarts {
/* width: 600px; */
height: 400px;
}
</style>