echarts 双Y轴,左右刻线对齐,封装

如果你们设计稿大概像这样,那么下面的方法都可参考

实现思路-- 找到数据中第一个轴的最小最大值,然后看分割线几根,相除,第二个类似操作就行

核心代码 诸位品鉴

js 复制代码
      let y1Min = null;
      let y1Max = null;
      let y2Min = null;
      let y2Max = null;
  
        y1Min = _getMinValue(props.datas.seriesData[key].data);
        y1Max = _getMaxValue(props.datas.seriesData[key].data);
        yData[0] = {
          name: seriesData.length > 0 ? props.datas.seriesData[key].unit : "",
          type: "value",
          min: y1Min,
          max: y1Max,
          // minInterval: 1,
          splitNumber: 5,
          interval: (y1Max - y1Min) / 5,
        };
        
        y2Min = _getMinValue(props.datas.seriesData[key].data);
        y2Max = _getMaxValue(props.datas.seriesData[key].data);
        yData[1] = {
          name: seriesData.length > 0 ? props.datas.seriesData[key].unit : "",
          type: "value",
          min: y2Min,
          max: y2Max,
          // minInterval: 1,
          splitNumber: 5,
          interval: (y2Max - y2Min) / 5,
        };
        
        function _getMaxValue(arr) {
          const max = Math.max(...arr);
          // 这样处理是为了不让最大值刚好到坐标轴最顶部
          return Math.ceil(max / 10) * 10;
        }
        function _getMinValue(arr) {
          const min = Math.min(...arr);
          // 这样处理是为了不让最大值刚好到坐标轴最底部
          return Math.floor(min / 10) * 10;
        }

开始使用

父页面

js 复制代码
<AToUnitCharts :datas="chartDetialList.VoltageAmmeterData" />


async function getVoltageAmmeterData() {
  let data = await XXXX(); 
 // 后端返回类似这样  
   //   {
   //   batterystackvoltage: 15,
   //   batterystackcurrent: 11,
   //   time: "2024-04-25 12:00:00",
   // },
   // {
   //   batterystackvoltage: 20,
    //  batterystackcurrent: 21,
    //  time: "2024-04-25 12:01:00",
   // },

  let keys = [
    {
      label: "batterystackvoltage",
      name: "总电压",
      colors: [167, 79, 214], // 这里是 rgba 的前三位,因为需求是线条是 100% 面积是10%
      unit: "电压(V)",
      legend: true,  // 这里是是否显示图例
      yIdex: 0, // 这里控制是坐标轴的左面还是右面
    },
    {
      label: "batterystackcurrent",
      name: "总电流",
      colors: [123, 159, 210], // 这里是 rgba 的前三位,因为需求是线条是 100% 面积是10%
      unit: "电流(A)",
      legend: true,  // 这里是是否显示图例
      yIdex: 1,
    },
  ];
  chartDetialList.VoltageAmmeterData = tickesTwoChartData(
    data.data,
    keys,
    "time"
  );
}

// 这个是封装上面接收到的字段,然后丢到子组件里让子组件去玩。  
//主要玩的就是数据驱动视图,不然子组件每个图表都是不一样的逻辑也太扯淡了
// data,返回的主数据   keys: label: 字段名称,name 名称 xkeys x轴的对应字段
 const tickesTwoChartData = (data, keys, xkeys) => {
  let xData = [];
  let seriesData = {};

  keys.forEach((x) => {
    seriesData[x.label] = {
      name: x.name,
      data: [],
      unit: x.unit,
      colors: x.colors,
      legend: x.legend || null,
      //
      yIdex: x.yIdex,
    };
  });

  data.forEach((item) => {
    xData.push(item[xkeys]);
    keys.forEach((x) => {
      seriesData[x.label].data.push(item[x.label]);
    });
  });
  return {
    xData,
    seriesData,
  };
};

封装一个根据数据驱动的echarts 面积图

js 复制代码
<template>
  <div class="w-100% h-100%" ref="myChart"></div>
</template>

<script setup lang="ts">
import * as echarts from "echarts";
import dayjs from "dayjs";
const props = defineProps({
  // 传入的参数
  datas: {
    type: Object,
    default: () => {},
  },
});
watch(
  () => props.datas,
  (newVal) => {
    initChart();
  },
  { deep: true }
);

function _getMaxValue(arr) {
  const max = Math.max(...arr);
  // 这样处理是为了不让最大值刚好到坐标轴最顶部
  return Math.ceil(max / 10) * 10;
}
function _getMinValue(arr) {
  const min = Math.min(...arr);
  // 这样处理是为了不让最大值刚好到坐标轴最底部
  return Math.floor(min / 10) * 10;
}

const myChart = ref(null);

