第136篇:Three.js基础入门动画API:setInterval 与 requestAnimationFrame的区别

Posted 养肥胖虎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第136篇:Three.js基础入门动画API:setInterval 与 requestAnimationFrame的区别相关的知识,希望对你有一定的参考价值。

好家伙,书接上文

 

function animate()      
//请求-动画-框架 requestAnimationFrame( animate ); //改变正方体在场景中的位置,让正方体动起来 cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render( scene, camera ); // 结合场景和相机进行渲染,即用摄像机拍下此刻的场景(最后一步)

 

 

 

这是一段动画的渲染方案

这里使用了requestAnimationFrame()而没有使用定时器setInterval

 

动画渲染部分为什么不使用定时器setTimeout而使用requestAnimationFrame()?

 

 

window.requestAnimationFrame() 

告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。

该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

当你准备更新动画时你应该调用此方法。这将使浏览器在下一次重绘之前调用你传入给该方法的动画函数 (即你的回调函数)。

回调函数执行次数通常是每秒 60 次,但在大多数遵循 W3C 建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配

                                                    ----来自MDN文档

 

说到定时器setInterval,我们又要扯到异步,

js引擎单线程执行的,它是基于事件驱动的语言.它的执行顺序是遵循一个叫做事件队列的机制.
浏览器有各种各样的线程,比如事件触发器,网络请求,定时器等等.线程的联系都是基于事件的.
js引擎处理到与其他线程相关的代码,就会分发给其他线程,他们处理完之后,需要js引擎计算时就是在事件队列里面添加一个任务.
这个过程中,js并不会阻塞代码等待其他线程执行完毕,而且其他线程执行完毕后添加事件任务告诉js引擎执行相关操作.
                            ----来自setTimeout 与 requestAnimationFrame 的区别 - 掘金 (juejin.cn)
 
 
所以说,定时有"被卡住的可能",他必须等前面的任务完成.
而刷新时间变长,帧数就会下降
而requestAnimationFrame采用系统时间间隔,保持最佳绘制效率,不会因为间隔时间过短,造成过度绘制,增加开销;
也不会因为间隔时间太长,使用动画卡顿不流畅,让各种网页动画效果能够有一个统一的刷新机制,从而节省系统资源,改善视觉效果。
 
 
所以我们总结一下:

requestAnimationFrame()优势:

1.requestAnimationFrame()更流畅

定时器setInterval存在延迟卡顿的问题

而使用 requestAnimationFrame 执行动画,能保证回调函数在屏幕每一次刷新间隔中只被执行一次,

确保不丢帧,动画不卡顿

 

2.requestAnimationFrame()更合理

定时器setInterval的执行频率由时间决定

而requestAnimationFrame()的执行频率与浏览器屏幕刷新次数相匹配

 

3.节约资源

当页面被隐藏时,定时器 setInterval 仍在后台执行动画任务

而requestAnimationFrame()的动画刷新会暂停

 
 
 

 

Three.JS提升学习6:创建动画和移动摄像机

*本文学习资源来自《Three.js开发指南 WebGL的JavaScript 3D库》

基础动画

基础渲染函数

render();
function render()
renderer.render(scene, camera);
requestAnimationFrame(render);

简单动画

我们可以通过改变物体的旋转、缩放、位置、材质、顶点、面以及其它很多方式来实现动画。

通过改变摄像机来实现动画

renderScene();

function renderScene()
group.rotation.x += 0.02;
requestAnimationFrame(renderScene);
renderer.render(scene, camera);

改变物体位置等属性实现动画

render();

function render()
stats.update();
// rotate the cube around its axes
cube.rotation.x += controls.rotationSpeed;
cube.rotation.y += controls.rotationSpeed;
cube.rotation.z += controls.rotationSpeed;

// bounce the sphere up and down
step += controls.bouncingSpeed;
sphere.position.x = 20 + ( 10 * (Math.cos(step)));
sphere.position.y = 2 + ( 10 * Math.abs(Math.sin(step)));

// render using requestAnimationFrame
requestAnimationFrame(render);
renderer.render(scene, camera);

选择对象

document.addEventListener(mousedown, onDocumentMouseDown, false);
document.addEventListener(mousemove, onDocumentMouseMove, false);

var projector = new THREE.Projector();
var tube;

