echarts y轴滚动(react版本)

news2024/9/25 14:06:57

目录

效果图如下,代码见下方

代码可以直接复制,图片和css也要复制

tsx代码

css代码

代码里用到的图片,可以换成自己项目的图


效果图如下,代码见下方

代码可以直接复制,图片和css也要复制

tsx代码
import React, { useEffect, useRef, useState } from "react";
import styles from "./index.module.less";
import listItemImg from "@/assets/images/biz/list-item-bg.png";
import barTopImg from "@/assets/images/biz/bar-top.png";
import * as echarts from "echarts";

const dataZoomDefaultShowNum = 5; // 默认显示的数据条数

const DataContent: React.FC<any> = (props) => {
  const chartDom: any = useRef(null);
  const chartResizeTimer: any = useRef(null);
  const chart: any = useRef(null);
  const scrollTimer: any = useRef(null);
  const [echartsOptions, setEchartsOptions] = useState<any>();

  const [data] = useState<any[]>([
    {
      name: "扬州市",
      num: "100",
      target: "500",
    },
    {
      name: "常州市",
      num: "200",
      target: "300",
    },
    {
      name: "南京市",
      num: "150",
      target: "300",
    },
    {
      name: "苏州市",
      num: "80",
      target: "100",
    },
    {
      name: "无锡市",
      num: "90",
      target: "150",
    },
    {
      name: "盐城",
      num: "110",
      target: "150",
    },
    {
      name: "淮安",
      num: "120",
      target: "150",
    },
    {
      name: "宿迁",
      num: "130",
      target: "150",
    },
  ]);

  useEffect(() => {
    if (!chartDom || !data || !data.length) {
      return;
    }
    if (!chart.current) {
      chart.current = echarts.init(chartDom.current as HTMLElement);
    }
    const fun = () => {
      // 绘制图表
      const barWidth = Math.floor(
        (8 * document.documentElement.clientWidth) / 1920
      );
      const symbolHeight = Math.floor(
        (14 * document.documentElement.clientWidth) / 1920
      );
      const axisFontSize = Math.floor(
        (16 * document.documentElement.clientWidth) / 1920
      );
      const axisY2FontSize = Math.floor(
        (20 * document.documentElement.clientWidth) / 1920
      );
      const axisY2UnitFontSize = Math.floor(
        (12 * document.documentElement.clientWidth) / 1920
      );
      const axisYImageSize = Math.floor(
        (16 * document.documentElement.clientWidth) / 1920
      );

      let yData: any[] = [];
      let sData: any[] = [];
      let dataDict: any = {};
      data.forEach((item) => {
        let currentPercent =
          Number(((Number(item.num) / Number(item.target)) * 100).toFixed(0)) >
          100
            ? 100
            : Number(
                ((Number(item.num) / Number(item.target)) * 100).toFixed(0)
              );
        dataDict[item.name] = { ...item, progress: currentPercent };
        yData.push(item.name);
        sData.push(currentPercent);
      });
      const echartsOption = {
        grid: {
          top: 0,
          left: 0,
          right: 0,
          bottom: 0,
          containLabel: true,
        },
        xAxis: {
          axisLabel: {
            show: false,
          },
          splitLine: {
            show: false,
          },
          max: 100,
        },
        yAxis: [
          {
            type: "category",
            axisLabel: {
              textStyle: {
                rich: {
                  image: {
                    backgroundColor: {
                      image: listItemImg,
                      width: axisYImageSize,
                      height: axisYImageSize,
                    },
                  },
                  name: {
                    color: "#C9EEFF",
                    fontSize: axisFontSize,
                  },
                },
              },
              formatter: function (v: any) {
                return `{image|}{name|${v}}`;
              },
            },
            axisLine: {
              show: false,
            },
            axisTick: {
              show: false,
            },
            data: yData,
          },
          {
            axisTick: "none",
            axisLine: "none",
            show: true,
            axisLabel: {
              inside: false,
              textStyle: {
                rich: {
                  value: {
                    color: "#C9EEFF",
                    fontSize: axisY2FontSize,
                    fontFamily: "DinBold",
                  },
                  unit: {
                    color: "#7883A7",
                    fontSize: axisY2UnitFontSize,
                  },
                },
              },
              formatter: function (v: any) {
                return `{value|${v}}{unit|%}`;
              },
            },
            data: sData,
          },
        ],
        series: [
          {
            type: "bar",
            barWidth,
            showBackground: true,
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
                { offset: 0, color: "#2D3A5C" },
                { offset: 0.78, color: "#2C86F0" },
                { offset: 1, color: "#DDECFD" },
              ]),
            },
            data: sData,
          },
          {
            name: "XXX",
            type: "pictorialBar",
            symbol: barTopImg,
            symbolSize: [2, symbolHeight],
            symbolOffset: [1, 0],
            itemStyle: {
              normal: {
                color: "#B8DAFF",
              },
            },
            symbolPosition: "end",
            data: sData,
          },
        ],
        dataZoom: [
          {
            yAxisIndex: 0,
            show: false,
            startValue: data.length - 1 - dataZoomDefaultShowNum,
            endValue: data.length - 2,
          },
          {
            yAxisIndex: 1,
            show: false,
            startValue: data.length - 1 - dataZoomDefaultShowNum,
            endValue: data.length - 2,
          },
        ],
      };
      chart && chart.current && chart.current.setOption(echartsOption);
      chart && chart.current && chart.current.resize();
      setEchartsOptions(echartsOption);
    };
    fun();

    window.addEventListener("resize", () => {
      if (chartResizeTimer && chartResizeTimer.current) {
        clearTimeout(chartResizeTimer.current);
        chartResizeTimer.current = null;
      }
      chartResizeTimer.current = setTimeout(() => {
        fun();
        clearTimeout(chartResizeTimer.current);
        chartResizeTimer.current = null;
      }, 100);
    });

    return () => {
      chart && chart.current && chart.current.clear();
      chart && chart.current && (chart.current = null);
    };
  }, [data]);

  // y轴自动滚动
  useEffect(() => {
    if (
      !echartsOptions ||
      !data ||
      !data.length ||
      data.length < dataZoomDefaultShowNum
    ) {
      return;
    }
    const setScrollTimer = () => {
      scrollTimer.current = setInterval(() => {
        if (echartsOptions.dataZoom[0].startValue < 1) {
          echartsOptions.dataZoom[0].startValue =
            data.length - 1 - dataZoomDefaultShowNum;
          echartsOptions.dataZoom[0].endValue = data.length - 2;
          echartsOptions.dataZoom[1].startValue =
            data.length - 1 - dataZoomDefaultShowNum;
          echartsOptions.dataZoom[1].endValue = data.length - 2;
        } else {
          echartsOptions.dataZoom[0].startValue =
            echartsOptions.dataZoom[0].startValue - 1;
          echartsOptions.dataZoom[0].endValue =
            echartsOptions.dataZoom[0].endValue - 1;
          echartsOptions.dataZoom[1].startValue =
            echartsOptions.dataZoom[1].startValue - 1;
          echartsOptions.dataZoom[1].endValue =
            echartsOptions.dataZoom[1].endValue - 1;
        }
        chart && chart.current && chart.current.setOption(echartsOptions, true);
      }, 1500);
    };
    const clearScrollTimer = () => {
      if (scrollTimer && scrollTimer.current) {
        clearInterval(scrollTimer.current);
        scrollTimer.current = null;
      }
    };
    setScrollTimer();
    const mouseOverFun = () => {
      clearScrollTimer();
    };
    const mouseOutFun = () => {
      setScrollTimer();
    };
    if (chartDom && chartDom.current) {
      chartDom.current.addEventListener("mouseover", mouseOverFun);
      chartDom.current.addEventListener("mouseout", mouseOutFun);
    }
    return () => {
      if (scrollTimer && scrollTimer.current) {
        clearInterval(scrollTimer.current);
        scrollTimer.current = null;
      }
      if (chartDom && chartDom.current) {
        chartDom.current.removeEventListener("mouseover", mouseOverFun);
        chartDom.current.removeEventListener("mouseout", mouseOutFun);
      }
    };
  }, [data, echartsOptions]);

  return (
    <div className={styles.content}>
      <div ref={chartDom} className={styles.chart} />
    </div>
  );
};

