从three.js旋转动画,我了解了requestAnimationFrame

这篇具有很好参考价值的文章主要介绍了从three.js旋转动画,我了解了requestAnimationFrame。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

 📫 大家好,我是南木元元,热衷分享有趣实用的文章,希望大家多多支持,一起进步!

 🍅 个人主页:南木元元


目录

three.js旋转动画

动画前置知识

屏幕刷新率与浏览器重绘次数

动画是如何形成的

实现动画的方式有哪些

什么是requestAnimationFrame

setTimeout&&setInterval

结语


three.js旋转动画

three.js中渲染出一个立方体很简单,代码如下:

import * as THREE from "three";

// 创建场景
const scene = new THREE.Scene();
// 创建透视相机
const fov = 45;
const aspect = window.innerWidth / window.innerHeight;
const near = 1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// 定位相机
camera.position.set(200, 300, 200);
camera.lookAt(0, 0, 0);

// 创建立方体(几何+材质)
const geometry = new THREE.BoxGeometry(10, 10, 10);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
// 添加到场景
scene.add(mesh);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 渲染
renderer.render(scene, camera);

如果要实现一个旋转动画,只需把渲染部分的代码稍作修改:

//循环渲染
function animation() {
  // 改变角度
  mesh.rotateY(0.01);
  // 重新渲染
  renderer.render(scene, camera);
  // 下一帧渲染回调
  requestAnimationFrame(animation);
}
animation();

效果:

从three.js旋转动画,我了解了requestAnimationFrame,# three.js,three.js,前端,动画

three.js中使用了requestAnimationFrame来实现动画的渲染,那么为什么不使用setInterval来实现呢?比如下面这样。

// 渲染函数
function animation() {
  mesh.rotateY(0.01); 
  renderer.render(scene, camera); 
}
// 间隔20ms周期性调用渲染函数
setInterval(animation, 20);

下面就来探究一下原因。

动画前置知识

我们先需要了解一些概念以及形成动画的原因。

屏幕刷新率与浏览器重绘次数

屏幕刷新率:1s内屏幕刷新的次数。

一般的电脑的屏幕刷新率为每秒60次1000ms/60≈16.7ms | 60FPS),也就是每16.7ms会刷新一下屏幕。当然此数值受到分辨率、显卡、屏幕尺寸等其他因素的影响。

由于一般的电脑的刷新频率是60FPS,所以大多数浏览器会限制其重绘次数,一般不会超过计算机的重绘次数,因为即使超过了其频率,用户的体验也不会得到提升。

动画是如何形成的

动画是由于肉眼导致的视觉残留,通过连续播放的静态图像形成的动态幻觉。动画说白了就是一张张照片,连起来依次展示,这样就形成一个动画效果,只要帧率高,人的眼睛就感觉不到卡顿,是连续的视频效果。当1s中连续播放24张图片时(24FPS),即可形成流畅的动画,通常来说计算机的刷新频率是60FPS

实现动画的方式有哪些

  • JavaScript:setTimeout和setInterval
  • css3:transition和animation
  • html:canvas和SVG
  • requestAnimationFrame API
  • ...

明明可以用css3、setTimeout来完成动画效果,为什么HTML5又提供了requestAnimationFrame?

什么是requestAnimationFrame

顾名思义,request(请求)Animation(动画)Frame(帧),来看看MDN上对它的定义。

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

通俗点讲就是该API的调用频率取决于浏览器的刷新率,也就是说浏览器屏幕刷新多少次,它就执行多少次,一般为每秒60次,可以将其理解为专门用来实现动画效果的api,让浏览器流畅的执行动画效果。

  • 那么为何要用这个api来做动画呢?

css动画代码简单,性能上也会好一点,因为浏览器会对CSS3的动画做一些优化(比如专门新建一个图层来跑动画),缺点是动画控制不够灵活,部分动画功能无法实现(如滚动动画),这时我们就要考虑使用js定时器来做动画。

