vue3+ts+echarts多Y轴图表
HTML
<!-- 温湿度传感器 --><el-row v-if="deviceTypeId === '2'"><el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24"><div class="chart-container"><div class="filter-container"><!-- <el-select v-model="WenduTimeType" placeholder="请选择时间维度" style="width: 200px;margin-right: 20px;"@change="handleWenduTimeTypeChange"><el-option label="小时" value="hour" /><el-option label="日" value="day" /><el-option label="月" value="month" /><el-option label="年" value="year" /></el-select> --><el-radio-group v-model="WenduTimeType" size="small" @change="generateWenduData"><el-radio-button label="day">日</el-radio-button><el-radio-button label="month">月</el-radio-button><el-radio-button label="year">年</el-radio-button></el-radio-group></div><div id="wenduRef" ref="wendurRef" style=" width: 100%;height: 400px;" class="chart wendu-chart"></div></div></el-col></el-row>
初始化
const wenduChart = ref<any>(null);
const wenduRef = ref<HTMLElement | null>(null)
const WenduTimeType = ref<'day' | 'month' | 'year' | 'hour'>('day')
const WenduSelectedHour = ref<Date>(new Date())
const WenduSelectedDay = ref<Date>(new Date())
const WenduSelectedMonth = ref<Date>(new Date())
const WenduSelectedYear = ref<Date>(new Date())
const WenduXAxisDatatem = ref<string[]>([])
const WenduDatatem = ref<number[]>([])
const WenduXAxisDatahum = ref<string[]>([])
const WenduDatahum = ref<number[]>([])
const WenduXAxisDataill = ref<string[]>([])
const WenduDataill = ref<number[]>([])
函数
// 新增温湿度图数据生成函数
function generateWenduData() {let timeAmount = '1';let timeUnit = 'd';if (WenduTimeType.value === 'day') timeUnit = 'd';else if (WenduTimeType.value === 'month') timeUnit = 'mo';else if (WenduTimeType.value === 'year') timeUnit = 'y';else if (WenduTimeType.value === 'hour') timeUnit = 'h';DashAPI.getsensor({// deviceCode: props.deviceCode,deviceCode: deviceCodeCS.value,timeAmount,timeUnit}).then(res => {const data = Array.isArray(res) ? res : [];const tem = data.find((item: any) => item.name === "temperature");const hum = data.find((item: any) => item.name === "humidity");const ill = data.find((item: any) => item.name === "illuminance");WenduXAxisDatatem.value = tem?.time || [];WenduDatatem.value = tem?.value || [];WenduXAxisDatahum.value = hum?.time || [];WenduDatahum.value = hum?.value || [];WenduXAxisDataill.value = ill?.time || [];WenduDataill.value = ill?.value || [];console.log("getsensor", data);updateWenduChart();});
}
// const botlineType = ref<'day' | 'month' | 'year'>('day');
// 新增温湿度图更新方法
function updateWenduChart(retry = 0) {function tryWendu() {const chartDom = document.querySelector('.wendu-chart') as HTMLElement;if (!chartDom || chartDom.offsetWidth === 0 || chartDom.offsetHeight === 0) {requestAnimationFrame(tryWendu);return;}// 1. ECharts实例和DOM同步if (wenduChart.value &&typeof (wenduChart.value as any).getDom === 'function' &&(wenduChart.value as any).getDom() !== chartDom) {wenduChart.value.dispose();wenduChart.value = null;}if (!wenduChart.value) {wenduChart.value = echarts.init(chartDom);}const option = {color: ['#5470C6', '#91CC75', '#EE6666'],tooltip: { trigger: 'axis', axisPointer: { type: 'cross' } },grid: {right: '20%'},xAxis: [{type: 'category',axisTick: { alignWithLabel: true, color: getTextColor() },data: WenduXAxisDatatem.value, // 以温度时间为主axisLine: { lineStyle: { color: getTextColor() } }}],yAxis: [{ type: 'value', name: '温度°C', position: 'left', alignTicks: true, axisLine: { show: true, lineStyle: { color: '#5470C6' } }, axisLabel: { formatter: '{value}' } },{ type: 'value', name: '湿度%', position: 'right', alignTicks: true, axisLine: { show: true, lineStyle: { color: '#91CC75' } }, axisLabel: { formatter: '{value} ' } },{ type: 'value', name: '光照lux', position: 'right', alignTicks: true, offset: 80, axisLine: { show: true, lineStyle: { color: '#EE6666' } }, axisLabel: { formatter: '{value} ' } }],series: [{ name: '温度', type: 'line', yAxisIndex: 0, data: WenduDatatem.value },{ name: '湿度', type: 'line', yAxisIndex: 1, data: WenduDatahum.value },{ name: '光照', type: 'line', yAxisIndex: 2, data: WenduDataill.value }]};wenduChart.value.setOption(option);wenduChart.value.resize();};tryWendu()
}
// 新增温湿度时间维度切换
const handleWenduTimeTypeChange = () => {if (WenduTimeType.value === 'day') {WenduSelectedHour.value = new Date()} else if (WenduTimeType.value === 'month') {WenduSelectedMonth.value = new Date()} else if (WenduTimeType.value === 'year') {WenduSelectedYear.value = new Date()} else if (WenduTimeType.value === 'hour') {WenduSelectedHour.value = new Date()}generateWenduData()
}
// 监听暗黑模式变化时,初始化新图表--若有需要
const observer = new MutationObserver((mutations) => {mutations.forEach((mutation) => {if (mutation.attributeName === 'class') {nextTick(() => {if (props.deviceTypeId === '2') {generateWenduData();} });}});
});
//渲染
// 页面加载和激活时都调用
function waitForContainerAndInitChart() {const chartDomwendu = document.querySelector('.wendu-chart') as HTMLElement;if (!chartDom || !chartDomradar || !chartDomwendu) {requestAnimationFrame(waitForContainerAndInitChart);return;}const { width, height } = chartDom.getBoundingClientRect();const { width: wenduWidth, height: wenduHeight } = chartDomwendu.getBoundingClientRect();if (width === 0 || height === 0 || radarWidth === 0 || radarHeight === 0 || wenduWidth === 0 || wenduHeight === 0) {requestAnimationFrame(waitForContainerAndInitChart);return;}
if (props.deviceTypeId === '2') {generateWenduData();}
}
// 生命周期钩子模拟
window.addEventListener('resize', handleResize);
observer.observe(document.documentElement, {attributes: true,attributeFilter: ['class']
});
// 用 requestAnimationFrame 递归检测容器宽高直到可用再初始化 ECharts
// 页面加载和激活时都调用
waitForContainerAndInitChart();
window.addEventListener('pageshow', () => {waitForContainerAndInitChart();
});
// 页面卸载时清理
window.addEventListener('beforeunload', () => {window.removeEventListener('resize', handleResize);if (wenduChart.value) wenduChart.value.dispose && wenduChart.value.dispose();observer.disconnect();
});// 页面加载时请求一次
onMounted(() => {if (props.deviceTypeId === '2') {generateWenduData();} window.addEventListener('resize', handleResize);observer.observe(document.documentElement, {attributes: true,attributeFilter: ['class']});
});onUnmounted(() => {window.removeEventListener('resize', handleResize);if (wenduChart.value) wenduChart.value.dispose && wenduChart.value.dispose();observer.disconnect();
});