export default DataContent;
css代码
.content {
  width: 430px;
  height: 240px;

  .chart {
    height: 100%;
    width: 100%;
  }
}
代码里用到的图片,可以换成自己项目的图

listItemImg

barTopImg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2163752.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode 1396. 设计地铁系统

1.题目基本信息 1.1.题目描述 地铁系统跟踪不同车站之间的乘客出行时间&#xff0c;并使用这一数据来计算从一站到另一站的平均时间。 实现 UndergroundSystem 类&#xff1a; void checkIn(int id, string stationName, int t) 通行卡 ID 等于 id 的乘客&#xff0c;在时间…

自动化测试常用函数:元素定位、操作与窗口管理

目录 一、元素的定位 1. cssSelector 2. xpath 2.1 获取HTML页面所有的节点 2.2 获取HTML页面指定的节点 2.3 获取一个节点中的直接子节点 2.4 获取一个节点的父节点 2.5 实现节点属性的匹配 2.6 使用指定索引的方式获取对应的节点内容 二、操作测试对象 1. 点击/提交…

多个ECU测试方案-IP地址相同-DoIP刷新-环境测试耐久测试

情况1&#xff1a;只有一个ECU进行测试 - 接口模块只需要使用一个车载以太网转换器&#xff1b; 情况2&#xff1a;多ECU同时测试&#xff0c;但ECU IP地址不一样&#xff0c;上位机多个网口 - 上位机测试软件&#xff0c;需要通过PC的不同网卡&#xff0c;访问各个ECU&#…