但是定时器做动画存在一个很大的问题:动画会抖动,体验效果不好。来看下面的一个例子。

let i = 0;
let requestId: number;
function animation() {
  test.style.marginLeft = `${i}px`;
  requestId = requestAnimationFrame(animation);
  i++;
  if (i > 200) {
    cancelAnimationFrame(requestId);
  }
}
animation();

上面用requestAnimationFrame实现了一个动画,不断修改dom元素的left值,使其运动起来,每执行一次大约是16.7ms同时requestAnimationFrame会返回一个请求 ID,是回调函数列表中的一个唯一值,可以使用cancelAnimationFrame通过传入该请求 ID 取消回调函数。

效果:

从three.js旋转动画,我了解了requestAnimationFrame,# three.js,three.js,前端,动画

接下来再来使用js的定时器动画来实现:

let i = 0;
let timerId: number;
function animation() {
  test.style.marginLeft = `${i}px`;
  // 执行间隔设置为 0,来模仿 requestAnimationFrame
  timerId = setTimeout(animation, 0);
  i++;
  if (i > 200) {
    clearTimeout(timerId);
  }
}
animation();

在这里将setTimeout的执行间隔设置为 0,来模仿requestAnimationFrame。单单从代码上实现的方式,看不出有什么区别,但是从下面具体的实现结果就可以看出很明显的差距了。

下图2是setTimeout执行结果:

从three.js旋转动画,我了解了requestAnimationFrame,# three.js,three.js,前端,动画

通过上述例子,你应该知道requestAnimationFrame比定时器好在哪里了吧。

setTimeout&&setInterval

setTimeout和setInterval的问题是,它们不够精确。这是由于事件循环机制导致的,该内在运行机制决定了时间间隔参数 实际上只是指定了把动画代码添加到事件队列中以等待执行的时间。如果队列前面已经加入了其它任务,那动画代码就要等前面的任务完成后再执行,并且如果时间间隔过短(小于16.7ms)会造成丢帧,所以就会导致动画可能不会按照预设的去执行,降低用户体验。

requestAnimationFrame采用浏览器时间间隔 ,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,消耗性能;也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,提高系统性能,改善视觉效果。

现在我们回到three.js旋转动画的例子,我们使用setInterval定时器代替requestAnimationFrame:

import * as THREE from "three";

// 创建场景
const scene = new THREE.Scene();
// 创建透视相机
const fov = 45;
const aspect = window.innerWidth / window.innerHeight;
const near = 1;
const far = 1000;
const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
// 定位相机
camera.position.set(200, 300, 200);
camera.lookAt(0, 0, 0);

// 创建立方体(几何+材质)
const geometry = new THREE.BoxGeometry(100, 100, 100);
const material = new THREE.MeshNormalMaterial();
const mesh = new THREE.Mesh(geometry, material);
// 添加到场景
scene.add(mesh);

// 创建渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 渲染函数
function animation() {
  mesh.rotateY(0.01); 
  renderer.render(scene, camera); 
}
//间隔20ms周期性调用渲染函数, 20ms也就是刷新频率是50FPS(1s/20ms),每秒渲染50次
setInterval(animation, 20);

这里官方说调用渲染方法.render()进行渲染的渲染频率不能太低。

//设置调用render函数的周期为200ms,刷新频率相当于5你能明显的感受到卡顿
setInterval("render()",200);

效果:

从three.js旋转动画,我了解了requestAnimationFrame,# three.js,three.js,前端,动画

你能明显感受到比较卡顿了。所以three.js动画渲染一般使用requestAnimationFrame,更好的利用浏览器渲染,保持最佳绘制效率。

结语

🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏✍️评论支持一下博主~     文章来源地址https://www.toymoban.com/news/detail-777328.html

