three.js学习(4)

107 阅读4分钟

10.Gsap动画库基本使用与原理

在之前我们写动画都得自己去计算时间,那有没有办法我只告诉它多少时间我要从哪里到哪里就给我动嘞。有!那就是我们非常著名的

补间动画:补间动画指的是做FLASH动画时,在两个关键帧中间需要做“补间动画”,才能实现图画的运动;插入补间动画后两个关键帧之间的插补帧是由计算机自动运算而得到的。

那么要介绍一个库叫做Gsap,它是一个从flash时代一直发展到今天的专业动画库。

首先要安装它

yarn add gsap

导入动画库

 //导入动画库
 import gsap from 'gsap'

简单的例子

 //设置动画
 gsap.to(cube.position, { x: 5, duration: 5 })
         👆我要控制的对象的位置     👆它的x轴属性移动到5的位置,使用5秒
 //也可以旋转
 gsap.to(cube.rotation, { x: 2*Math.PI, duration: 5 })

运动速率 (时间曲线Easing)

速率默认是匀速的。时间曲线的关键词是ease,可以设置进场in、出场out、进出场inOut

 gsap.to(cube.rotation, { x: 2 * Math.PI, duration: 5, ease: "power1.inOut" })

11.Gsap控制动画属性与方法

回调函数

在gsap的方法里它是提供一些回调函数的,例如在动画开始的时候触发、在动画完成的时候触发等等

 gsap.to(cube.position, {
         x: 5,
         duration: 5,
         //在动画开始的时候触发回调
         onStart: () => { console.log('动画开始') },
         //在动画完成的时候触发回调
         onComplete: () => { console.log('动画结束') },
     })

动画的重复

动画的重复可以使用它的 repeat 属性来实现。

 gsap.to(cube.position, {
         x: 5,
         duration: 5,
         //设置重复次数,若想设置无限次则次数填-1
         //repeat:-1  那么它就永远不会触发onComplete
         repeat:2
     })

往返运动

想要动画进行往返运动的话,用到的是属性 yoyo:Boolean

 gsap.to(cube.position, {
         x: 5,
         duration: 5,
         repeat:-1,
         yoyo:true
     })

延迟动画

是在指定的动画 onStart( ) 之前做出延迟运动的效果。

 gsap.to(cube.position, {
         x: 5,
         duration: 5,
         repeat: -1,
         yoyo: true,
         //延迟动画
         delay:2
     })

自由控制动画

那我能不能在自己想要的时候让它动画进行、不想要的时候让动画停止呢,当然是可以的。

首先我们得先拿到动画对象:

 const animate1 = gsap.to(cube.position, {
         x: 5,
         duration: 5,
         onStart: () => { console.log('动画开始') },
         onComplete: () => { console.log('动画结束') },
         //设置重复次数,若想设置无限次则次数填-1
         // repeat:2
         repeat: -1,
         yoyo: true,
         //延迟动画
         delay:2
     })

接着我们监听事件

动画对象有一个pause( ) 方法来暂停动画,也可以用resume( ) 来重新启动,isActive( ) 可以判断当前是否在运动。

 window.addEventListener("dblclick", () => {
     if (animate1.isActive()) {
         //暂停动画
         animate1.pause()
     } else {
         //恢复动画
         animate1.resume()
     }
 })

12.根据浏览器尺寸变化实现自适应画面

这边先讲到我们控制器的阻尼 (惯性) .enableDamping,可以给控制器带来重量感,默认值是false。!!必须在动画循环里调用.update()

 //创建轨道控制器
 const controls = new OrbitControls(camera, renderer.domElement)
 //设置控制器阻尼,让控制器更有真实效果,!!必须在动画循环里调用.update()
 controls.enableDamping = true
 
 function render() {
     //在动画循环里调用.update()
     controls.update()
     
     renderer.render(scene, camera)
     requestAnimationFrame(render)
 }

监听画面变化,更新渲染画面

window.addEventListener中有一个resize事件,可以监听到尺寸大小的变化。

 //监听画面变化,更新渲染画面
 window.addEventListener("resize", () => {
     //更新摄像头 宽高比
     camera.aspect = window.innerWidth / window.innerHeight
         //更新摄像机的投影矩阵
     camera.updateProjectionMatrix()
 
     //更新渲染器
     renderer.setSize(window.innerWidth, window.innerHeight)
         //设置渲染器的像素比
     renderer.setPixelRatio(window.devicePixelRatio)
 })

13.调用js接口控制画布全屏和退出全屏

这里有几个注意的点,在文档对象document中有一个fullscreenElement表示全屏的元素。请求全屏应在想要被全屏的元素上请求,而取消全屏应在document上取消。因为该元素请求全屏后就会加入到document中。

例子:双击控制画布全屏

 window.addEventListener("dblclick", () => {
     const fullScreenElement = document.fullscreenElement
     if (fullScreenElement) { //判断是否拥有全屏元素
         //退出全屏
         document.exitFullscreen()
     } else {
         //让画布对象全屏
         renderer.domElement.requestFullscreen()
     }
 })

14.应用图形用户界面更改变量

这里呢我们可以安装一个dat.gui库,帮助我们在页面上可以有一个控制面板供我们调节这个我们正在制作的3D对象。

 //导入dat.gui 轻量级的UI界面控制库
 import * as dat from 'dat.gui'
 
 //初始化GUI界面
 const gui = new dat.GUI()
 //我们能操作的对象的属性,可以设置最大最小值和“步伐”可以更细致
 gui.add(cube.position, "x").min(0).max(5).step(0.01).name('移动x轴').onChange((value)=>{
     console.log("值被修改为:",value)
     }).onFinishChange((value)=>{
         console.log("停下之后才会触发,值为:",value)
     })
 //修改物体的颜色  需要一个参数对象
 const params = {
     color: '#ffff00',
     fn: () => {
     //让物体运动
         gsap.to(cube.position, { x: 5, duration: 2, yoyo: true, repeat: -1 })
     }
 }
 
 gui.addColor(params, 'color').onChange((value) => {
         cube.material.color.set(value)
     })
 //物体是否显示,由于它本身的属性visible是boolean属性,因此会展示一个选项框
 gui.add(cube, "visible").name('是否显示')
 
 //自定义事件按钮,点击后触发params中的fn方法
 gui.add(params, 'fn').name('物体运动')

当然如果有多个物体需要控制的话、或者多个部件,可以分别创建文件夹:

 const gui = new dat.GUI()
 
 const folder = gui.addFolder("一个文件夹")
 //添加方式与之前相同
 folder.add(cube, "visible").name('是否显示')
 folder.add(params, 'fn').name('物体运动')

明天来正式学习几何体