使用React 18、Echarts和MUI实现温度计

news2024/11/25 1:02:18

关键词 React 18 EchartsMUI

前言

在本文中,我们将结合使用React 18EchartsMUI(Material-UI)库,展示如何实现一个交互性的温度计。我们将使用Echarts绘制温度计的外观,并使用MUI创建一个漂亮的用户界面。
本文将详细介绍实现温度计所需的关键代码以及其他必要的步骤,本文会尽可能的提供详细的注释。

完成后的样式

温度计.jpg

关键代码

import React from 'react';
import * as echarts from 'echarts/core';
import { EChartOption } from '../../EChartOption';
import CommonChart from '../../CommonChart';
import { Box } from '@mui/material';

interface TemperatureBarProps {
  deviceData: any;
}

const MAX_TEMPERATURE_SOCPE = 120; //温度上限
const MIN_TEMPERATURE_SOCPE = -40; // 温度下限

/**
 * 温度图表组件
 */
const TemperatureChart = () => {
  // 温度数值
  let TPvalue = MAX_TEMPERATURE_SOCPE;
  // 刻度数据
  let kd = [];
  // 渐变色配置
  let Gradient = [];

  // 创建刻度数据
  for (
    let i = 0, len = MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE;
    i <= len;
    i += 1
  ) {
    if (i % 20 === 10) {
      kd.push('');
    } else if (i % 40 === 0) {
      kd.push('-48');
    } else if (i % 8 === 0) {
      kd.push('-28');
    } else {
      kd.push('');
    }
  }

  // 根据温度数值设置渐变色和文本内容
  if (TPvalue > 20) {
    Gradient.push(
      {
        offset: 0,
        color: '#93FE94'
      },
      {
        offset: 0.5,
        color: '#E4D225'
      },
      {
        offset: 1,
        color: '#E01F28'
      }
    );
  } else if (TPvalue > -20) {
    Gradient.push(
      {
        offset: 0,
        color: '#93FE94'
      },
      {
        offset: 1,
        color: '#E4D225'
      }
    );
  } else {
    Gradient.push({
      offset: 1,
      color: '#93FE94'
    });
  }

  // 温度图表配置选项
  const option = {
    animation: false, // 禁止动画效果
    title: {
      text: '  ℃',
      top: '5px',
      left: 'center',
      textStyle: {
        color: '#fff',
        fontStyle: 'normal',
        fontWeight: 'normal',
        fontSize: '16px',
        padding: 5
      }
    },
    grid: {
      left: '45', // 图表距离容器左边的距离
      bottom: 20, // 图表距离容器底部的距离
      top: 30 // 图表距离容器顶部的距离
    },
    yAxis: [
      {
        show: false, // 不显示y轴
        data: [], // y轴的数据
        min: 0, // y轴的最小值
        max: MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE + 10, // y轴的最大值
        axisLine: {
          show: false // 不显示y轴的轴线
        }
      },
      {
        show: false, // 不显示y轴
        min: 0, // y轴的最小值
        max: MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE // y轴的最大值
      },
      {
        type: 'category', // 类型为分类
        position: 'left', // y轴的位置在左边
        offset: -80, // y轴与图表的偏移量
        axisLabel: {
          fontSize: 10, // y轴标签的字体大小
          color: 'white' // y轴标签的颜色为白色
        },
        axisLine: {
          show: false // 不显示y轴的轴线
        },
        axisTick: {
          show: false // 不显示y轴的刻度线
        }
      }
    ],
    xAxis: [
      {
        show: false, // 不显示x轴
        min: -50, // x轴的最小值
        max: 80, // x轴的最大值
        data: [] // x轴的数据
      },
      {
        show: false, // 不显示x轴
        min: -48, // x轴的最小值
        max: 120 // x轴的最大值
      }
    ],
    series: [
      {
        name: '条', // 数据项名称
        type: 'bar', // 图表类型为柱状图
        xAxisIndex: 0, // 与第一个x轴关联
        data: [MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE + 10], // 柱状图的数据
        barWidth: 18, // 柱状图的宽度,
        label: {
          show: true // 显示标签
        },
        itemStyle: {
          color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
            {
              offset: 0.05,
              color: '#5087EC' // 渐变颜色的起始色
            },
            {
              offset: 0.5,
              color: '#58DBA4' // 渐变颜色的起始色
            },
            {
              offset: 0.6,
              color: '#FFF81D' // 渐变颜色的中间色
            },
            {
              offset: 0.8,
              color: '#FA9917' // 渐变颜色的中间色
            },
            {
              offset: 1,
              color: '#FF4D4F' // 渐变颜色的结束色
            }
          ]),
          borderRadius: [8, 8, 2, 2] // 柱状图的圆角样式
        },
        z: 2 // 数据系列层叠的顺序值
      },
      {
        name: '圆', // 数据项名称
        type: 'scatter', // 图表类型为散点图
        hoverAnimation: false, // 禁止散点图的Hover动画效果
        data: [0], // 散点图的数据
        xAxisIndex: 0, // 与第一个x轴关联
        symbolSize: 18, // 散点图的符号大小
        itemStyle: {
          color: '#5087EC', // 散点图的颜色
          opacity: 1 // 散点图的透明度
        },
        z: 2 // 数据系列层叠的顺序值
      },
      {
        name: '刻度', // 数据项名称
        type: 'bar', // 图表类型为柱状图
        yAxisIndex: 0, // 与第一个y轴关联
        xAxisIndex: 1, // 与第二个x轴关联
        label: {
          show: true, // 显示标签
          position: 'left', // 标签的位置在左边
          distance: 10, // 标签与柱状图的距离
          color: 'white', // 标签的颜色为白色
          fontSize: 14, // 标签的字体大小
          formatter: function (params) {
            if (
              params.dataIndex >
              MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE
            ) {
              return '';
            }
            if (params.dataIndex % 20 === 0) {
              return params.dataIndex + MIN_TEMPERATURE_SOCPE;
            }
            return '';
          } // 标签的格式化函数
        },
        barGap: '-100%', // 柱状图之间的距离
        data: kd, // 柱状图的数据
        barWidth: 0.5, // 柱状图的宽度
        itemStyle: {
          color: 'white', // 柱状图的颜色为白色
          barBorderRadius: 120 // 柱状图的圆角样式
        },
        z: 0 // 数据系列层叠的顺序值
      }
    ]
  } as EChartOption;

  // 返回渲染图表的组件
  return <CommonChart option={option} width="100%" height="100%" />;
};

