|
|
|
|
<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: item.data.length > 100 ? '15%' : "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>
|