3 changed files with 29 additions and 370 deletions
@ -1,369 +0,0 @@
@@ -1,369 +0,0 @@
|
||||
<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' |
||||
}, |
||||
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(() => { |
||||
console.log(props.xAxisData, '======xAxisData') |
||||
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 = () => { |
||||
let allData = []; |
||||
props.seriesData.forEach(series => { |
||||
if (series.data) { |
||||
series.data.forEach(item => { |
||||
// 根据数据结构获取数值,可能是 [time, value] 或 {tm: time, value: value} 格式 |
||||
const value = Array.isArray(item) ? item[1] : (item.value !== undefined ? item.value : item); |
||||
if (value !== undefined && value !== null && !isNaN(value)) { |
||||
allData.push(Number(value)); |
||||
} |
||||
}); |
||||
} |
||||
}); |
||||
|
||||
// 计算y轴范围 |
||||
let yAxisMin = 0; |
||||
let yAxisMax = 100; |
||||
|
||||
if (allData.length > 0) { |
||||
const minVal = Math.min(...allData); |
||||
const maxVal = Math.max(...allData); |
||||
|
||||
// 添加一些边距,使图表更美观 |
||||
const range = maxVal - minVal; |
||||
const margin = range > 0 ? range * 0.1 : 1; |
||||
|
||||
yAxisMin = Math.floor((minVal - margin) * 100) / 100; // 保留两位小数 |
||||
yAxisMax = Math.ceil((maxVal + margin) * 100) / 100; // 保留两位小数 |
||||
|
||||
// 如果数据值都很小,确保最小值不为负数(可根据实际需求调整) |
||||
if (minVal >= 0 && yAxisMin < 0) { |
||||
yAxisMin = 0; |
||||
} |
||||
} |
||||
const series = props.seriesData.map((item, index) => { |
||||
const colors = [ |
||||
["#fccb05", "#f5804d"], |
||||
["#8bd46e", "#09bcb7"], |
||||
["#248ff7", "#6851f1"] |
||||
]; |
||||
const color = colors[index % colors.length]; |
||||
|
||||
return { |
||||
name: props.legendData[index], |
||||
type: "line", |
||||
barWidth: item.data.length > 100 ? '15%' : "20", |
||||
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", |
||||
min: yAxisMin, |
||||
max: yAxisMax, |
||||
|
||||
name: 'mm', |
||||
nameLocation: 'middle', |
||||
|
||||
nameTextStyle: {//y轴上方单位的颜色 |
||||
color: '#464b50' |
||||
}, |
||||
nameGap: 50, |
||||
axisLine: { |
||||
show: true, |
||||
lineStyle: { |
||||
color: "#ccc", |
||||
}, |
||||
}, |
||||
|
||||
splitLine: { |
||||
show: true, |
||||
lineStyle: { |
||||
color: "#ccc", |
||||
}, |
||||
}, |
||||
axisLabel: { |
||||
textStyle: { |
||||
color: "#000000", |
||||
}, |
||||
// 添加formatter属性,保留两位小数 |
||||
formatter: function (value) { |
||||
return value.toFixed(2); |
||||
} |
||||
}, |
||||
}, |
||||
dataZoom: [ |
||||
{ |
||||
show: true, |
||||
// height: 15, |
||||
xAxisIndex: [0], |
||||
bottom: "8%", |
||||
start: 0, |
||||
end: 100, |
||||
handleIcon: |
||||
"path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z", |
||||
handleSize: "110%", |
||||
handleStyle: { |
||||
color: "#d3dee5", |
||||
}, |
||||
textStyle: { |
||||
color: "#000", |
||||
}, |
||||
borderColor: "#90979c", |
||||
}, |
||||
{ |
||||
type: "inside", |
||||
show: true, |
||||
// height: 15, |
||||
start: 1, |
||||
end: 35, |
||||
}, |
||||
// { |
||||
// type: 'inside' |
||||
// }, |
||||
// { |
||||
// type: 'slider' |
||||
// } |
||||
], |
||||
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> |
||||
Loading…
Reference in new issue