function onDocumentMouseDown(event)
// 屏幕坐标转为三维场景中的坐标
var vector = new THREE.Vector3(( event.clientX / window.innerWidth ) * 2 - 1, -( event.clientY / window.innerHeight ) * 2 + 1, 0.5);
vector = vector.unproject(camera);
//创建raycaster向场景中发射光线
var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
//哪些被光线照到
var intersects = raycaster.intersectObjects([sphere, cylinder, cube]);

if (intersects.length > 0)
//照到的修改属性
console.log(intersects[0]);

intersects[0].object.material.transparent = true;
intersects[0].object.material.opacity = 0.1;

Tween.js

实现动画

// create a tween
// http://sole.github.io/tween.js/examples/03_graphs.html
var posSrc = pos: 1;
var tween = new TWEEN.Tween(posSrc).to(pos: 0, 5000);
tween.easing(TWEEN.Easing.Sinusoidal.InOut);

var tweenBack = new TWEEN.Tween(posSrc).to(pos: 1, 5000);
tweenBack.easing(TWEEN.Easing.Sinusoidal.InOut);

tween.chain(tweenBack);
tweenBack.chain(tween);


var onUpdate = function ()
var count = 0;
var pos = this.pos;

loadedGeometry.vertices.forEach(function (e)
var newY = ((e.y + 3.22544) * pos) - 3.22544;
pointCloud.geometry.vertices[count++].set(e.x, newY, e.z);
);

pointCloud.sortParticles = true;
;

tween.onUpdate(onUpdate);
tweenBack.onUpdate(onUpdate);

加载模型及启动tween

var loader = new THREE.PLYLoader();

loader.load("../assets/models/test.ply", function (geometry)
loadedGeometry = geometry.clone();

var material = new THREE.PointCloudMaterial(
color: 0xffffff,
size: 0.4,
opacity: 0.6,
transparent: true,
blending: THREE.AdditiveBlending,
map: generateSprite()
);

pointCloud = new THREE.PointCloud(geometry, material);
pointCloud.sortParticles = true;

tween.start();
scene.add(pointCloud);
);


render();

运行效果:
Three.JS提升学习6:创建动画和移动摄像机_缩放

使用摄像机

Three.js 提供了一些摄像机控件,使用这些控件可以控制场景中的摄像机。这些控件在Three.js发布包中,可以在examples/js/controls目录中找到它们。

名称

英文

描述

第一视角控件器

FirstPersonControls

类似第一视角射击游戏中的摄像机,使用键盘移动、鼠标转动

飞行控制器

FlyControls

飞行模拟控制器,用键盘和鼠标控制摄像机的移动

翻滚控制器

RollControls

飞行控制器的简化版,允许绕着z轴旋转

轨迹球控制器

TrackBallControls

最常用的控制器,可以使用鼠标(或控制球)来轻松移动、平移或缩放场景

轨道控制器

OrbitControls

该控件可以在特定的场景中模拟轨道中的卫星,可以使用鼠标和键盘在场景中游走

其它控件:
设备朝向控制器:DeviceOrientationControls
编辑控制器:EditorControls
眼睛控制器:OculusControls
正交轨迹球控制器:OrthographicTrackball Controls
鼠标锁定控制器:PointerLockControls
变换控制器:TransformCOntrols
VR控制器:VRControls

除了控制器,还可以通过修改position属性来移动摄像机,通过lookAt()方法来改变摄像机的朝向。

轨迹球控制器使用示例

<script type="text/javascript" src="../libs/TrackballControls.js"></script>
<script>
var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
/// 把控制器绑定到摄像机上
var trackballControls = new THREE.TrackballControls(camera);

trackballControls.rotateSpeed = 1.0; //摄像机的旋转速度
trackballControls.zoomSpeed = 1.0;
trackballControls.noZoom = false; //允许缩放
trackballControls.panSpeed = 1.0;
trackballControls.staticMoving = true;
</script>

在render里更新摄像机的位置

function render() 
//用来精确计算出此次调用距离上次调用的时间间隔
var delta = clock.getDelta();
//更新摄像机的位置
trackballControls.update(delta);
requestAnimationFrame(render);
webGLRenderer.render(scene, camera)

变形动画与骨骼动画

略……


以上是关于第136篇:Three.js基础入门动画API:setInterval 与 requestAnimationFrame的区别的主要内容,如果未能解决你的问题,请参考以下文章

Three.js入门篇创建一个场景

webGL之three.js入门3--材料篇

Three.js基础坐标轴辅助器requestAnimationFrame处理动画Clock时钟resize页面尺寸

three.js - (入门三)

webGL之three.js入门4--ThreeJS Editor入门篇

Web3D|基于WebGL的Three.js框架|入门篇