278 lines
6.4 KiB
Vue
278 lines
6.4 KiB
Vue
|
|
<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>
|