echarts可视化之起点归零+左右0轴对齐

自领导从竞品看到起点归零功能开始 基本每个折线图都有这个需求 还会两个不同指标放在左右轴对比查看的需求 因此整理一份出来留档(思路)

参考

1. 默认状态

2. 具体需求

  1. 拖动时间轴 起点始终归零 计算策略:每条线+1 之后, 拖动时间轴范围内的数据除以该范围的起点,再-1, 即可实现拖动时间轴起点归零
  2. 左右轴要求 0 轴严格对齐 便于参照

3. 代码实现

3.1. 起点归零

既然给了策略,那就是一个算法实现的问题了。首先触发条件是拖动时间轴 那自然在 echarts 的dataZoom 方法里去实现 。

3.1.1. 第一步拿到最新时间范围的起始点下标 (s,e)

ini 复制代码
 echartsInstance.on("dataZoom", () => {
  let xAxis = echartsInstance.getModel().option.dataZoom[0];
  let s = xAxis.startValue;
  let e = xAxis.endValue;
  operateData(s, e);
});

3.1.2. 根据(s,e)重新赋值

ini 复制代码
// 简化版
const operateData = (arr: any[], s?: number, e?: number) => {
  // arr 即为需要起点归零的项
  const sIdx = s ?? 0;
  const eIdx = e ?? arr.length - 1;
  for (let i = s; i < eIdx; i++) {
    const el = arr[i];
    arr[i] = (el / arr[sIdx] - 1).toFixed(2);
  }
};
// 处理完后重新setOption

3.2. 0 轴对齐

3.2.1. 根据两组数据计算出最大最小值

ini 复制代码
const maintainScale = (originData: any) => {
  const res: any = {};
  // 1.计算每个Y轴的最大值和最小值
  originData.forEach((item: any) => {
    const yAxisIndex = item.yAxisIndex;
    const values = item.temp.map((value: any) => {
      return value;
    }); // 确保转换为整数
    if (!res[yAxisIndex]) {
      res[yAxisIndex] = {
        max: Math.max(...values),
        min: Math.min(...values),
      };
    } else {
      res[yAxisIndex].max = Math.max(res[yAxisIndex].max, ...values);
      res[yAxisIndex].min = Math.min(res[yAxisIndex].min, ...values);
    }
  });
  // 2.如果只有一个Y轴或没有Y轴,不需要调整
  if (Object.keys(res).length !== 2) {
    return false;
  }
  // 3.获取两个Y轴的最大值和最小值
  const max1 = res[0].max || 1;
  const min1 = res[0].min || 0;
  const max2 = res[1].max || 1;
  const min2 = res[1].min || 0;
  // 4.如果两个Y轴的最小值都不小于零,不需要调整
  if (min1 >= 0 && min2 >= 0) {
    return false;
  }
  // 5.计算两个Y轴数据范围的比例
  const ratio = (max1 - min1) / (max2 - min2);
  const minMax: any = {};
  if (max1 < max2 * ratio) {
    minMax.y1Max = max2 * ratio;
    minMax.y2Max = max2;
  } else {
    minMax.y1Max = max1;
    minMax.y2Max = max1 / ratio;
  }

  if (min1 < min2 * ratio) {
    minMax.y1Min = min1;
    minMax.y2Min = min1 / ratio;
  } else {
    minMax.y1Min = min2 * ratio;
    minMax.y2Min = min2;
  }

  // 6.扩展数据范围,避免数据点紧贴 Y 轴
  function gap(value: any) {
    return value * 1.05;
  }
  minMax.y1Min = gap(minMax.y1Min);
  minMax.y2Min = gap(minMax.y2Min);
  minMax.y1Max = gap(minMax.y1Max);
  minMax.y2Max = gap(minMax.y2Max);

  return minMax;
};

3.2.2. 赋值重新渲染

arduino 复制代码
const scaleNum = maintainScale(transformedData);
// 如果scaleNum不存在即用默认最大最小值
tempObj = {
  ...tempObj,
  yAxis: [
    {
      ...options.yAxis[0],
      max: (value: any) => {
        const { max } = value;
        return scaleNum ? scaleNum.y1Max : max;
      },
      min: (value: any) => {
        const { min } = value;
        return scaleNum ? scaleNum.y1Min : min;
      },
    },
    {
      ...options.yAxis[1],
      max: (value: any) => {
        const { max } = value;
        return scaleNum ? scaleNum.y2Max : max;
      },
      min: (value: any) => {
        const { min } = value;
        return scaleNum ? scaleNum.y2Min : min;
      },
    },
  ],
};
// 更新图表数据
chartInstance?.current?.setOption(tempObj);

4. 效果

相关推荐
古蓬莱掌管玉米的神9 小时前
vue3语法watch与watchEffect
前端·javascript
拉一次撑死狗9 小时前
Vue基础(2)
前端·javascript·vue.js
qq_5443291710 小时前
下载一个项目到跑通的大致过程是什么?
javascript·学习·bug
Jane - UTS 数据传输系统13 小时前
VUE+ Element-plus , el-tree 修改默认左侧三角图标,并使没有子级的那一项不展示图标
javascript·vue.js·elementui
ThomasChan12315 小时前
Typescript 多个泛型参数详细解读
前端·javascript·vue.js·typescript·vue·reactjs·js
zzlyx9915 小时前
.NET 9 微软官方推荐使用 Scalar 替代传统的 Swagger
javascript·microsoft·.net
Bunury15 小时前
组件封装-List
javascript·数据结构·list
我命由我1234515 小时前
NPM 与 Node.js 版本兼容问题:npm warn cli npm does not support Node.js
前端·javascript·前端框架·npm·node.js·html5·js
Orange30151116 小时前
【自己动手开发Webpack插件:开启前端构建工具的个性化定制之旅】
前端·javascript·webpack·typescript·node.js
Jacob程序员18 小时前
leaflet绘制室内平面图
android·开发语言·javascript