基于 RealSense D435相机实现手部姿态检测

基于 RealSense D435i相机进行手部姿态检测&#xff0c;其中采用 Mediapipe 进行手部检测&#xff0c;以下是详细步骤&#xff1a; Mediapipe 是一个由 Google开发的开源框架&#xff0c;专门用于构建多媒体处理管道&#xff0c;特别是计算机视觉和机器学习任务。它提供了一系列…

第68期 | GPTSecurity周报

GPTSecurity是一个涵盖了前沿学术研究和实践经验分享的社区&#xff0c;集成了生成预训练Transformer&#xff08;GPT&#xff09;、人工智能生成内容&#xff08;AIGC&#xff09;以及大语言模型&#xff08;LLM&#xff09;等安全领域应用的知识。在这里&#xff0c;您可以找…

【YashanDB知识库】如何配置jdbc驱动使getDatabaseProductName()返回Oracle

本文转自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7352676.html?templateId1718516 问题现象 某些三方件&#xff0c;例如 工作流引擎activiti&#xff0c;暂未适配yashandb&#xff0c;使用中会出现如下异常&#xff1a; 问题的风险及影响 …

【YashanDB知识库】查询YashanDB表空间使用率

本文转自YashanDB官网&#xff0c;具体内容请见https://www.yashandb.com/newsinfo/7369203.html?templateId1718516 【问题分类】功能使用 【关键字】表空间&#xff0c;使用率 【问题描述】YashanDB使用过程中&#xff0c;如何查询表空间的使用率 【问题原因分析】需要查…

NTPD使用/etc/ntp.conf配置时钟同步详解

NTPD使用/etc/ntp.conf配置时钟同步详解 引言安装NTPD配置/etc/ntp.conf1. 权限控制(restrict)2. 指定上层NTP服务器(server)3. 本地时间服务器(可选)启动NTPD服务验证时间同步ntpd服务默认多长时间同步一次ntp.conf上如何配置同步的频率和间隔配置步骤注意事项结论引言 …

虚拟数据架构能否取代传统数据架构?

虚拟数据架构能否取代传统数据架构&#xff1f; 前言虚拟数据架构能否取代传统数据架构 前言 数据虚拟化能够将分散在不同地方的数据整合起来&#xff0c;形成一个统一的视图&#xff0c;让数据同学能够更轻松地访问和分析这些数据。就像是把一堆杂乱无章的拼图碎片拼成了一幅…

从前端到全栈,你只差这款神器!

