当前位置: 首页 > news >正文

echarts 实现签到记录日历组件

以下笔记来源:编程导航

分析

有三种基本图表可以选择:

  1. 基础日历图:https://echarts.apache.org/examples/zh/editor.html?c=calendar-simple
  2. 日历热力图:https://echarts.apache.org/examples/zh/editor.html?c=calendar-heatmap

跟上一个图的区别就是鼠标放上去可以展示具体的热力值,热力值越高,图块的颜色越深。

  1. 日历图:https://echarts.apache.org/examples/zh/editor.html?c=calendar-charts

当我们只需要实现签到功能的时候,不涉及热力数值的区分(只有 0 和 1 签到 / 未签到的区别)。

官方生成数据的循环代码如下:

for (let time = date; time <= end; time += dayTime) {data.push([echarts.time.format(time, '{yyyy}-{MM}-{dd}', false),Math.floor(Math.random() * 10000)]);
}

得到的数据是一个二维数组,每个元素表示一个日期和对应的数值(也正是后端需要返回的结构):

[['2017-01-01', 3456],['2017-01-02', 8975],...
]

调整热力值的范围,从而控制颜色深浅。还支持调整颜色:

visualMap: {show: false,min: 0,max: 1,inRange: {color: ['#efefef', 'lightgreen']  // 颜色从灰色到浅绿色},
},

在这里插入图片描述

实现

安装 ECharts:https://echarts.apache.org/zh/index.html

和 React ECharts 可视化库:https://github.com/hustcc/echarts-for-react

npm install --save echarts
npm install --save echarts-for-react

安装失败的话,在命令后加 --force

封装日历图组件:

1)参考 React ECharts 的 官方文档 来使用 ECharts 组件,把 Demo 代码复制到新建的组件文件中。

2)定义签到日期数组变量,将数组转换为图表需要的数据。其中,对日期的处理需要用到 dayjs 库:

tsx
复制代码
// 签到日期列表([1, 200],表示第 1 和第 200 天有签到记录)
const [dataList, setDataList] = useState<number[]>([]);// 计算图表需要的数据
const year = new Date().getFullYear();
const optionsData = dataList.map((dayOfYear, index) => {// 计算日期字符串const dateStr = dayjs(`${year}-01-01`).add(dayOfYear - 1, "day").format("YYYY-MM-DD");return [dateStr, 1];
});

4)参考 Echarts 的官方 Demo 开发前端日历图:https://echarts.apache.org/examples/zh/editor.html?c=calendar-simple

先在 Demo 页面里调整好效果,得到 options 选项。

💡 小技巧:可以通过配置项或者询问 AI 得到需要的配置

import React, {useEffect, useState} from "react";
import ReactECharts from "echarts-for-react";
import "./index.css";
import dayjs from "dayjs";
import {getUserSignInRecordUsingGet} from "@/api/userController";
import {message} from "antd";/*** 日历图组件* @constructor*/
export default function CalendarChart() {// 签到日期列表([1, 200],表示第 1 和第 200 天有签到记录)const [dataList, setDataList] = useState<number[]>([1, 200]);const fetchDataList =  async  () => {try {// 请求后端获取数据const res = await getUserSignInRecordUsingGet({year});setDataList(res.data);} catch (e) {message.error(`获取刷题签到记录失败: ${e.message}`);}}useEffect(() => {fetchDataList();}, []);// 计算图表需要的数据// 当前年份const year = new Date().getFullYear();const optionsData = dataList.map((dayOfYear, index) => {// 计算日期字符串const dateStr = dayjs(`${year}-01-01`).add(dayOfYear - 1, "day").format("YYYY-MM-DD");return [dateStr, 1];});// 图表配置const options = {visualMap: {show: false,min: 0,max: 1,inRange: {// 颜色从灰色到浅绿色color: ["#efefef", "lightgreen"],},},calendar: {range: year,left: 20,// 单元格自动宽度,高度为 16 像素cellSize: ['auto', 16],yearLabel: {position: "top",formatter: `${year} 年刷题记录`,}},series: {type: "heatmap",coordinateSystem: "calendar",data: optionsData,},};return <ReactECharts option={options} />;
}

执行签到:

这里单独封装了一个钩子,因为进入详情页面时才会执行自动签到,而详情页面是在服务端渲染(本项目),获取不到登录态,所以我们需要单独封装一个钩子,在客户端额外发送请求来执行签到。

import { useEffect, useState } from "react";
import { message } from "antd";
import { addUserSignInUsingPost } from "@/api/userController";/*** 添加用户签到记录钩子*/
const useAddUserSignInRecord = () => {const [loading, setLoading] = useState(false);// 请求后端执行签到const doFetch = async () => {setLoading(true);try {await addUserSignInUsingPost();} catch (e) {message.error("添加刷题签到记录失败," + e.message);} finally {setLoading(false);}};useEffect(() => {doFetch();}, []);return { loading };
};export default useAddUserSignInRecord;

该钩子需要在客户端组件中执行,因为用到了 useEffect 防止重复请求、并且还需要获取到用户登录态。

todo: 签到成功,可以保存到 LocalStorage 等位置,防止每次刷题都重复发送签到请求。


http://www.mrgr.cn/news/21727.html

相关文章:

  • 推荐一款强大的OCR软件,请低调使用!
  • (备份) esp32 GPIO
  • 冒泡排序——基于Java的实现
  • 人工智能时代开启ai代写模式,让创作变得更加简单!
  • Python 中考虑 concurrent.futures 实现真正的并行计算
  • 解锁数据洞察:如何使用Python读取Excel文件
  • 自用NAS系列1-设备
  • 自动生成文案的神器,一键轻松生成爆款文案
  • 新手做短视频素材在哪里找?做短视频素材工具教程网站有哪些?
  • 【Oracle篇】全面理解优化器和SQL语句的解析步骤(含执行计划的详细分析和四种查看方式)(第二篇,总共七篇)
  • [数据结构] 哈希结构的哈希冲突解决哈希冲突
  • 【leetcode详解】考试的最大困扰度(滑动窗口典例)
  • Transformer从零详细解读
  • ​T​P​三​面​
  • 分布式架构下的秒杀优化实战:从高并发到数据一致性
  • Java Stream API
  • 模型训练套路(二)
  • freetts播放语音处理案例
  • 【Linux】探索进程优先级的奥秘,解锁进程的调度与切换
  • Differential Diffusion,赋予每个像素它应有的力量,以及在comfyui中的测试效果