export default function TemperatureBar() {
  const [maxTemperature, setMaxTemperature] = React.useState<number>(80); // 定义最大温度的状态值,默认为80
  const [minTemperature, seMinTemperature] = React.useState<number>(-20); // 定义最小温度的状态值,默认为-20

  return (
    <Box
      ref={parentRef}
      sx={{
        display: 'flex',
        height: '100%',
        alignItems: 'center',
        justifyContent: 'center',
        position: 'relative',
        color: '#fff'
      }}
    >
      {isMinHieght ?
        <Box
          sx={{
            display: 'flex',
            flexDirection: 'column',
            textAlign: 'left'
          }}
        >
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center',
              mb: 2
            }}
          >
            <Box
              sx={{
                borderLeft: '10px solid transparent',
                borderRight: '10px solid transparent',
                borderBottom: '20px solid #FF4D4F',
                width: 0,
                height: 0,
                display: 'inline-block'
              }}
            ></Box>
            <span
              style={{
                paddingLeft: '4px'
              }}
            >
             最高温度
              {parseFloat(String(maxTemperature)).toFixed(1)}</span>
          </Box>
          <Box
            sx={{
              display: 'flex',
              alignItems: 'center'
            }}
          >
            <Box
              sx={{
                borderLeft: '10px solid transparent',
                borderRight: '10px solid transparent',
                borderTop: '20px solid #5087EC',
                width: 0,
                height: 0,
                display: 'inline-block'
              }}
            ></Box>
            <span
              style={{
                paddingLeft: '4px'
              }}
            >
             最低温度
              {parseFloat(String(minTemperature)).toFixed(1)}</span>
          </Box>
        </Box> :
        <Box
          sx={{
            width: 'calc(100% - 80px)',
            maxWidth: '140px',
            height: '80%',
            background: '#363636',
            borderRadius: '8px',
            position: 'relative',
            boxShadow: '2px 2px 8px 0px rgba(0, 0, 0, 0.7)'
          }}
        >
          <Box
            sx={{
              position: 'absolute',
              top: '-25px',
              right: '-30px',
              display: 'flex',
              alignItems: 'center',
              fontSize: '12px'
            }}
          >
            <Box
              sx={{
                marginRight: '10px',
                display: 'flex',
                alignItems: 'center'
              }}
            >
              <Box
                sx={{
                  borderLeft: '8px solid transparent',
                  borderRight: '8px solid transparent',
                  borderBottom: '14px solid #FF4D4F',
                  width: 0,
                  height: 0,
                  display: 'inline-block'
                }}
              ></Box>
              <span
                style={{
                  paddingLeft: '4px'
                }}
              >
                最高
              </span>
            </Box>
            <Box
              sx={{
                display: 'flex',
                alignItems: 'center'
              }}
            >
              <Box
                sx={{
                  borderLeft: '8px solid transparent',
                  borderRight: '8px solid transparent',
                  borderTop: '14px solid #5087EC',
                  width: 0,
                  height: 0,
                  display: 'inline-block'
                }}
              ></Box>
              <span
                style={{
                  paddingLeft: '4px'
                }}
              >
                最小
              </span>
            </Box>
          </Box>
          <Box
            sx={{
              position: 'absolute',
              left: '50%',
              top: '10px'
            }}
          >
            {/* <span>℃</span> */}
          </Box>

          <Box
            sx={{
              position: 'absolute',
              width: 'calc(50% + 20px)',
              margin: 0,
              left: '50%',
            top: `calc(30px + ((100% - 50px) * (${MAX_TEMPERATURE_SOCPE}  - ${maxTemperature} + 10) / ${
                MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE + 10
              }))`,
              transition: 'top 0.3s ease'
            }}
          >
            <hr
              style={{
                position: 'relative',
                margin: 0,
                color: '#FF4D4F',
                border: 'none',
                borderTop:  '1px solid #FF4D4F' 
              }}
            />
            <Box
              sx={{
                position: 'absolute',
                left: 'calc(100% - 10px)',
                top: '-26px',
                borderLeft: '10px solid transparent',
                borderRight: '10px solid transparent',
                borderBottom:  '16px solid #FF4D4F' 
                width: 0,
                height: 0,
                display: 'flex',
                justifyContent: 'center',
                paddingBottom: '18px'
              }}
            >
              {parseFloat(String(maxTemperature)).toFixed(1)}
            </Box>
          </Box>

          <Box
            sx={{
              position: 'absolute',
              margin: 0,
              width: 'calc(50% + 20px)',
              left: '50%',
              top: `calc(30px + (100% - 50px) * (${MAX_TEMPERATURE_SOCPE}  - ${minTemperature} + 10) / ${
                MAX_TEMPERATURE_SOCPE - MIN_TEMPERATURE_SOCPE + 10
              })`,
              transition: 'top 0.3s ease'
            }}
          >
            <hr
              style={{
                position: 'relative',
                margin: 0,
                border: 'none',
                borderTop:  '1px solid #5087EC' 
              }}
            />
            <Box
              sx={{
                position: 'absolute',
                left: 'calc(100% - 10px)',
                top: '-8px',
                borderLeft: '10px solid transparent',
                borderRight: '10px solid transparent',
                borderTop:  '16px solid #5087EC'
                width: 0,
                height: 0,
                display: 'flex',
                justifyContent: 'center',
                paddingTop: '3px'
              }}
            >
              {parseFloat(String(minTemperature)).toFixed(1)}
            </Box>
          </Box>
          <TemperatureChart />
        </Box>
      }
    </Box>
  );
}

