Threejs入门之六:利用HTML5的requestAnimationFrame方法实现物体的旋转
认识requestAnimationFrame
requestAnimationFrame是html5 提供一个专门用于请求动画的API,用法与settimeout很相似,只是不需要设置时间间隔而已。requestAnimationFrame使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给cancelAnimationFrame用于取消这个函数的执行 requestAnimationFrame有以下几个特点 1.requestAnimationFrame会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,如果系统绘制率是 60Hz,那么回调函数就会16.7ms再被执行一次,也就是说,requestAnimationFrame的执行步伐跟着系统的绘制频率走。它能保证回调函数在屏幕每一次的绘制间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。 2.在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,减少了CPU、GPU和内存使用量 3.requestAnimationFrame是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节CPU的开销
Threejs中利用requestAnimationFrame实现动画
接上节内容,首先在index.js中定义一个函数,在函数中调用requestAnimationFrame()方法,实现周期性循环执行
function render() {
// requestAnimationFrame 实现周期性循环执行
requestAnimationFrame(render)//请求再次执行渲染函数render,渲染下一帧
}
在render函数中,我们调用mesh的旋转函数,给它一个旋转弧度,使其沿y周旋转
// 定义一个render函数
function render() {
// requestAnimationFrame 实现周期性循环执行
mesh.rotateY(0.01) //y轴旋转的弧度
requestAnimationFrame(render)//请求再次执行渲染函数render,渲染下一帧
}
然后在js中调用render函数,刷新浏览器发现物体仍然是静止的状态,这里要注意,我们在render周期函数中每次都让mesh旋转0.01孤度,其实是已经执行了的,但是我们的渲染器没有更新,所以不会显示 我们应该将渲染器的渲染函数也放到render中
// 定义一个render函数
function render() {
// requestAnimationFrame
mesh.rotateY(0.01)//沿y轴旋转的弧度,单位 弧度
renderer.render(scene,camera)
requestAnimationFrame(render)//请求再次执行渲染函数render,渲染下一帧
}
render()
刷新浏览器,发现物体已经沿y轴自动旋转了。
代码优化
1、上面定义了一个render函数用于定时刷新渲染器,因此,我们之前的相机控件轨道控制器OrbitControls的监听change事件就可以取消掉了,因为render函数是周期执行的,总会渲染页面 2、我们之前的renderer.render(scene,camera)这句代码也可以取消了,统一在render函数中渲染。
完整代码如下
import * as THREE from 'three'
// 引入轨道控制器扩展库OrbitControls.js
import {
OrbitControls }
from 'three/addons/controls/OrbitControls.js'
// 创建一个三维场景,相当于一个画布
const scene = new THREE.Scene()
// 创建一个几何体,相当于在画布上想要呈现的物体
const geometry = new THREE.BoxGeometry(100,100,100)
// 创建材质,相当于画画时的颜料
// const material = new THREE.MeshBasicMaterial({
// color:0xff0000,//设置颜色
// transparent:true,//开启透明
// opacity:0.5//设置透明度
// }
)
const material = new THREE.MeshLambertMaterial({
color:0xff0000,//设置颜色
}
)
// 添加辅助坐标轴
// const axesHelper = new THREE.AxesHelper(100)
// scene.add(axesHelper)
// 创建物体,相当于在画物体的过程,将上面的几何体和材质结合起来形成物体
const mesh = new THREE.Mesh(geometry,material)
// 设置物体在场景中的位置
mesh.position.set(0,10,0)
// 将物体添加到场景中,相当于将物体添加到画布汇总
scene.add(mesh)
// console.log(mesh);
// 创建环境光
const light = new THREE.AmbientLight(0x404040,1)
scene.add(light)
// 创建点光 参数1 光的颜色,参数2 光的强度
const pointLight = new THREE.PointLight(0xffffff,1)
// 点光源的位置
pointLight.position.set(100,100,100)
scene.add(pointLight)
// 创建点光源辅助对象
const pointLightHelper = new THREE.PointLightHelper(pointLight,10)
scene.add(pointLightHelper)
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff,1)
// 设置光源的方向:通过光源position属性和目标指向对象的position属性计算光线的方向
directionalLight.position.set(80,100,50)
// 光的方向指向对象网格模型mesh,不设置默认为0,0,0
directionalLight.target = mesh
scene.add(directionalLight)
// 创建平行光辅助对象
const directionalLightHelper = new THREE.DirectionalLightHelper(directionalLight,10,0x00ff00)
scene.add(directionalLightHelper)
// 聚光灯
const spotLight = new THREE.SpotLight( 0xffffff );
spotLight.position.set( 0, 200, 100 );
scene.add(spotLight)
// 创建聚光灯辅助对象
const spotLightHelper = new THREE.SpotLightHelper(spotLight,0x0000ff)
scene.add(spotLightHelper)
// 创建一个相机,相机相当于画家的眼睛,
// PerspectiveCamera 透视相机:有四个参数,fov:视角,aspect:宽高比,一般定位为相机照射物体的宽高比值,
// near:近端点,离相机最近的点,far:远端点,离相机最远的点
const width = 600
const height = 400
const camera = new THREE.PerspectiveCamera(70,width/height,1,800)
// 设置相机的位置,即画家的眼睛离画布的位置
camera.position.set(200,200,200)
// 设置相机要看的位置,即眼睛要看的物体的位置
// 相机看原点
// camera.lookAt(0,0,0)
// 相机看向物体
camera.lookAt(mesh.position)
// 创建webgl渲染器
const renderer = new THREE.WebGLRenderer()
// canvas画布宽高
renderer.setSize(width,height)
// 执行渲染操作,将scene和camera关联起来,
// 相当于太阳,你有一个空间scene,空间中有物体,有人的眼睛camera,但是没有光是看不到物体的
// renderer.render(scene,camera)
// 把渲染结果canvas画布,添加到网页上
// document.body.appendChild(renderer.domElement)
document.getElementById('webgl').appendChild(renderer.domElement)
// 定义一个render函数
function render() {
// requestAnimationFrame
mesh.rotateY(0.01)//沿y轴旋转的弧度,单位 弧度
renderer.render(scene,camera)
requestAnimationFrame(render)//请求再次执行渲染函数render,渲染下一帧
}
render()
// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera,renderer.domElement)
// 监听轨道控制器的change事件,监听到改变时,重新执行渲染操作渲染三维场景
// controls.addEventListener('change',function(){
// renderer.render(scene,camera)
// }
)
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: Threejs入门之六:利用HTML5的requestAnimationFrame方法实现物体的旋转
本文地址: https://pptw.com/jishu/291390.html