到了这里,关于从three.js旋转动画,我了解了requestAnimationFrame的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • three.js进阶之动画系统

    我曾在three.js进阶之骨骼绑定文章中提到了AnimationMixer、AnimationAction等内容,其实这些应该属于Three.js的动画系统,本文就系统的介绍一下动画系统(Animation System)。 一般情况下,我们很少会使用three.js的动画系统去手动创建动画——因为这真的很麻烦,更高效便捷的做法还是

    2024年02月02日
    浏览(41)
  • three.js 汽车行驶动画效果

    实现原理是使用TWEEN.Tween实现动画效果 使用Promise编写模型的异步加载方法 参数position是汽车初始位置,参数rotation是汽车初始朝向 调用: 第1个参数是汽车初始位置,第2个参数表示汽车初始朝向:西 参数start是行驶起点位置,参数end是行驶终点位置,参数speed是速度 this.mod

    2024年02月05日
    浏览(44)
  • Three.js 进阶之旅:滚动控制模型动画和相机动画 ?

    声明:本文涉及图文和模型素材仅用于个人学习、研究和欣赏,请勿二次修改、非法传播、转载、出版、商用、及进行其他获利行为。 专栏上篇文章《Three.js 进阶之旅:页面*滑滚动-王国之泪》 讲解并实现了如何使用 R3F 进行页面图片*滑滚动,本文内容在上节的基础上,学习

    2024年02月06日
    浏览(52)
  • Three.js 模型加载及加载简单动画

    时间过的好快啊~再一次感叹,忙忙碌碌一年又过去了,新年第一帖,新的一年也要加油呀! 简单介绍下Three.js吧,Three.js是基于原生WebGL封装运行的三维引擎,在所有WebGL引擎中,Three.js是国内文资料最多、使用最广泛的三维引擎。因为使用简单,入门比较容易。 Three.js的具体

    2024年02月12日
    浏览(50)
  • Three.js使用OrbitControls后修改相机旋转方向无效

            在项目中添加了OrbitControls控制器来控制相机的旋转和平移,但是需要修改初始的相机角度,于是我把相机的角度进行修改,如下: 运行项目后发现相机的位置并没有发生变化。原因是相机旋转和移动被OrbitControls控制器托管了。         方法1.于是我尝试创建一个组

    2024年02月16日
    浏览(53)
  • three.js 使用 tweenjs绘制相机运动动画

    效果: 代码:  

    2024年01月18日
    浏览(53)
  • Three.js之相机、渲染器、光源、动画、性能监测

    第一个3D案例—透视投影相机 第一个3D案例—渲染器 … Canvas画布布局和全屏 透视投影相机PerspectiveCamera WebGL渲染器WebGLRenderer 辅助观察坐标系AxesHelper 漫反射网格材质MeshLambertMaterial 点光源PointLight 点光源辅助观察PointLightHelper 环境光AmbientLight 平行光DirectionalLight 平行光辅助观

    2024年02月13日
    浏览(45)
  • Three.js加载FBX模型并解析骨骼动画

    通过Threejs先加载一个.FBX格式的三维模型文件,然后解析该文件中的骨骼动画信息。  FBX 加载器 FBXLoader.js 加载fbx模型文件 加载模型文件,加载完成后,如果模型显示位置不符合要求,可以通过Threejs程序进行平移、缩放等操作。 查看FBX模型帧动画数据 stl、obj都是静态模型,

    2024年02月07日
    浏览(87)
  • Three.js移动端双指触屏控制旋转和缩放

    在移动端通过双指来控制物体的选择和缩放。旋转通过双指旋转操作,而缩放通过双指距离实现。实现平台是小程序基于three.js的AR版。 旋转:两个手指产生的两个点可以算出一个向量,那么我就通过程序前后两帧计算两个向量之间的夹角来判断旋转的角度信息。这里我通过

    2024年02月08日
    浏览(67)
  • three.js 缓动算法.easing(渐入相机动画)

    效果:淡入,靠近物体 代码:

    2024年01月19日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包