- 需求背景
- 解决思路
- 解决效果
- index.vue
需求背景
需要做一个水库高程模拟的图表,x轴是水平距离,y轴是高程,需要模拟改水库的形状
echarts 图表集链接
解决思路
配合ui切图,模拟水库形状
解决效果
index.vue
<!--/**
* @author: liuk
* @date: 2024-10-24
* @describe: 水情图表
*/-->
<template>
<div ref="chatDom" class="waterConditionChart"></div>
</template>
<script lang="ts" setup>
import {ref, onMounted, watch, nextTick} from "vue"
import * as echarts from 'echarts'
import "echarts-liquidfill"
import {formatToFixed, getEquiUnit} from "@/utils/dictionary";
// Props
const props = defineProps(['data'])
let myChart = null // Vue3 使用 proxy 对象代理,而 echarts 则使用了大量的全等(===), 对比失败从而导致了bug。
const chatDom = ref(null)
watch(() => props.data, (data) => {
nextTick(() => {
if (!myChart) return
drawChart()
const option = myChart.getOption()
myChart.clear()
myChart.setOption(renderFn(option, data))
})
}, {immediate: true})
onMounted(() => {
drawChart()
window.addEventListener('resize', () => {
drawChart()
const option = myChart.getOption()
myChart.clear()
myChart.setOption(renderFn(option, props.data,))
});
})
const renderFn = (option, data) => {
// option.series[0].data[0].value = data.num || 0
// option.series[0].max = data.total || 0
return option
}
const drawChart = () => {
let chartDom = chatDom.value
if (chartDom == null) {
return
}
echarts.dispose(chartDom)
myChart = echarts.init(chartDom)
const option = {
title: [{
top: 125,
left: 50,
text: "当前水位:33.15m",
textStyle: {
color: "#fff",
fontSize: 12,
fontWeight: "normal"
},
}],
tooltip: {
trigger: 'axis',
padding: [5, 10, 5, 10],
backgroundColor: 'rgba(0,0,0,.6)',
borderColor: 'transparent',
formatter: (param) => `
<div class="waterConditionChart-popup">
${
param.filter(item=>item.seriesName==="当前水位").map(item => `
<p class="item">
<i class="icon" style="background-color:${item.color || 'red'}"></i>
<span class="name">${item.seriesName}</span>
<span class="value"><b>${formatToFixed(item.data)}</b>${item.data !== '--' ? getEquiUnit(item.seriesName) : ''}</span>
</p>`).join("")
}
</div>
`
},
grid: {
top: '35',
left: '0',
right: '10',
bottom: '0',
containLabel: true,
},
xAxis: [{
type: 'category',
boundaryGap: false,
nameGap: 5,
axisLine: {
show: true,
lineStyle: {
color: '#999'
},
},
axisLabel: {
color: '#9eaaba',
},
axisTick: {
show: false,
},
data: ['0', '50', '100', '150', '200', '250', '300'],
}],
yAxis: [{
name: '高程(m)',
nameTextStyle: {
color: '#9eaaba',
},
offset: 0,
min: 20,
max: 60,
type: 'value',
interval: 5,
axisLabel: {
show: true,
color: "#9eaaba",
},
axisLine: {show: false},
splitLine: {
show: true,
lineStyle: {
width: 1,
color: "rgba(49,105,129,0.4)",
type: 'dashed'
}
},
}],
series: [
{
name:"当前水位",
type: 'line',
smooth: true, //是否平滑曲线显示
symbolSize: 0,
lineStyle: {
width: 1
},
areaStyle: {
color: "rgba(0, 145, 255,0.5)"
},
data: [33, 33, 33, 32, 26, 25, 24],
z: 1
},
{
type: 'line',
symbolSize: 0,
areaStyle: {
color: "rgb(194,137,44)"
},
lineStyle: {
width: 0
},
data: [25, 25, 25, 25, 25, 25, 25],
z: 2
},
{
type: 'line',
symbolSize: 0,
lineStyle: {
width: 2,
type: "dashed",
color: "rgba(114, 255, 198, 1)"
},
data: [50, 50, 50, 50, 50, 50, 50],
z: 2
}
]
}
option && myChart.setOption(option)
}
</script>
<style lang="scss" scoped>
.waterConditionChart {
width: 100%;
height: 100%;
}
</style>
<style lang="scss">
.waterConditionChart-popup {
overflow: hidden;
font-size: 12px;
color: #fff;
.top {
//margin-bottom: 16px;
font-weight: bold;
}
.item {
display: flex;
align-items: center;
margin: 5px 0;
&:last-child {
margin-bottom: 0;
}
.icon {
display: inline-block;
width: 12px;
height: 12px;
margin-right: 10px;
border-radius: 50%;
background: rgba(0, 166, 255, 1);
}
.name {
width: 50px;
margin-right: 10px;
}
.value {
flex: 1;
text-align: right;
}
}
}
</style>