作为一名前端开发者&#xff0c;你是否也遇到过这样的困扰&#xff1a;界面做好了&#xff0c;功能完成了一半&#xff0c;却因为没有后端支持而卡住了进度&#xff1f;想自己搭建服务器&#xff0c;发现耗时耗力&#xff0c;学习曲线陡峭&#xff0c;最后项目拖延、效率大打折…

瑞芯微RK3566鸿蒙开发板Android11修改第三方输入法为默认输入法

本文适用于触觉智能所有支持Android11系统的开发板修改第三方输入法为默认输入法。本次使用的是触觉智能的Purple Pi OH鸿蒙开源主板&#xff0c;搭载了瑞芯微RK3566芯片&#xff0c;类树莓派设计&#xff0c;是Laval官方社区主荐的一款鸿蒙开发主板。 一、安装输入法并查看输入…

mysql如何快速编写单表查询语句

目录 背景生成sql语句 背景 我们在编写查询语句的时候&#xff0c;都提倡需要用到哪些字段就查哪些字段&#xff0c;这样有两个好处&#xff1a;1、可以增加程序运行效率&#xff0c;2、可以避免无关字段被暴露。那我们一个字段一个字段写就比较烦&#xff0c;有没有方法快速生…

优化 Go 语言数据打包:性能基准测试与分析

场景&#xff1a;在局域网内&#xff0c;需要将多个机器网卡上抓到的数据包同步到一个机器上。 原有方案&#xff1a;tcpdump -w 写入文件&#xff0c;然后定时调用 rsync 进行同步。 改造方案&#xff1a;使用 Go 重写这个抓包逻辑及同步逻辑&#xff0c;直接将抓到的包通过网…

udig处理 shape地图中 数据显示

比如城市的名称的显示 udig新建project 新建Map 然后添加shape 修改 attribute 中文 为英文 没啥用&#xff0c;改不了 这里Label 勾选下&#xff0c;选择 市 拷贝XML 到geoserver style里面 参考 geoserver发布shp地图-CSDN博客

排序算法Java实现

文章目录 排序算法概述比较排序算法非比较排序算法稳定 vs 不稳定Java 中的排序 外部排序1) 冒泡排序2) 选择排序3) 堆排序4) 插入排序5) 希尔排序6) 归并排序递归实现时间复杂度非递归实现 7) 归并插入8) 快速排序随机基准点处理重复值 9) 计数排序10) 桶排序11) 基数排序 排序…

javaseday31多线程

什么是多线程 线程与进程 小结 并发和并行 并发 并行 小结 多线程的实现方式 方法一 public class Demo1 {public static void main(String[] args) {//使用多线程的第一种方法/*** 1、创建一个类继承Thread类* 2、并重写run方法* 3、创建子类对象&#xff0c;并启动线程*/M…

深度知识追踪(论文复现)

深度知识追踪&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 深度知识追踪&#xff08;论文复现&#xff09;论文概述论文方法实验部分数据集实验步骤step1:安装环境依赖step2:下载数据集&#xff0c;将其变成one-hot编码step3:进行训练…

备战软考Day04-计算机网络

1、计算机网络的分类 2、七层网络体系结构 3、网络的设备与标准 4、TCP/IP协议族 TCP/IP作为Internet的核心协议&#xff0c;被广泛应用于局域网和广域网中&#xff0c;目前已成为事实上的国际标准 1、TCP/IP分层模型 TCP/IP协议是Internet的基础和核心&#xff0c;和OSI参考…

SqlSugar的where条件中使用可空类型报语法错误

SQLServer数据表中有两列可空列&#xff0c;均为数值类型&#xff0c;同时在数据库中录入测试数据&#xff0c;Age和Height列均部分有值。   使用SqlSugar的DbFirst功能生成数据库表类&#xff0c;其中Age、Height属性均为可空类型。   当Where函数中的检索条件较多时&a…

Web3技术在元宇宙中的应用:从区块链到智能合约

随着元宇宙的兴起&#xff0c;Web3技术正逐渐成为其基础&#xff0c;推动着数字空间的重塑。元宇宙不仅是一个虚拟世界&#xff0c;它还代表着一个由去中心化技术驱动的新生态系统。在这个系统中&#xff0c;区块链和智能合约发挥着至关重要的作用&#xff0c;为用户提供安全、…