1.引言
最近在做一个管理系统,主要技术栈使用的是Vue3+TS+Vite+ElementPlus,主要参考项目是yudao-ui-admin-vue3,其中用到ECharts5做数字大屏,展示中国地图相关信息,以此基础做一个分享,写下这篇文章。
"dependencies": {
"@element-plus/icons-vue": "^2.1.0",
"@kjgl77/datav-vue3": "^1.6.1",
"@vueuse/core": "^10.2.1",
"echarts": "^5.4.2",
"echarts-wordcloud": "^2.1.0",
"element-plus": "2.3.7",
"vue": "3.3.4",
"vue-i18n": "9.2.2",
"vue-router": "^4.2.4",
"vue-types": "^5.1.0",
"vuedraggable": "^4.1.0"
}
在读这篇文章之前,建议先读一下自适应大屏容器组件这篇文章。
2.封装ECharts组件
通常在实际项目中,需要用到ECharts图表的地方肯定很多,我们可以封装一个ECharts组件,方便使用,这里在 yudao-ui-admin-vue3基础上,添加了一个响应式变量,为了在引用ECharts父组件中获取到ECharts初始化实例,在地图中自动随机显示各省份数据的函数中使用。
为什么要添加这个响应式变量了?我实际使用中遇到的问题,如果把ECharts初始化实例赋值为响应式变量,会导致tooltip提示框在设置trigger: ‘axis’显示不出来,如果赋值为非响应式变量,父组件接受变量时数据为空,拿不到数据,所以我的解决办法是添加一个响应式变量,这样双方都可以满足。
<script lang="ts" setup>
import type { EChartsOption } from 'echarts'
import echarts from '@/plugins/echarts'
import { debounce } from 'lodash-es'
import 'echarts-wordcloud'
import { propTypes } from '@/utils/propTypes'
import { PropType } from 'vue'
import { useAppStore } from '@/store/modules/app'
import { isString } from '@/utils/is'
import { useDesign } from '@/hooks/web/useDesign'
defineOptions({ name: 'EChart' })
const { getPrefixCls, variables } = useDesign()
const prefixCls = getPrefixCls('echart')
const appStore = useAppStore()
const props = defineProps({
options: {
type: Object as PropType<EChartsOption>,
required: true
},
width: propTypes.oneOfType([Number, String]).def('100%'),
height: propTypes.oneOfType([Number, String]).def('100%')
})
const isDark = computed(() => appStore.getIsDark)
const theme = computed(() => {
const echartTheme: boolean | string = unref(isDark) ? true : 'auto'
return echartTheme
})
const options = computed(() => {
return Object.assign(props.options, {
darkMode: unref(theme)
})
})
const elRef = ref<ElRef>()
let echartRef: Nullable<echarts.ECharts> = null
/**********************添加的响应式变量******************/
const eChart = ref()
const contentEl = ref<Element>()
const styles = computed(() => {
const width = isString(props.width) ? props.width : `${props.width}px`
const height = isString(props.height) ? props.height : `${props.height}px`
return {
width,
height
}
})
const initChart = () => {
if (unref(elRef) && props.options) {
echartRef = echarts.init(unref(elRef) as HTMLElement)
echartRef?.setOption(unref(options))
/**********************初始化后再赋值******************/
eChart.value = echartRef
}
}
watch(
() => options.value,
(options) => {
if (echartRef) {
echartRef?.setOption(options)
}
},
{
deep: true
}
)
const resizeHandler = debounce(() => {
if (echartRef) {
echartRef.resize()
}
}, 100)
const contentResizeHandler = async (e: TransitionEvent) => {
if (e.propertyName === 'width') {
resizeHandler()
}
}
onMounted(() => {
initChart()
window.addEventListener('resize', resizeHandler)
contentEl.value = document.getElementsByClassName(`${variables.namespace}-layout-content`)[0]
unref(contentEl) &&
(unref(contentEl) as Element).addEventListener('transitionend', contentResizeHandler)
})
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeHandler)
unref(contentEl) &&
(unref(contentEl) as Element).removeEventListener('transitionend', contentResizeHandler)
})
onActivated(() => {
if (echartRef) {
echartRef.resize()
}
})
defineExpose({ eChart })
</script>
<template>
<div ref="elRef" :class="[$attrs.class, prefixCls]" :style="styles"></div>
</template>
3.数据的准备
数据主要分为ECharts5需要的中国地图数据,需要显示的自定义数据,以及各个省份的中心经纬度数据。
1.地图数据。由于ECharts5地图不能直接引入,需要自己下载JSON数据,然后引入。地图数据下载地址为阿里云数据可视化平台,下载JSON数据,可根据自己的需要对南海诸岛的数据做编辑。数据下载后,放入asserts目录中,引入。
2.自定义显示数据。自定义显示数据就是想要在地图上显示的信息,当鼠标点击某个省份后,tooltip显示框显示的数据内容。本地中,显示的数据为各个省份合同数以及合同金额,如下图所示。
数据格式为:
interface digitalScreenDataType {
name: string
value: number
}
interface contractInfoForFirstArea {
name: string
contractInfoByFirstArea: digitalScreenDataType[]
}
数据内容举例:
[
{
name: '北京市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.9923 },
{ name: '合同总数', value: 51 }
]
},
{
name: '天津市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 170.2683 },
{ name: '合同总数', value: 30790 }
]
}
]
3.各个省份的中心经纬度数据。此数据主要为了显示各省份的中心点,利用的ECharts的配置,可以让中心点具有不同的显示效果。ECharts文档传送门。
数据定义:
const geoCodeMap = [
{ name: '北京市', delay: 63, lossPercent: 2, value: [119.337634104, 26.0911937119] },
{ name: '天津市', delay: 63, lossPercent: 2, value: [117.190182, 39.125596] },
{ name: '河北省', delay: 63, lossPercent: 2, value: [114.502461, 38.045474] },
{ name: '山西省', delay: 63, lossPercent: 2, value: [112.549248, 37.857014] },
{ name: '内蒙古自治区', delay: 63, lossPercent: 2, value: [111.670801, 40.818311] },
{ name: '辽宁省', delay: 63, lossPercent: 2, value: [123.429096, 41.796767] },
{ name: '吉林省', delay: 63, lossPercent: 2, value: [125.3245, 43.886841] },
{ name: '黑龙江省', delay: 63, lossPercent: 2, value: [126.642464, 45.756967] },
{ name: '上海市', delay: 63, lossPercent: 2, value: [121.487899486, 31.24916171] },
{ name: '江苏省', delay: 63, lossPercent: 2, value: [118.767413, 32.041544] },
{ name: '浙江省', delay: 63, lossPercent: 2, value: [120.153576, 30.287459] },
{ name: '安徽省', delay: 63, lossPercent: 2, value: [117.283042, 31.86119] },
{ name: '福建省', delay: 63, lossPercent: 2, value: [119.306239, 26.075302] },
{ name: '江西省', delay: 63, lossPercent: 2, value: [115.892151, 28.676493] },
{ name: '山东省', delay: 63, lossPercent: 2, value: [117.000923, 36.675807] },
{ name: '河南省', delay: 63, lossPercent: 2, value: [113.665412, 34.757975] },
{ name: '湖北省', delay: 63, lossPercent: 2, value: [114.298572, 30.584355] },
{ name: '湖南省', delay: 63, lossPercent: 2, value: [112.982279, 28.19409] },
{ name: '广东省', delay: 63, lossPercent: 2, value: [113.280637, 23.125178] },
{ name: '广西壮族自治区', delay: 63, lossPercent: 2, value: [108.320004, 22.82402] },
{ name: '海南省', delay: 63, lossPercent: 2, value: [110.33119, 20.031971] },
{ name: '重庆市', delay: 63, lossPercent: 2, value: [106.504962, 29.533155] },
{ name: '四川省', delay: 63, lossPercent: 2, value: [104.065735, 30.659462] },
{ name: '贵州省', delay: 63, lossPercent: 2, value: [106.713478, 26.578343] },
{ name: '云南省', delay: 63, lossPercent: 2, value: [102.712251, 25.040609] },
{ name: '西藏自治区', delay: 63, lossPercent: 2, value: [91.132212, 29.660361] },
{ name: '陕西省', delay: 63, lossPercent: 2, value: [108.948024, 34.263161] },
{ name: '甘肃省', delay: 63, lossPercent: 2, value: [103.823557, 36.058039] },
{ name: '青海省', delay: 63, lossPercent: 2, value: [96.07, 36.62] },
{ name: '宁夏回族自治区', delay: 63, lossPercent: 2, value: [106.278179, 38.46637] },
{ name: '新疆维吾尔自治区', delay: 63, lossPercent: 2, value: [87.617733, 43.792818] },
{ name: '台湾省', delay: 63, lossPercent: 2, value: [121.509062, 25.044332] },
{ name: '香港特别行政区', delay: 63, lossPercent: 2, value: [114.173355, 22.320048] },
{ name: '澳门特别行政区', delay: 63, lossPercent: 2, value: [113.54909, 22.198951] }
]
配置项:
{
type: 'effectScatter',
coordinateSystem: 'geo',
symbolSize: 7,
effectType: 'ripple',
legendHoverLink: false,
showEffectOn: 'render',
rippleEffect: {
period: 4,
scale: 2.5,
brushType: 'stroke'
},
zlevel: 1,
itemStyle: {
color: '#99FBFE',
shadowBlur: 5,
shadowColor: '#fff'
},
data: geoCodeMap
}
4.地图展示组件
/** * @LeftTop.vue * @author: zgr * @createTime: 2023/9/25 */
<template>
<EChart :options="options" ref="chinaMapRef" />
</template>
<script lang="ts" setup>
interface digitalScreenDataType {
name: string
value: number
}
interface contractInfoForFirstArea {
name: string
contractInfoByFirstArea: digitalScreenDataType[]
}
import * as echarts from 'echarts'
import chinaData from '@/assets/map/china.json'
echarts.registerMap('china', chinaData)
defineOptions({ name: 'ContractMap' })
//计时器
const timer = reactive({
//地图动态显示数据
mapIntervalTimer: null
})
const geoCodeMap = [
{ name: '北京市', delay: 63, lossPercent: 2, value: [119.337634104, 26.0911937119] },
{ name: '天津市', delay: 63, lossPercent: 2, value: [117.190182, 39.125596] },
{ name: '河北省', delay: 63, lossPercent: 2, value: [114.502461, 38.045474] },
{ name: '山西省', delay: 63, lossPercent: 2, value: [112.549248, 37.857014] },
{ name: '内蒙古自治区', delay: 63, lossPercent: 2, value: [111.670801, 40.818311] },
{ name: '辽宁省', delay: 63, lossPercent: 2, value: [123.429096, 41.796767] },
{ name: '吉林省', delay: 63, lossPercent: 2, value: [125.3245, 43.886841] },
{ name: '黑龙江省', delay: 63, lossPercent: 2, value: [126.642464, 45.756967] },
{ name: '上海市', delay: 63, lossPercent: 2, value: [121.487899486, 31.24916171] },
{ name: '江苏省', delay: 63, lossPercent: 2, value: [118.767413, 32.041544] },
{ name: '浙江省', delay: 63, lossPercent: 2, value: [120.153576, 30.287459] },
{ name: '安徽省', delay: 63, lossPercent: 2, value: [117.283042, 31.86119] },
{ name: '福建省', delay: 63, lossPercent: 2, value: [119.306239, 26.075302] },
{ name: '江西省', delay: 63, lossPercent: 2, value: [115.892151, 28.676493] },
{ name: '山东省', delay: 63, lossPercent: 2, value: [117.000923, 36.675807] },
{ name: '河南省', delay: 63, lossPercent: 2, value: [113.665412, 34.757975] },
{ name: '湖北省', delay: 63, lossPercent: 2, value: [114.298572, 30.584355] },
{ name: '湖南省', delay: 63, lossPercent: 2, value: [112.982279, 28.19409] },
{ name: '广东省', delay: 63, lossPercent: 2, value: [113.280637, 23.125178] },
{ name: '广西壮族自治区', delay: 63, lossPercent: 2, value: [108.320004, 22.82402] },
{ name: '海南省', delay: 63, lossPercent: 2, value: [110.33119, 20.031971] },
{ name: '重庆市', delay: 63, lossPercent: 2, value: [106.504962, 29.533155] },
{ name: '四川省', delay: 63, lossPercent: 2, value: [104.065735, 30.659462] },
{ name: '贵州省', delay: 63, lossPercent: 2, value: [106.713478, 26.578343] },
{ name: '云南省', delay: 63, lossPercent: 2, value: [102.712251, 25.040609] },
{ name: '西藏自治区', delay: 63, lossPercent: 2, value: [91.132212, 29.660361] },
{ name: '陕西省', delay: 63, lossPercent: 2, value: [108.948024, 34.263161] },
{ name: '甘肃省', delay: 63, lossPercent: 2, value: [103.823557, 36.058039] },
{ name: '青海省', delay: 63, lossPercent: 2, value: [96.07, 36.62] },
{ name: '宁夏回族自治区', delay: 63, lossPercent: 2, value: [106.278179, 38.46637] },
{ name: '新疆维吾尔自治区', delay: 63, lossPercent: 2, value: [87.617733, 43.792818] },
{ name: '台湾省', delay: 63, lossPercent: 2, value: [121.509062, 25.044332] },
{ name: '香港特别行政区', delay: 63, lossPercent: 2, value: [114.173355, 22.320048] },
{ name: '澳门特别行政区', delay: 63, lossPercent: 2, value: [113.54909, 22.198951] }
]
let preSelectMapIndex = 0
const dataList = ref<contractInfoForFirstArea[]>([])
const options = reactive<echarts.EChartsOption>({
showLegendSymbol: false,
tooltip: {
trigger: 'item',
//是否显示提示框组件
show: true,
backgroundColor: 'rgba(0,0,55,0.4)',
textStyle: {
color: 'white',
fontSize: 14,
lineHeight: 20
},
// 如果需要自定义 tooltip样式,需要使用formatter
formatter: function (params) {
let toolTipHtml = ''
let data = dataList.value
for (let i = 0; i < data.length; i++) {
if (params.name === data[i].name) {
toolTipHtml += data[i].name + ':<br>'
for (let j = 0; j < data[i].contractInfoByFirstArea.length; j++) {
toolTipHtml +=
data[i].contractInfoByFirstArea[j].name +
':' +
data[i].contractInfoByFirstArea[j].value +
'<br>'
}
}
}
return toolTipHtml
}
},
visualMap: {
min: 0,
max: 800,
show: false,
seriesIndex: 0,
// 颜色
inRange: {
color: ['rgba(41,166,206, .5)', 'rgba(69,117,245, .9)']
}
},
// 底部背景
geo: {
show: true,
aspectScale: 0.85, //长宽比
zoom: 1.6,
top: '30%',
left: '25%',
map: 'china',
roam: false,
itemStyle: {
areaColor: 'rgba(0,0,0,0)',
shadowColor: 'rgba(138,181,218,0.8)',
borderColor: '#232652',
borderWidth: 2
},
emphasis: {
itemStyle: {
areaColor: '#00aeef',
shadowColor: 'rgba(138,181,218,0.8)'
}
}
},
series: [
{
name: '',
type: 'map',
aspectScale: 0.85, //长宽比
zoom: 1.6,
map: 'china', // 自定义扩展图表类型
top: '30%',
left: '25%',
itemStyle: {
color: 'red',
areaColor: 'rgba(19,54,162, .5)',
borderColor: 'rgba(0,242,252,.3)',
borderWidth: 1,
shadowBlur: 7,
shadowColor: '#00f2fc'
},
emphasis: {
itemStyle: {
areaColor: '#4f7fff',
borderColor: 'rgba(0,242,252,.6)',
borderWidth: 2,
shadowBlur: 10,
shadowColor: '#00f2fc'
}
},
label: {
formatter: (params) => `${params.name}`,
show: true,
position: 'insideRight',
fontSize: 12,
color: '#efefef'
},
data: [] as contractInfoForFirstArea[]
},
{
type: 'effectScatter',
coordinateSystem: 'geo',
symbolSize: 7,
effectType: 'ripple',
legendHoverLink: false,
showEffectOn: 'render',
rippleEffect: {
period: 4,
scale: 2.5,
brushType: 'stroke'
},
zlevel: 1,
itemStyle: {
color: '#99FBFE',
shadowBlur: 5,
shadowColor: '#fff'
},
data: geoCodeMap
}
]
})
const getData = async () => {
let resData: contractInfoForFirstArea[] = [
{
name: '北京市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.9923 },
{ name: '合同总数', value: 51 }
]
},
{
name: '天津市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 170.2683 },
{ name: '合同总数', value: 30790 }
]
},
{
name: '上海市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.2098 },
{ name: '合同总数', value: 5 }
]
},
{
name: '重庆市',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 4.5777 },
{ name: '合同总数', value: 144 }
]
},
{
name: '新疆维吾尔自治区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 2.5839 },
{ name: '合同总数', value: 78 }
]
},
{
name: '西藏自治区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.2476 },
{ name: '合同总数', value: 14 }
]
},
{
name: '宁夏回族自治区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 1.3043 },
{ name: '合同总数', value: 353 }
]
},
{
name: '内蒙古自治区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 4.4069 },
{ name: '合同总数', value: 256 }
]
},
{
name: '广西壮族自治区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.9392 },
{ name: '合同总数', value: 47 }
]
},
{
name: '黑龙江省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 1.5711 },
{ name: '合同总数', value: 53 }
]
},
{
name: '吉林省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 5.3852 },
{ name: '合同总数', value: 157 }
]
},
{
name: '辽宁省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 5.1029 },
{ name: '合同总数', value: 193 }
]
},
{
name: '河北省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 17.9545 },
{ name: '合同总数', value: 1101 }
]
},
{
name: '山东省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 9.7 },
{ name: '合同总数', value: 568 }
]
},
{
name: '江苏省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 6.6828 },
{ name: '合同总数', value: 239 }
]
},
{
name: '安徽省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 7.2328 },
{ name: '合同总数', value: 260 }
]
},
{
name: '浙江省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 7.7085 },
{ name: '合同总数', value: 309 }
]
},
{
name: '福建省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 3.15 },
{ name: '合同总数', value: 241 }
]
},
{
name: '广东省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 28.461 },
{ name: '合同总数', value: 1102 }
]
},
{
name: '海南省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 8.5549 },
{ name: '合同总数', value: 423 }
]
},
{
name: '云南省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 5.5561 },
{ name: '合同总数', value: 422 }
]
},
{
name: '贵州省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 2.8905 },
{ name: '合同总数', value: 82 }
]
},
{
name: '四川省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 10.9661 },
{ name: '合同总数', value: 409 }
]
},
{
name: '湖南省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 3.0104 },
{ name: '合同总数', value: 144 }
]
},
{
name: '湖北省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 3.7586 },
{ name: '合同总数', value: 157 }
]
},
{
name: '河南省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 8.2312 },
{ name: '合同总数', value: 230 }
]
},
{
name: '山西省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 6.1501 },
{ name: '合同总数', value: 322 }
]
},
{
name: '陕西省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 3.265 },
{ name: '合同总数', value: 133 }
]
},
{
name: '甘肃省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 1.4853 },
{ name: '合同总数', value: 58 }
]
},
{
name: '青海省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 1.2578 },
{ name: '合同总数', value: 30 }
]
},
{
name: '江西省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 2.8155 },
{ name: '合同总数', value: 67 }
]
},
{
name: '台湾省',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0.0032 },
{ name: '合同总数', value: 2 }
]
},
{
name: '香港特别行政区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0 },
{ name: '合同总数', value: 0 }
]
},
{
name: '澳门特别行政区',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0 },
{ name: '合同总数', value: 0 }
]
},
{
name: '南海诸岛',
contractInfoByFirstArea: [
{ name: '合同总额(亿)', value: 0 },
{ name: '合同总数', value: 0 }
]
}
]
dataList.value = resData
options.series[0].data = resData
}
// 重新随机选中地图区域
const reSelectMapRandomArea = () => {
const length = 34
nextTick(() => {
try {
const map = chinaMapRef.value.eChart
let index = Math.floor(Math.random() * length)
while (index === preSelectMapIndex || index >= length) {
index = Math.floor(Math.random() * length)
}
map.dispatchAction({
type: 'unselect',
seriesIndex: 0,
dataIndex: preSelectMapIndex
})
map.dispatchAction({
type: 'showTip',
seriesIndex: 0,
dataIndex: index
})
map.dispatchAction({
type: 'select',
seriesIndex: 0,
dataIndex: index
})
preSelectMapIndex = index
} catch (error) {
console.log('2345' + error)
}
})
}
const chinaMapRef = ref()
const handleMapRandomSelect = () => {
nextTick(() => {
try {
const map = chinaMapRef.value.eChart
setTimeout(() => {
reSelectMapRandomArea()
}, 0)
// 移入区域,清除定时器、取消之前选中并选中当前
map.on('mouseover', function (params) {
clearInterval(timer.mapIntervalTimer)
map.dispatchAction({
type: 'unselect',
seriesIndex: 0,
dataIndex: preSelectMapIndex
})
map.dispatchAction({
type: 'select',
seriesIndex: 0,
dataIndex: params.dataIndex
})
preSelectMapIndex = params.dataIndex
})
// 移出区域重新随机选中地图区域,并开启定时器
map.on('globalout', function () {
reSelectMapRandomArea()
startInterval()
})
startInterval()
} catch (error) {
console.log('134' + error)
}
})
}
// 开启定时器
const startInterval = () => {
// 应通过接口获取配置时间,暂时写死5s
const time = 2000
if (timer.mapIntervalTimer !== null) {
clearInterval(timer.mapIntervalTimer)
}
timer.mapIntervalTimer = setInterval(() => {
reSelectMapRandomArea()
}, time)
}
//去除定时器
const clearData = () => {
if (timer.mapIntervalTimer) {
clearInterval(timer.mapIntervalTimer)
timer.mapIntervalTimer = null
}
}
onMounted(() => {
getData()
handleMapRandomSelect()
})
onUnmounted(() => {
clearData()
})
</script>
<style scoped></style>
几个需要说明的地方:
1.option配置中的显示数据。本例中,数据直接写死赋值,在实际使用中,我们可能是从后端异步拉取数据然后再显示,这就会有一个问题,组件加载完毕,数据却还没有获取完毕。本人在实际项目的办法是初始化一个定时器,1秒钟获取一次数据,如果加载到数据就销毁定时器,继续赋值给option中的数据。
const getData = async () => {
let resData: contractInfoForFirstArea[] = digitalScreenStore.getContractInfoForFirstArea
if (resData.length > 0 && timer.initDataTimer !== null) {
// 清除多次执行定时器
clearInterval(Number(timer.initDataTimer))
timer.initDataTimer = null
}
dataList.value = resData
options.series[0].data = resData
}
const getInitDataTimer = () => {
timer.initDataTimer = setInterval(getData, 1000)
}
onMounted(() => {
getInitDataTimer()
getData()
})
2.tooltip中的formatter函数。如果简单的字符串满足不了显示数据的要求,可以自定义函数,返回一段自定义HTML,显示对应数据。
3.自动随机选择省份区域,并显示tooltip数据。主要为三个函数,handleMapRandomSelect,reSelectMapRandomArea,startInterval,最初引用链接为koi-screen Vue2版,ECharts5的配置也有一些变化,所以改进为现在的Vue3+ECharts5版。
5.总结
本篇文章简单介绍了ECharts组件的封装,以及地图组件的封装,大概描述了实际项目中遇到的问题以及自己的一些解决办法,行文比较简单概括,所给代码并不能达到文章开始图片效果,对于一些问题可能还不是能很好的理解,欢迎批评指正,一起探讨交流进步。