后言

在本文中,我们使用React 18EchartsMUI库展示了如何实现一个交互性的温度计。我们通过创建一个温度计组件,并使用Echarts库绘制温度计的外观。使用MUI库,我们创建了一个漂亮的用户界面来容纳温度计。如果不使用MUI,只需要把MUI相关标签改成HTML标签即可。

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

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

相关文章

视觉盛宴:TikTok独特的短视频美学探究

TikTok作为一款风靡全球的短视频应用&#xff0c;不仅改变了用户获取信息和娱乐的方式&#xff0c;更塑造了一种独特的短视频美学。从舞蹈、音乐、剧情到创意拍摄手法&#xff0c;TikTok的短视频内容呈现出丰富多彩的画面&#xff0c;构建了一场视觉盛宴。本文将深入探讨TikTok…

web 前端之标签练习+知识点

目录 实现过程&#xff1a; 结果显示 1、HTML语法 2、注释标签 3、常用标签 4、新标签 5、特殊标签 6、在网页中使用视频和音频、图片 7、表格标签 8、超链接标签 使用HTML语言来实现该页面 实现过程&#xff1a; <!DOCTYPE html> <html><head>…

【C++初阶】七、内存管理(C/C++内存分布、C++内存管理方式、operator new / delete 函数、定位new表达式)

