最近遇到了需要将web端图表迁移到h5端,遇到了echarts的交互问题
想要实现的效果
最终实现效果
PieChart组件
<template>
<div class="my-chart" ref="chartRef"></div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
type IProps = {
data: any
}
const props = defineProps<IProps>()
let myChart: ECharts
const chartRef = ref<HTMLDivElement>()
watch(
() => props.data,
() => {
drawChart()
},
)
const getOptions = () => {
const { color, data } = props.data.reduce(
(result, items) => {
const { color, value, label: name, endColor } = items
result.color.push(color)
result.data.push({ value, name, endColor, color })
return result
},
{ color: [], data: [] },
)
const options: EChartsOption = {
title: {
text: '',
left: 'center',
top: 'center',
itemGap: 5, // 设置标题和副标题的间距
},
color: color,
series: [
{
type: 'pie',
radius: ['65%', '90%'],
data: data,
labelLine: {
show: false,
},
label: {
show: false,
position: 'center',
},
itemStyle: {
borderRadius: 3,
borderColor: '#fff',
borderWidth: 1,
},
emptyCircleStyle: {
borderCap: 'round',
},
},
],
}
return options
}
const drawChart = () => {
if (myChart) myChart.dispose()
myChart = echarts.init(chartRef.value)
if (props.data.length <= 0) {
myChart.showLoading({
text: '-暂无数据-',
showSpinner: false, // 隐藏加载中的转圈动图
textColor: '#9d9d9d',
maskColor: 'rgba(255, 255, 255, 0)',
fontSize: '14px',
fontWeight: '400',
})
} else {
myChart.hideLoading()
}
myChart.setOption(getOptions())
}
defineExpose({
highlightChart: (text: string, percent: string | number, index: number) => {
myChart.dispatchAction({
type: 'downplay',
seriesIndex: null, // 如果只想取消特定系列的高亮,可设置系列索引
dataIndex: null, // 如果只想取消特定数据项的高亮,可设置数据项索引
})
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 0,
dataIndex: index,
})
let option = myChart.getOption()
option.title = {
text: `${text}`,
subtext: `${percent}%`,
rich: {
// 定义富文本样式
mainTitle: {
color: 'red',
fontWeight: 'bold',
},
subTitle: {
color: 'blue',
fontStyle: 'italic',
},
},
}
myChart.setOption(option)
},
})
</script>
<style lang="scss" scoped>
.my-chart {
width: 100%;
height: 400px;
}
</style>
页面调用
<div class="chart-item-chart">
<PieChart :data="nodeHealthList" ref="nodeHealthChartRef" />
<div class="chart-item-chart_legend">
<div
class="legend-item"
:class="{ 'legend-item-active': item.active }"
v-for="(item, index) in nodeHealthList"
:key="index"
@click="highlightNodeHealth(item, index)"
>
<div class="legend-item-wrapper">
<div class="icon" :style="{ background: item.color }"></div>
<div class="label">{{ item.label }}</div>
<div class="value">{{ item.value }}</div>
</div>
</div>
</div>
</div>
主要实现方法 highlightNodeHealth
/**节点健康诊断 PieChart实例对象*/
const nodeHealthChartRef = ref<InstanceType<typeof import('./components/pieChart/index.vue')['default']>>()
type INodeHealthList = (typeof NodeHealthList)[number] & { active?: boolean }
/**节点健康选择的节点或企业数据 */
const nodeHealthList = ref<INodeHealthList[]>()
/**高亮节点健康诊断 */
const highlightNodeHealth = (item: INodeHealthList, index: number) => {
nodeHealthList.value?.forEach((i) => (i.active = false))
item.active = true
// 百分比
let percent: string | number
if (item.value == 0) {
percent = 0
} else {
const total = (nodeHealthList.value?.reduce((total, item) => total + item.value, 0) as number) || 0
percent = ((item.value / total) * 100).toFixed(2)
}
nodeHealthChartRef.value?.highlightChart(item.label, percent, index)
}
echarts的高亮实现方法
defineExpose({
highlightChart: (text: string, percent: string | number, index: number) => {
myChart.dispatchAction({
type: 'downplay',
seriesIndex: null, // 如果只想取消特定系列的高亮,可设置系列索引
dataIndex: null, // 如果只想取消特定数据项的高亮,可设置数据项索引
})
myChart.dispatchAction({
type: 'highlight',
seriesIndex: 0,
dataIndex: index,
})
let option = myChart.getOption()
option.title = {
text: `${text}`,
subtext: `${percent}%`,
rich: {
// 定义富文本样式
mainTitle: {
color: 'red',
fontWeight: 'bold',
},
subTitle: {
color: 'blue',
fontStyle: 'italic',
},
},
}
myChart.setOption(option)
},
})