vue3+ts+echarts多Y轴图表

发布于:2025-07-14 ⋅ 阅读:(18) ⋅ 点赞:(0)

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();
});


网站公告

今日签到

点亮在社区的每一天
去签到