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

Vue3+Three.js:requestAnimationFrame的详细介绍

文章目录

  • 理解requestAnimationFrame的基本概念
    • 定义
    • 核心作用
    • 与传统定时器实现的对比
      • setTimeout/setInterval 实现动画的优缺点
      • requestAnimationFrame 的优点
    • 典型应用场景
  • requestAnimationFrame的工作原理
    • 浏览器渲染流程详解
    • requestAnimationFrame 的调用时机
    • 与浏览器刷新率同步的实现
  • requestAnimationFrame的语法与参数
    • **语法**
    • **参数说明**
  • 完整代码(渲染一个立方体的变体)

理解requestAnimationFrame的基本概念

定义

requestAnimationFrame 是浏览器提供的一个专门用于动画效果的API,它告诉浏览器您希望执行一个动画,并请求浏览器在下次重绘之前调用指定的函数来更新动画。

核心作用

  1. 与浏览器刷新率同步:自动匹配显示器的刷新率(通常60Hz,即每秒60次),确保动画流畅不丢帧
  2. 优化性能:当页面处于非活动状态(如标签页被隐藏)时自动暂停执行,减少资源消耗
  3. 浏览器优化:浏览器可以合并多个动画请求,进行统一优化处理

与传统定时器实现的对比

setTimeout/setInterval 实现动画的优缺点

优点

  • 兼容性更好(支持所有浏览器)
  • 可以自由控制执行间隔时间

缺点

  1. 性能问题
    • 无法与屏幕刷新同步,可能导致过度绘制或丢帧
    • 即使页面隐藏也会继续执行,浪费CPU资源
    • 示例:用setInterval实现的动画在标签页后台运行时仍然消耗资源
  2. 时间不精确
    • 受JavaScript事件循环影响,实际执行时间可能延迟
    • 在低端设备上可能出现明显的卡顿现象
  3. 电池消耗
    • 不会自动暂停,持续消耗设备电量

requestAnimationFrame 的优点

  1. 性能优化
    • 自动匹配显示器刷新率,减少不必要的重绘
    • 页面不可见时自动暂停,节省资源
    • 示例:使用rAF的动画在切换标签页后自动停止
  2. 流畅度
    • 确保动画在每次屏幕刷新时只更新一次
    • 避免"布局抖动"问题(多个CSS属性同时变化时)
  3. 现代浏览器支持
    • 包括自动降频(当设备刷新率降低时自动调整)

典型应用场景

  1. 复杂动画:如游戏、数据可视化等需要高性能的场景
  2. 响应式UI:需要与用户交互同步的界面动画
  3. 滚动效果:实现平滑的滚动和视差效果

requestAnimationFrame的工作原理

浏览器渲染流程详解

现代浏览器的渲染流程通常包含以下关键步骤:

  1. JavaScript 执行
    • 执行同步 JavaScript 代码
    • 处理事件回调
    • requestAnimationFrame 回调在此阶段执行
  1. 样式计算(Style Calculation)
    • 计算应用于每个 DOM 元素的 CSS 样式
    • 包括继承样式和层叠样式计算
  1. 布局(Layout/Reflow)
    • 计算每个元素在页面中的几何位置和大小
    • 构建渲染树(Render Tree)
  1. 绘制(Paint)
    • 将元素转换为实际像素
    • 生成绘制指令列表
  1. 合成(Composite)
    • 将不同层合并为最终图像
    • 使用 GPU 加速处理

requestAnimationFrame 的调用时机

requestAnimationFrame(rAF) 的设计目的是与浏览器刷新率同步执行动画代码:

  1. 同步机制
    • rAF 回调会在浏览器每次重绘前执行
    • 通常与显示器刷新率同步(如 60Hz 显示器约 16.67ms 一次)
  1. 调用位置
    • rAF 回调在渲染管线的 JavaScript 执行阶段执行
    • 执行时机在样式计算和布局之前
  1. 性能优势
    • 避免不必要的中间帧计算
    • 当页面不可见或最小化时会自动暂停

与浏览器刷新率同步的实现

  1. 垂直同步(VSync)协调
    • 浏览器会等待显示器发出的 VSync 信号
    • rAF 回调队列在 VSync 信号到来时执行
  1. 60FPS 优化
    • 这种递归调用方式确保与刷新率同步
