使用requestAnimationFrame写防抖和节流
debounce.ts
防抖工具函数:
function Animate() {this.timer = null;
}Animate.prototype.start = function (fn) {if (!fn) {throw new Error('需要执行函数');}if (this.timer) {this.stop();}this.timer = requestAnimationFrame(fn);
}Animate.prototype.stop = function () {if (!this.timer) {return;}cancelAnimationFrame(this.timer);this.timer = null;
}export default Animate;
注意:
以上是es5写法,也可以自行改成es6的class类写法
使用示例:
import React, { useState, useEffect } from 'react';
import Animate from 'utils/debounce';export default function UseTransition() {const [isAnimationFrame, setIsAnimationFrame]= useState(false);const [rangeValue, setRangeValue] = useState(1);const [renderData, setRenderData] = useState([1]);const [isPending, setIsPending] = useState(false);const animate = new Animate();const handleRange = (e) => {const value = parseInt(e.target.value, 10);setRangeValue(value);// 模拟 startTransition 的效果setIsPending(true);// 使用 requestAnimationFrame 模拟异步操作const fn = () => {const arr = Array(value).fill(null).map((_, index) => index + 1);setRenderData(arr);setIsPending(false);animate.stop();}// 1000/60动画帧频率isAnimationFrame ? animate.start(fn): fn();};useEffect(() => {return () => {isAnimationFrame && animate.stop();};}, []);const jsx = renderData.map((item) => (<divkey={item}style={{width: 20,height: 20,backgroundColor: `#${Math.floor(Math.random() * 22222222).toString(16)}`,margin: 10,display: 'inline-block',}}>{item}</div>));return (<div><div style={{ textAlign: 'center' }}><label><inputtype="checkbox"checked={isAnimationFrame}onChange={(e) => {setIsAnimationFrame(e.target.checked)}}/>setIsAnimationFrame</label><inputtype="range"value={rangeValue}min={0}max={10000}style={{ width: 120 }}onChange={handleRange}/><span>进度条 {rangeValue}</span><span>{isPending ? 'loading' : ''}</span><hr /></div>{jsx}</div>);
}
throttle.ts
节流工具函数
function Animate() {this.timer = null;this.lastRun = 0;this.interval = 1000 / 60; // 默认每秒 60 帧,即约 16.67 毫秒
}Animate.prototype.start = function (fn, interval = 1000 / 60) {if (!fn) {throw new Error('需要执行函数');}this.interval = interval;// 高精度:performance.now() 返回的时间戳精度通常在微秒级别,而 Date.now() 的精度通常在毫秒级别。const now = performance.now();if (this.timer === null && (now - this.lastRun >= this.interval)) {this.lastRun = now;this.timer = requestAnimationFrame(() => {fn();this.timer = null;this.start(fn, interval); // 递归调用以继续动画});}
}Animate.prototype.stop = function () {if (!this.timer) {return;}cancelAnimationFrame(this.timer);this.timer = null;this.lastRun = 0;
}export default Animate;
使用示例:
import React, { useState, useEffect } from 'react';
import Animate from 'utils/throttle';export default function UseTransition() {const [isAnimationFrame, setIsAnimationFrame]= useState(false);const [rangeValue, setRangeValue] = useState(1);const [renderData, setRenderData] = useState([1]);const [isPending, setIsPending] = useState(false);const animate = new Animate();const handleRange = (e) => {const value = parseInt(e.target.value, 10);setRangeValue(value);// 模拟 startTransition 的效果setIsPending(true);// 使用 requestAnimationFrame 模拟异步操作const fn = () => {const arr = Array(value).fill(null).map((_, index) => index + 1);setRenderData(arr);setIsPending(false);animate.stop();}// 1000/60动画帧频率isAnimationFrame ? animate.start(fn, 1000/60): fn();};useEffect(() => {return () => {isAnimationFrame && animate.stop();};}, []);const jsx = renderData.map((item) => (<divkey={item}style={{width: 20,height: 20,backgroundColor: `#${Math.floor(Math.random() * 22222222).toString(16)}`,margin: 10,display: 'inline-block',}}>{item}</div>));return (<div><div style={{ textAlign: 'center' }}><label><inputtype="checkbox"checked={isAnimationFrame}onChange={(e) => {setIsAnimationFrame(e.target.checked)}}/>setIsAnimationFrame</label><inputtype="range"value={rangeValue}min={0}max={10000}style={{ width: 120 }}onChange={handleRange}/><span>进度条 {rangeValue}</span><span>{isPending ? 'loading' : ''}</span><hr /></div>{jsx}</div>);
}
防抖和节流的区别?
防抖(Debounce)
定义:
- 防抖是指在一系列连续的事件触发中,只在最后一次事件触发后的一段时间内执行一次回调函数。
特点:
- 忽略中间的调用,只在最后一次调用后执行。
- 适用于需要在用户操作结束后再执行某些操作的场景,例如输入框的搜索建议、窗口的 resize 事件等。
节流(Throttle)
定义:
- 节流是指在一定时间间隔内最多执行一次回调函数。
特点:
- 在指定的时间间隔内,无论触发多少次事件,最多只执行一次回调函数。
- 当前时间戳now 减去 上一次执行animate的时间戳lastRun的结果 >= 指定的时间间隔,则执行一次函数。
- 适用于需要在固定时间间隔内执行某些操作的场景,例如滚动事件、鼠标移动事件等。
相关文章:
使用requestAnimationFrame写防抖和节流
debounce.ts 防抖工具函数: function Animate() {this.timer null; }Animate.prototype.start function (fn) {if (!fn) {throw new Error(需要执行函数);}if (this.timer) {this.stop();}this.timer requestAnimationFrame(fn); }Animate.prototype.stop function () {i…...
Puppeteer 与浏览器版本兼容性:自动化测试的最佳实践
Puppeteer 支持的浏览器版本映射:从 v20.0.0 到 v23.6.0 自 Puppeteer v20.0.0 起,这个强大的自动化库开始支持与 Chrome 浏览器的无头模式和有头模式共享相同代码路径,为自动化测试带来了更多便利。从 v23.0.0 开始,Puppeteer 进…...
Java方法重写
在Java中,方法重写是指在子类中重新定义父类中已经定义的方法。以下是Java方法重写的基本原则: 子类中的重写方法必须具有相同的方法签名(即相同的方法名、参数类型和返回类型)。子类中的重写方法不能比父类中的原方法具有更低的…...
vscode通过.vscode/launch.json 内置php服务启动thinkphp 应用后无法加载路由解决方法
我们在使用vscode的 .vscode/launch.json Launch built-in server and debug 启动thinkphp应用后默认是未加载thinkphp的路由文件的, 这个就导致了,某些thinkphp的一些url路由无法访问的情况, 如http://0.0.0.0:8000/api/auth.admin/info这…...
Webserver(2.6)有名管道
目录 有名管道有名管道使用有名管道的注意事项读写特性有名管道实现简单版聊天功能拓展:如何解决聊天过程的阻塞 有名管道 可以用在没有关系的进程之间,进行通信 有名管道使用 通过命令创建有名管道 mkfifo 名字 通过函数创建有名管道 int mkfifo …...
四足机器人实战篇之一:波士顿spot机器人工程实现分析
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言一、机器人发展历史二、硬件系统及电机执行器篇硬件系统电机执行器传感器机处理器电气连接三、感知(视觉点云、局部地图、定位)篇1.深度相机获取…...
TensorFlow 预训练目标检测模型集合
Tensorflow 提供了一系列在不同数据集上预训练的目标检测模型,包括 COCO 数据集、Kitti 数据集、Open Images 数据集、AVA v2.1 数据集、iNaturalist 物种检测数据集 和 Snapshot Serengeti 数据集。这些模型可以直接用于推理,特别是当你对这些数据集中已…...
字符串的区别
C 和 Java 字符串的区别 最近 C 和 Java 在同步学习,都有个字符串类型,但二者不太一样,于是就做了些许研究。 在编程中,字符串作为数据类型广泛应用于不同的场景。虽然 C 和 Java 都允许我们处理字符串,但它们在字符…...
EMR Serverless Spark:一站式全托管湖仓分析利器
本文根据2024云栖大会实录整理而成,演讲信息如下: 演讲人: 李钰(绝顶) | 阿里云智能集团资深技术专家,阿里云 EMR 团队负责人 活动: 2024 云栖大会 AI - 开源大数据专场 数据平台技术演变 …...
Linux find 匹配文件内容
在Linux中,你可以使用find命令结合-exec或者-execgrep来查找匹配特定内容的文件。以下是一些示例: 查找当前目录及其子目录下所有文件内容中包含"exampleText"的文件: find . -type f -exec grep -l "exampleText" {} \…...
【Redis优化——如何优雅的设计key,优化BigKey,Pipeline批处理Key】
Redis优化——如何优雅的设计key,优化BigKey,Pipeline批处理Key 一、Key的设计1. 命名规范2. 长度限制在44字节以内 二、BigKey优化1. 查找bigkey2. 删除BigKey3. 优化BigKey 三、Pipeline批处理Key1. 单节点的Pipeline2. 集群下的Pipeline 一、Key的设计…...
数据结构与算法分析:你真的理解图算法吗——深度优先搜索(代码详解+万字长文)
一、前言 图是计算机科学中用来表示复杂结构信息的一种基本结构。本章我们会讨论一些通用的围表示法,以及一些频繁使用的图算法。本质上来说,一个图包含一个元素集合(也就是顶点),以及元素两两之间的关系(也就是边),由于应用范围所限,本章我们仅仅讨论简单图,简单围并不会如(a…...
LinkedList 分析
LinkedList 简介 LinkedList 是一个基于双向链表实现的集合类,经常被拿来和 ArrayList 做比较。关于 LinkedList 和ArrayList的详细对比,我们 Java 集合常见面试题总结(上)有详细介绍到。 双向链表 不过,我们在项目中一般是不会使用到 Link…...
【C/C++】模拟实现strlen
学习目标: 使用代码模拟实现strlen。 逻辑: strlen 需要输入一个字符串数组类型的变量,并且返回一个整型类型的数据。strlen 需要计算字符串数组有多少个元素。 代码1:使用计数器 #define _CRT_SECURE_NO_WARNINGS 1 #include&…...
mybatis从浅入深一步步演变分析
mybatis从浅入深一步步演变分析 版本一:不使用代理(非spring) package com.yimeng.domain;public class User {private int id;private String username;private String password;public int getId() {return id;}public void setId(int id…...
Java阶段三02
第3章-第2节 一、知识点 面向接口编程、什么是spring、什么是IOC、IOC的使用、依赖注入 二、目标 了解什么是spring 理解IOC的思想和使用 了解IOC的bean的生命周期 理解什么是依赖注入 三、内容分析 重点 了解什么是spring 理解IOC的思想 掌握IOC的使用 难点 理解IO…...
【Linux】掌握库的艺术:我的动静态库封装之旅
🌈个人主页:Yui_ 🌈Linux专栏:Linux 🌈C语言笔记专栏:C语言笔记 🌈数据结构专栏:数据结构 🌈C专栏:C 文章目录 1.什么是库1.2 认识动静态库1.2.1 动态库1.2.2…...
UE5动画控制 基础
素材 mixamo先去选择一个character 点击下载 就这个下载下来 然后选几个animation, 记得勾选 把动作下载了 without skin就是只要动作 然后把他们放在一个文件夹里先 UE里导入 找一个文件夹,直接拖拽进来那个character的fbx,默认配置就…...
流畅!HTMLCSS打造网格方块加载动画
效果演示 这个动画的效果是五个方块在网格中上下移动,模拟了一个连续的加载过程。每个方块的动画都是独立的,但是它们的时间间隔和路径被设计为相互协调,以创建出流畅的动画效果。 HTML <div class"loadingspinner"><…...
linux命令之top(Linux Command Top)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 本人主要分享计算机核心技…...
MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
Vite中定义@软链接
在webpack中可以直接通过符号表示src路径,但是vite中默认不可以。 如何实现: vite中提供了resolve.alias:通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...