相关代码gitee自取&#xff1a; C语言学习日记: 加油努力 (gitee.com) 接上期&#xff1a; 【C初阶】六、类和对象&#xff08;初始化列表、static成员、友元、内部类&#xff09;-CSDN博客 目录 一 . C/C内存分布 C/C中程序内存区域划分&#xff1a; 二 . C内存管理方式 …

YOLOv8改进 | 2023检测头篇 | 利用AFPN改进检测头适配YOLOv8版(全网独家创新)

一、本文介绍 本文给大家带来的改进机制是利用今年新推出的AFPN&#xff08;渐近特征金字塔网络&#xff09;来优化检测头&#xff0c;AFPN的核心思想是通过引入一种渐近的特征融合策略&#xff0c;将底层、高层和顶层的特征逐渐整合到目标检测过程中。这种渐近融合方式有助于…

047:vue加载循环倒计时 示例

第047个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 &#xff08;1&#xff09;提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使…

Nature子刊 | snATAC-seq 揭示斑马鱼胚胎早期发育过程中的单核染色质景观

2023年7月19日&#xff0c;一篇题为“Single-nucleus chromatin landscapes during zebrafish early embryogenesis”的研究论文在scientific data&#xff08;IF9.8&#xff09;上发表&#xff0c;该研究使用华大智造单细胞测序平台进行snATAC-seq&#xff0c;建立了斑马鱼胚胎…

openGauss学习笔记-150 openGauss 数据库运维-备份与恢复-物理备份与恢复之gs_backup

文章目录 openGauss学习笔记-150 openGauss 数据库运维-备份与恢复-物理备份与恢复之gs_backup150.1 背景信息150.2 前提条件150.3 语法150.4 参数说明150.5 示例 openGauss学习笔记-150 openGauss 数据库运维-备份与恢复-物理备份与恢复之gs_backup 150.1 背景信息 openGaus…

数据结构之单链表(不带头单向非循环链表)

一.引言 上一节我们学过了顺序表&#xff0c;那么我们想想顺序表有没有问题呢&#xff1f;我们来讨论顺序表的问题及思考。 顺序表问题&#xff1a; 1.中间/头部的插入删除&#xff0c;时间复杂度为O(N) 2. 增容需要申请新空间&#xff0c;拷贝数据&#xff0c;释放旧空间。会…

循环依赖:解析软件设计的迷局

目录 引言 循环依赖的本质 影响与挑战 1. 编译和构建问题 2. 耦合度增加 3. 难以进行单元测试 4. 可扩展性降低 解决循环依赖的策略 1. 模块重构 2. 引入接口抽象 3. 依赖注入 4. 模块化与分层设计 5. 使用工具进行分析 实际案例&#xff1a;Spring框架的循环依赖…