function animate() {// 动画逻辑requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
  1. 高刷新率设备适配
    • 在 120Hz 显示器上会自动调整为约 8.3ms 执行一次
    • 无需开发者手动调整时间间隔

requestAnimationFrame的语法与参数

语法

const requestID = requestAnimationFrame(callback);

参数说明

  1. callback:浏览器在下次重绘(repaint)前调用的函数,通常是动画的更新逻辑。
  • 回调函数参数:
    • timestamp(时间戳):由 requestAnimationFrame 自动传入,表示回调被调用的时间(从页面加载开始的毫秒数)。可用于计算帧间隔时间(delta time),实现时间同步的动画。
    • 示例:
function animate(timestamp) {console.log("当前帧时间戳:", timestamp);// 动画逻辑...
}
requestAnimationFrame(animate);
  1. 返回值
  • 类型:number(非零整数)
  • 描述:返回一个唯一标识符(ID),可用于取消动画帧请求(通过 cancelAnimationFrame)。
  • 示例:
     const animationID = requestAnimationFrame(animate);// 取消动画cancelAnimationFrame(animationID);

完整代码(渲染一个立方体的变体)

Vue3+Three.js打造3D立方体

可以与上面这个帖子中的代码进行对比,稍微不同,在下面的截图中有具体标注,也就是白色框的部分。

<script setup lang="ts">
import * as THREE from 'three'
import { onMounted, ref } from 'vue'const canvasThree = ref()// 创建scene、camera、renderer
let scene: THREE.Scene, camera: THREE.PerspectiveCamera, renderer: THREE.WebGLRenderer, cube: THREE.Mesh
// 1.创建场景
function initScene() {scene = new THREE.Scene()
}
// 2.创建相机
function initCamera() {camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000,)camera.position.set(0, 0, 10)scene.add(camera)
}
// 3.创建物体(几何体 + 材质 = 物体)
function initCube() {const boxWidth = 1const boxHeight = 1const boxDepth = 1const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth)const material = new THREE.MeshBasicMaterial({ color: 0x44AA88 })cube = new THREE.Mesh(geometry, material)scene.add(cube)
}
// 4.渲染场景
function initRenderer() {// 创建渲染器renderer = new THREE.WebGLRenderer({ antialias: true, canvas: canvasThree.value })// 设置渲染器尺寸renderer.setSize(window.innerWidth, window.innerHeight)
}
// 5.动画循环渲染场景
function animate() {requestAnimationFrame(animate)// 渲染场景renderer.render(scene, camera)
}
onMounted(() => {// 初始化场景、相机、渲染器、物体initScene()initCamera()initRenderer()initCube()// 启动动画循环animate()
})
</script><template><canvas id="canvasThree" ref="canvasThree" />
</template>

在这里插入图片描述

这里就是我们在使用three.js这个库时,所应用的requestAnimationFrame

  • 根据上面的理论知识,来理解这里的白色代码,整个代码,除了白色部分,在上个帖子已经说明。
  • 重复下:就是我们要看到一个立方体,需要:创建场景、创建相机并放入场景中、渲染这个场景到我们的网页元素
  • 这时,我们添加一个立方体,放入场景中,也是我们做好了上面的三步,事实上是渲染不出来的。
  • 如果我们采用这次的动画函数来渲染,这样就可以了。(我相信根据上面的对requestAnimationFrame的理论介绍,细思是比较容易理解的。)
  • 在前两个帖子,实现了官网的案例,以及对轨道控制器的使用,其实都有这个代码,这次,针对这个requestAnimationFrame,也就是我们的动画函数,做了更深的介绍。
http://www.dtcms.com/a/483694.html

相关文章:

  • 找南阳建立网站的公司wordpress彻底禁用google
  • WHAT - 前端动画的前世今生
  • 技术视界 | 破解“1+1>2”的难题:多机器人系统的协同挑战与前沿突破
  • PPT宏代码
  • asp.net网站开发全过程淘宝客网站开发教程
  • 无锡网站优化推广东莞模板网站设计
  • 高级网站开发工程师什么是云速建站服务
  • 建动画网站需要多少钱德阳企业网站建设
  • SpringBootTest运行线程池被拒绝
  • 百度快照和做网站有关系吗企业网站网站建设电话
  • 高港做网站专业网站建设新闻
  • 网页网站设计公司排行榜高端网站创建
  • 工业时序数据分析:波动情况
  • 脚本三合一:设备监控+文档筛选+UUID重命名
  • 数据结构——哈希(自定义hashMap实现、解决哈希冲突、拉链寻址Java实现)
  • 电力电子技术 第二章——稳态分析
  • 湛江做网站苏州厂商如何备案成企业网站
  • 德州极速网站建设小程序网站登录验证码显示不出来
  • PT2000 Dev Studio产生的微码解析一-Channel 1
  • 笔试强训(二)
  • 专业全网推广建站公司网站正能量视频不懂我意思吧
  • Pixel-Perfect:生成像素级深度细节深度提升
  • 如何利用网站赚钱建立网站的公司
  • Java字节码与流量回放
  • 网站开发与设计作业网站全屏轮播怎么做
  • ceph 之跳过监控栈 --skip-monitoring-stack
  • wordpress添加表情合肥建站公司seo
  • 网站建设公司 关于我们目录更新 wordpress
  • 有专门做网站的吗wordpress上看图片慢
  • 2345浏览器网站进入做网站阿里巴巴好还是百度好