function initChart() {
  let legendData = [];
  let seriesData = [];
  let yData = [];
  let y1Min = null;
  let y1Max = null;
  let y2Min = null;
  let y2Max = null;
  for (const key in props.datas.seriesData) {
    if (props.datas.seriesData[key].legend) {
      legendData.push({
        name: props.datas.seriesData[key].name,
        icon: "rect",
        itemStyle: {
          color: `rgba(${props.datas.seriesData[key].colors.join(",")},1)`,
        },
      });
    }

    seriesData.push({
      name: props.datas.seriesData[key].name,
      type: "line",
      yAxisIndex: props.datas.seriesData[key].yIdex,
      areaStyle: {
        color: {
          type: "linear",
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            {
              offset: 0,
              color: `rgba(${props.datas.seriesData[key].colors.join(
                ","
              )},0.1)`,
            },
            {
              offset: 1,
              color: `rgba(${props.datas.seriesData[key].colors.join(",")},0)`,
            },
          ],
        },
      },
      lineStyle: {
        color: `rgba(${props.datas.seriesData[key].colors.join(",")},1)`,
      },
      itemStyle: {
        color: `rgba(${props.datas.seriesData[key].colors.join(",")},1)`,
      },
      smooth: true,
      unit: props.datas.seriesData[key].unit,
      data: props.datas.seriesData[key].data,
    });

    if (seriesData.length > 0) {
      if (props.datas.seriesData[key].yIdex == 0) {
        y1Min = _getMinValue(props.datas.seriesData[key].data);
        y1Max = _getMaxValue(props.datas.seriesData[key].data);
        yData[0] = {
          name: seriesData.length > 0 ? props.datas.seriesData[key].unit : "",
          type: "value",
          min: y1Min,
          max: y1Max,
          // minInterval: 1,
          splitNumber: 5,
          interval: (y1Max - y1Min) / 5,
        };

        // console.log(y1Min, "--------------", y1Max);
      }

      if (props.datas.seriesData[key].yIdex == 1) {
        y2Min = _getMinValue(props.datas.seriesData[key].data);
        y2Max = _getMaxValue(props.datas.seriesData[key].data);
        yData[1] = {
          name: seriesData.length > 0 ? props.datas.seriesData[key].unit : "",
          type: "value",
          min: y2Min,
          max: y2Max,
          // minInterval: 1,
          splitNumber: 5,
          interval: (y2Max - y2Min) / 5,
        };
        // console.log(y2Min, "--------------", y2Max);
      }
    }
  }

  let chartDom = myChart.value;
  let myCharts = echarts.init(chartDom);
  let option = {
    grid: {
      left: "3%",
      right: "3%",
      bottom: "15%",
      top: "10%",
      containLabel: true,
    },
    tooltip: {
      trigger: "axis",
      axisPointer: {
        label: {
          backgroundColor: "#6a7985",
        },
      },
    },
    legend: {
      show: legendData.length > 0,
      data: legendData,
      top: 0,
      itemHeight: 3,
      itemWidth: 15,
      left: "center",
      width: "100%",
    },
    xAxis: {
      type: "category",
      boundaryGap: false,
      axisLine: {
        lineStyle: {
          color: "#86909C",
        },
      },
      axisLabel: {
       // 这里需求是时间。我格式化过了,不需要的小伙子小姐姐可以不用
        formatter: function (value, index) {  
       
          return dayjs(value).format("HH:mm");
        },
      },
      data: props.datas?.xData,
    },
    yAxis:
      yData.length > 0
        ? yData
        : {
            name: seriesData.length > 0 ? seriesData[0].unit : "",
            type: "value",
          },
    series: seriesData,
  };

  option && myCharts.setOption(option);

  const observer = new ResizeObserver(() => {
    myCharts.resize();
  });
  observer.observe(chartDom);
}

onMounted(() => {
  initChart();
});
</script>

完活! 有用 好用AI肯定干不出来这样的

相关推荐
customer0813 分钟前
【开源免费】基于SpringBoot+Vue.JS社区养老服务平台(JAVA毕业设计)
java·vue.js·spring boot·spring cloud·开源
noravinsc18 分钟前
vue2 definecomponent is not defined
前端·javascript·vue.js
禁默1 小时前
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】CSS样式解析:行内、内部与外部样式的区别与优先级分析
前端·css
姚永强1 小时前
web前端第三次作业
前端·javascript·css
编程星空1 小时前
diff算法简析
前端·javascript·html
工业互联网专业1 小时前
基于springboot+vue的游戏创意工坊与推广平台的设计与实现
java·vue.js·spring boot·毕业设计·源码·课程设计·游戏创意工坊与推广平台
邢行行1 小时前
全面解析 CSS 常见简写语法及其使用规则
前端
田本初1 小时前
【React】如何画一个箭头
前端·react.js·前端框架
落榜美术生1 小时前
vite中的依赖预构建 到底是什么 做了什么
前端
小王不会写code2 小时前
vue-cli-service权限不足(Linux运行vue)
vue.js