TreeChart.vue
<template>
<div ref="chartRef" class='big-chart'></div>
</template>
<script setup lang='ts'>
import { onMounted, PropType, shallowRef, watch } from 'vue'
import * as echarts from 'echarts'
import { ECharts, EChartsCoreOption } from 'echarts'
const props = defineProps({
option: {
type: Object as PropType<EChartsCoreOption>,
required: true,
default: () => ({})
},
loading: Boolean
})
const chartRef = shallowRef<HTMLElement | null>(null)
const chart = shallowRef<ECharts | null>(null)
function init() {
if (props.option) {
chart.value = echarts.init(chartRef.value!)
setOption(props.option)
}
}
function setOption(option, notMerge?: boolean, lazyUpdate?: boolean) {
chart?.value?.setOption(option, notMerge, lazyUpdate)
}
function resize() {
chart.value!.resize()
}
watch(() => props.option, () => {
console.log(props.option,'props.option')
setOption(props.option)
})
// show loading
watch(() => props.loading, (val) => {
if (!chart.value) return
if (val) {
chart.value!.showLoading()
} else {
chart.value!.hideLoading()
}
})
onMounted(() => {
setTimeout(() => {
init()
}, 10);
})
defineExpose({
chart,
setOption,
resize
})
</script>
<style lang='scss' scoped>
.big-chart {
width: 500px;
height: 500px;
}
</style>
在父组件中使用:
<template>
<div>
<!-- 其他代码 -->
<MyTreeCharts :option="option"></MyTreeCharts>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import MyTreeCharts from './components/TreeCharts.vue';
const topographyData = ref([
{
name: '总配电室',
children: [
{
name: 'A区配电柜',
children: [
{
name: 'A1线路',
value: 100,
children: [
{
name: 'A1-1支线',
value: 45
},
{
name: 'A1-2支线',
value: 55
}
]
},
{
name: 'A2线路',
value: 80,
children: [
{
name: 'A2-1支线',
value: 40
},
{
name: 'A2-2支线',
value: 40
}
]
},
{
name: 'A3线路',
value: 90
}
]
},
{
name: 'B区配电柜',
children: [
{
name: 'B1线路',
value: 70,
children: [
{
name: 'B1-1支线',
value: 35
},
{
name: 'B1-2支线',
value: 35
}
]
},
{
name: 'B2线路',
value: 85,
children: [
{
name: 'B2-1支线',
value: 42
},
{
name: 'B2-2支线',
value: 43
}
]
},
{
name: 'B3线路',
value: 95
}
]
},
{
name: 'C区配电柜',
children: [
{
name: 'C1线路',
value: 95,
children: [
{
name: 'C1-1支线',
value: 30
},
{
name: 'C1-2支线',
value: 35
},
{
name: 'C1-3支线',
value: 30
}
]
},
{
name: 'C2线路',
value: 75,
children: [
{
name: 'C2-1支线',
value: 25
},
{
name: 'C2-2支线',
value: 25
},
{
name: 'C2-3支线',
value: 25
}
]
}
]
},
{
name: 'D区配电柜',
children: [
{
name: 'D1线路',
value: 88,
children: [
{
name: 'D1-1支线',
value: 44
},
{
name: 'D1-2支线',
value: 44
}
]
},
{
name: 'D2线路',
value: 92,
children: [
{
name: 'D2-1支线',
value: 46
},
{
name: 'D2-2支线',
value: 46
}
]
},
{
name: 'D3线路',
value: 78
},
{
name: 'D4线路',
value: 85
}
]
},
{
name: 'E区配电柜',
children: [
{
name: 'E1线路',
value: 82,
children: [
{
name: 'E1-1支线',
value: 41
},
{
name: 'E1-2支线',
value: 41
}
]
},
{
name: 'E2线路',
value: 76,
children: [
{
name: 'E2-1支线',
value: 38
},
{
name: 'E2-2支线',
value: 38
}
]
},
{
name: 'E3线路',
value: 94,
children: [
{
name: 'E3-1支线',
value: 47
},
{
name: 'E3-2支线',
value: 47
}
]
}
]
}
]
}
]);
const option = ref({
tooltip: {
trigger: 'item',
triggerOn: 'mousemove'
},
series: [
{
type: 'tree',
data: topographyData.value,
top: '3%',
left: '27%',
bottom: '3%',
right: '50%',
symbolSize: 8,
itemStyle: {
normal: {
color: 'rgb(231, 56, 40)',
borderColor: 'rgb(231, 56, 40)'
},
emphasis: {
color: '#ffffff',
borderColor: 'rgb(231, 56, 40)'
}
},
label: {
position: 'left',
verticalAlign: 'middle',
align: 'right',
fontSize: 12
},
lineStyle: {
color: 'rgb(231, 56, 40)',
width: 2 // 线条宽度
},
leaves: {
label: {
position: 'middle',
verticalAlign: 'top',
align: 'left'
}
},
emphasis: {
focus: 'descendant'
},
zoom: 1.0, // 缩放系数
expandAndCollapse: true,
animationDuration: 550,
animationDurationUpdate: 750
}
]
})
</script>
最终的效果图:
image.png