文件系统和磁盘管理应用训练 make编译

一、 掌握Linux下磁盘管理的方法 掌握文件系统的挂载和卸载 掌握磁盘限额与文件权限管理 二、内容&#xff08;详细步骤与结果&#xff09;&#xff1a; &#xff08;1&#xff09;使用 fdisk 命令进行硬盘分区 以 root 用户登录到系统字符界面下输人 fdisk 命令&#xff…

基于ssm保险业务管理系统设计与实现论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本保险业务管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

在普通的项目中创建web的功能

新增web功能: 1.创建一个新项目&#xff0c;不勾选模板&#xff1a;2.添加web功能&#xff1a; 1.创建一个新项目&#xff0c;不勾选模板&#xff1a; 发现普通项目没有webapp文件夹&#xff0c;即没有web的功能。 2.添加web功能&#xff1a; Add framework support:添加一些…

配置本地端口镜像示例(1:1)

本地端口镜像简介 本地端口镜像是指观察端口与监控设备直接相连&#xff0c;观察端口直接将镜像端口复制来的报文转发到与其相连的监控设备进行故障定位和业务监测。 配置注意事项 观察端口专门用于镜像报文的转发&#xff0c;因此不要在上面配置其他业务&#xff0c;防止镜像…

XML映射文件(第二种方式执行SQL语句)

第一种方式是注解的方式在下面&#xff1a; 注解操作SQL语句https://blog.csdn.net/m0_71149935/article/details/134908856?spm1001.2014.3001.5501 要想使用XML&#xff0c;需要遵守三项规范&#xff1a; XML映射文件的名称与Mapper接口名称一致&#xff0c;并且将XML映射…

数据库容灾的设计与实现(五)

六、容灾方案的应用评估 上文中设计了油田数据级容灾系统&#xff0c;完成了基于Oracle Data Guard数据级容灾架构的设计和实施&#xff0c;实现了Broker Failover的FSFO切换技术、触发器提供不间断服务器端服务、客户端使用TAF实现透明故障转移的&#xff0c;完成了数据级容灾…

统信UOS_麒麟KYLINOS上跨架构下载离线软件包

原文链接&#xff1a;统信UOS/麒麟KYLINOS上跨架构下载离线软件包 hello&#xff0c;大家好啊&#xff0c;今天给大家带来一篇在统信UOS/麒麟KYLINOS上跨架构下载离线软件包的实用教程。在我们的日常工作中&#xff0c;可能会遇到这样的情况&#xff1a;需要为不同架构的设备下…

可学习超图拉普拉斯算子代码

python版本&#xff1a;3.6。sklearn版本&#xff1a;scikit-learn0.19 问题1&#xff1a;ERROR: Could not build wheels for ecos, scs, which is required to install pyproject.toml-based projects| 解决办法&#xff1a;cvxpy安装过程中遇到的坑_ecos 2.0.7.post1 cp37 …

使用Python提取PDF文件中指定页面的内容

在日常工作和学习中&#xff0c;我们经常需要从PDF文件中提取特定页面的内容。在本篇文章中&#xff0c;我们将介绍如何使用Python编程语言和两个强大的库——pymupdf和wxPython&#xff0c;来实现这个任务。 1. 准备工作 首先&#xff0c;确保你已经安装了以下两个Python库&…

软件无线电SDR-频谱采集python实现

sdr做的频谱采集&#xff0c;保存的500张频谱图&#xff0c;能看出来是什么东西吗&#xff1f;

SQL错题集2

1.插入记录 用户1001在2021年9月1日晚上10点11分12秒开始作答试卷9001&#xff0c;并在50分钟后提交&#xff0c;得了90分&#xff1b; 用户1002在2021年9月4日上午7点1分2秒开始作答试卷9002&#xff0c;并在10分钟后退出了平台。 2.请把exam_record表中2021年9月1日之前开始作…