You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
9.6 KiB
310 lines
9.6 KiB
<template> |
|
<!-- <div > --> |
|
<div ref="ChartsTimeBarRef" style="height:100%;width: 100%;" class="chart-container"></div> |
|
<!-- </div> --> |
|
</template> |
|
<script setup> |
|
import * as echarts from "echarts"; |
|
import dayjs from 'dayjs' |
|
import { onMounted, nextTick, ref, onUnmounted } from "vue"; |
|
const props = defineProps({ |
|
legendData: { |
|
type: Array, |
|
default: () => [] |
|
}, |
|
xAxisData: { |
|
type: Array, |
|
default: () => [] |
|
}, |
|
seriesData: { |
|
type: Array, |
|
default: () => [] |
|
}, |
|
textTitle: { |
|
type: String, |
|
default: '' |
|
}, |
|
unit: { |
|
type: String, |
|
default: 'mm' |
|
}, |
|
echartType: { |
|
type: String, |
|
default: 'bar' |
|
}, |
|
grid: { |
|
type: Object, |
|
default: () => { |
|
return { |
|
left: "5%", |
|
right: "5%", |
|
bottom: "16%", |
|
top: "16%", |
|
containLabel: true, |
|
} |
|
} |
|
} |
|
|
|
}) |
|
const ChartsTimeBarRef = ref(null); |
|
let echartsBar = null; |
|
let resizeObserver = null; |
|
// 监听props变化,确保数据更新后重新初始化图表 |
|
watch([() => props.legendData, () => props.xAxisData, () => props.seriesData], () => { |
|
if (echartsBar) { |
|
|
|
updateChart(); |
|
} |
|
}, { deep: true }); |
|
onMounted(() => { |
|
|
|
|
|
initEcharts(); |
|
window.addEventListener('resize', handleResize); |
|
// 监听容器本身尺寸变化 |
|
if (ChartsTimeBarRef.value) { |
|
resizeObserver = new ResizeObserver(handleResize); |
|
resizeObserver.observe(ChartsTimeBarRef.value); |
|
} |
|
}); |
|
|
|
onUnmounted(() => { |
|
window.removeEventListener('resize', handleResize); |
|
if (resizeObserver && ChartsTimeBarRef.value) { |
|
resizeObserver.unobserve(ChartsTimeBarRef.value); |
|
} |
|
if (echartsBar) { |
|
echartsBar.dispose(); |
|
} |
|
}); |
|
const echartsLoading = ref(true); |
|
const initEcharts = () => { |
|
nextTick(() => { |
|
if (ChartsTimeBarRef.value) { |
|
echartsBar = echarts.init(ChartsTimeBarRef.value, "macarons"); |
|
let option = getChartOption(); |
|
echartsBar.setOption(option); |
|
|
|
// 确保图表尺寸适应容器 |
|
const resizeChart = () => { |
|
if (echartsBar && ChartsTimeBarRef.value) { |
|
echartsBar.resize({ |
|
width: ChartsTimeBarRef.value.clientWidth, |
|
height: ChartsTimeBarRef.value.clientHeight |
|
}); |
|
} |
|
}; |
|
|
|
// 初始化时调整一次大小 |
|
resizeChart(); |
|
} |
|
}); |
|
}; |
|
const updateChart = () => { |
|
nextTick(() => { |
|
if (echartsBar) { |
|
let option = getChartOption(); |
|
echartsBar.setOption(option, true); // 使用notMerge:true来完全替换旧选项 |
|
resizeChart(); |
|
} |
|
}); |
|
}; |
|
|
|
const resizeChart = () => { |
|
if (echartsBar && ChartsTimeBarRef.value) { |
|
echartsBar.resize({ |
|
width: ChartsTimeBarRef.value.clientWidth, |
|
height: ChartsTimeBarRef.value.clientHeight |
|
}); |
|
} |
|
}; |
|
const handleResize = () => { |
|
if (echartsBar && ChartsTimeBarRef.value) { |
|
// 添加防抖机制,避免频繁触发 |
|
clearTimeout(window.resizeTimer); |
|
window.resizeTimer = setTimeout(() => { |
|
echartsBar.resize({ |
|
width: ChartsTimeBarRef.value.clientWidth, |
|
height: ChartsTimeBarRef.value.clientHeight, |
|
animation: { |
|
duration: 300 |
|
} |
|
}); |
|
}, 100); |
|
} |
|
}; |
|
|
|
|
|
const getChartOption = () => { |
|
console.log(props.legendData, props.xAxisData, props.seriesData) |
|
const series = props.seriesData.map((item, index) => { |
|
const colors = [ |
|
["#248ff7", "#6f5be8"], |
|
["#248ff7", "#6f5be8"], |
|
|
|
]; |
|
const color = colors[index % colors.length]; |
|
|
|
return { |
|
name: props.legendData[index], |
|
type: item.type, |
|
barWidth: "20", |
|
yAxisIndex: index, |
|
showSymbol: false, |
|
itemStyle: { |
|
normal: { |
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
|
{ offset: 0, color: color[0] }, |
|
{ offset: 1, color: color[1] } |
|
]), |
|
barBorderRadius: 12, |
|
}, |
|
}, |
|
data: item.data?.map(val => val[1]), |
|
}; |
|
}); |
|
let option = { |
|
// backgroundColor: "#323a5e", |
|
title: { |
|
text: props.textTitle, |
|
textStyle: { |
|
align: "center", |
|
color: "#000", |
|
fontSize: 20, |
|
}, |
|
top: "3%", |
|
left: "50%", |
|
}, |
|
tooltip: { |
|
trigger: "axis", |
|
axisPointer: { |
|
// 坐标轴指示器,坐标轴触发有效 |
|
type: "shadow", // 默认为直线,可选为:'line' | 'shadow' |
|
}, |
|
}, |
|
grid: props.grid, |
|
legend: { |
|
data: props.legendData, |
|
right: 10, |
|
top: 12, |
|
textStyle: { |
|
color: "#000", |
|
}, |
|
itemWidth: 12, |
|
itemHeight: 10, |
|
// itemGap: 35 |
|
}, |
|
xAxis: { |
|
type: "category", |
|
data: props.xAxisData, |
|
axisLine: { |
|
lineStyle: { |
|
color: "#ccc", |
|
}, |
|
}, |
|
|
|
axisLabel: { |
|
textStyle: { |
|
fontFamily: "Microsoft YaHei", |
|
}, |
|
showMinLabel: true, // 强制显示最小值标签 |
|
showMaxLabel: true, // 强制显示最大值标签 |
|
formatter: function (value) { |
|
let date = dayjs(value) |
|
let yearMonthDay = date.format('YYYY-MM-DD') |
|
let hourMinute = date.format('HH:mm') |
|
let result = `{a|${hourMinute}}\n{b|${yearMonthDay}}`; |
|
if (props.timeType == 'day') { |
|
result = `{b|${yearMonthDay}}`; |
|
} |
|
return result |
|
}, |
|
|
|
rich: { |
|
a: { |
|
fontSize: 12, |
|
color: '#000', |
|
padding: [0, 0, 5, 0] // 上右下左的内边距,这里给上方小时分钟添加一点底部间距 |
|
}, |
|
b: { |
|
fontSize: 12, |
|
color: '#000' |
|
} |
|
} |
|
}, |
|
}, |
|
|
|
yAxis: [ |
|
|
|
{ // 水位 - 右侧 |
|
type: 'value', |
|
name: '水位 (m)', |
|
axisLabel: { color: '#EE6666' }, |
|
nameTextStyle: { color: '#EE6666', fontWeight: 'bold' }, |
|
splitLine: { |
|
show: true, |
|
lineStyle: { |
|
color: "#ccc", |
|
}, |
|
}, |
|
}, |
|
{ // 雨量 - 左侧 |
|
type: 'value', |
|
name: '雨量 (mm)', |
|
inverse: true, |
|
nameLocation: 'start', |
|
position: 'right', |
|
axisLabel: { color: '#1075FD' }, |
|
nameTextStyle: { color: '#1075FD', fontWeight: 'bold' }, |
|
splitLine: { |
|
show: true, |
|
lineStyle: { |
|
color: "#ccc", |
|
}, |
|
}, |
|
|
|
} |
|
], |
|
|
|
series: series, |
|
}; |
|
|
|
return option |
|
// var app = { |
|
// currentIndex: -1, |
|
// }; |
|
// setInterval(function () { |
|
// var dataLen = option.series[0].data.length; |
|
|
|
// // 取消之前高亮的图形 |
|
// myChart.dispatchAction({ |
|
// type: "downplay", |
|
// seriesIndex: 0, |
|
// dataIndex: app.currentIndex, |
|
// }); |
|
// app.currentIndex = (app.currentIndex + 1) % dataLen; |
|
// //console.log(app.currentIndex); |
|
// // 高亮当前图形 |
|
// myChart.dispatchAction({ |
|
// type: "highlight", |
|
// seriesIndex: 0, |
|
// dataIndex: app.currentIndex, |
|
// }); |
|
// // 显示 tooltip |
|
// myChart.dispatchAction({ |
|
// type: "showTip", |
|
// seriesIndex: 0, |
|
// dataIndex: app.currentIndex, |
|
// }); |
|
// }, 1000); |
|
|
|
} |
|
</script> |
|
<style scoped> |
|
.chart-container { |
|
width: 100%; |
|
height: 100%; |
|
min-height: 300px; |
|
position: relative; |
|
} |
|
</style> |