Threejs與Tween.js結合創(chuàng)建動畫的詳細圖文教程
tween.js介紹
Tween.js是一個可以產(chǎn)生平滑動畫效果的js庫,其官方地址為:https://github.com/tweenjs/tween.js/,可以將源碼下載后,可以在tween.js/dist/文件夾下找到相應的js代碼,在HTML中進行引用;也可以通過npm命令在終端控制臺中安裝tween.js模塊
npm install @tweenjs/tween.js
然后在相應的頁面引用Tween.js
import * as TWEEN from '@tweenjs/tween.js'
tween.js的使用方法
tween.js的使用非常簡單,只需要三步就可以完成一個補間動畫
1、在創(chuàng)建Tween實例的時候將想要修改的變量作為參數(shù)傳遞給Tween
2、使用TWEEN.Tween().to()方法,傳入結束點的最終值,以及動畫花費多少時間兩個參數(shù)
3、使用Tween().start()方法,啟動動畫,tween引擎就可以計算從開始動畫點到結束動畫點之間值,來產(chǎn)生平滑的動畫效果
tween.js的核心方法
.to()方法
控制補間的運動形式及方向 .to() , 當tween啟動時,Tween.js將讀取當前屬性值并 應用相對值來找出新的最終值
.start(time) 方法
補間動畫啟動的方法, .start 方法接受一個參數(shù) time , 如果加入這個參數(shù),那么補間不會立即開始直到特定時刻才會開始
.stop()方法
關閉補間動畫 .stop() , 關閉這個正在執(zhí)行的補間動畫
.repeat()方法
使用該方法可以使動畫重復執(zhí)行,它接受一個參數(shù) , 描述需要重復多少次
.delay()方法
延遲執(zhí)行動畫的方法 .delay() , 接受一個參數(shù)用于控制延遲的具體時間,表示延遲多少時間后才開始執(zhí)行動畫
.pause()方法
暫停動畫.pause() , 暫停當前補間運動,與resume方法配合使用
.resume()方法
恢復動畫 .resume() , 恢復這個已經(jīng)被暫停的補間運動
.yoyo() 方法
控制補間重復的模式 .yoyo() , 這個功能只有在使用 repeat 時才有效果 ,該動畫像悠悠球一樣來回運動 , 而不是重新開始
.update()方法
更新補間動畫 TWEEN.update() , 動態(tài)更新補間運動一般配合 window.requestAnimationFrame 使用
.chain()方法
鏈式補間動畫,當我們順序排列不同的補間動畫時,比如我們在上一個補間結束的時候立即啟動另外一個補間動畫,使用 .chain() 方法來做。
//tweenB動畫在tweenA動畫完成后執(zhí)行 tweenA.chain(tweenB);
在一些情況下,可能需要將多個補間鏈接到另一個補間,以使它們(鏈接的補間)同時開始動畫:
tweenA.chain(tweenB,tweenC);
注意:調用 tweenA.chain(tweenB) 實際上修改了tweenA,所以tweenA總是在tweenA完成時啟動。 chain 的返回值只是tweenA,不是一個新的tween。
.getAll()方法
獲取所有的補間組 TWEEN.getAll()
.removeAll()方法
刪除所有的補間組 TWEEN.removeAll()
.add()方法
新增補間 TWEEN.add(tween) ,添加一個特定的補間 var tween=new TWEEN.Tween()
.remove()方法
刪除補間 TWEEN.remove(tween),刪除一個特定的補間var tween=new TWEEN.Tween()
.Group()方法
新增一個補間組,var Group=TWEEN.Group()
, new TWEEN.Tween({ x: 1 }, Group)
, 將已經(jīng)配置好的補間動畫進行分組 , TWEEN.update()
和TWEEN.removeAll()
, 不會影響到已經(jīng)分好組的補間動畫
tween.js回調函數(shù)
.onStart()補間動畫開始時執(zhí)行,只執(zhí)行一次
new TWEEN.Tween().onStart((obj)=>{})
, 補間開始時執(zhí)行,只執(zhí)行一次, 當使用 repeat() 重復補間時,不會重復運行 ,onStart((obj)=>{})
obj 補間對象作為第一個參數(shù)傳入
.onStop() 停止補間動畫時執(zhí)行
new TWEEN.Tween().onStop((obj)=>{})
, 當通過 onStop() 顯式停止補間時執(zhí)行,但在正常完成時并且在停止任何可能的鏈補間之前執(zhí)行補間,onStop((obj)=>{})
obj 補間對象作為第一個參數(shù)傳入
.onUpdate() 每次更新時執(zhí)行
new TWEEN.Tween().onUpdate((obj)=>{})
, 每次補間更新時執(zhí)行,返回實際更新后的值, onUpdate((obj)=>{})
obj 補間對象作為第一個參數(shù)傳入
.onComplete() 補間動畫完成時執(zhí)行
new TWEEN.Tween().onComplete((obj)=>{})
, 當補間正常完成(即不停止)時執(zhí)行 , onComplete((obj)=>{})
obj 補間對象作為第一個參數(shù)傳入
.onRepeat() 重復補間動畫時執(zhí)行
new TWEEN.Tween().onRepeat((obj)=>{}) , 當補間動畫完成,即將進行重復動畫的時候執(zhí)行 , onComplete((obj)=>{}) `obj 補間對象作為第一個參數(shù)傳入
TWEEN.Easing 緩動函數(shù)
tween.js為我們封裝好了常用的緩動動畫,如線性,二次,三次,四次,五次,正弦,指數(shù),圓形,彈性,下落和彈跳等緩動函數(shù)
以及對應的緩動類型:In (先慢后快) ;Out (先快后慢) 和 InOut (前半段加速,后半段減速)
常見的緩動動畫如下
- Linear:線性勻速運動效果;
- Quadratic:二次方的緩動(t^2);
- Cubic:三次方的緩動(t^3);
- Quartic:四次方的緩動(t^4);
- Quintic:五次方的緩動(t^5);
- Sinusoidal:正弦曲線的緩動(sin(t));
- Exponential:指數(shù)曲線的緩動(2^t);
- Circular:圓形曲線的緩動(sqrt(1-t^2));
- Elastic:指數(shù)衰減的正弦曲線緩動;
- Back:超過范圍的三次方緩動((s+1)t^3 – st^2);
- Bounce:指數(shù)衰減的反彈緩動。
- 以上每個效果都分三個緩動類型,分別是:
- easeIn:從0開始加速的緩動,也就是先慢后快;
- easeOut:減速到0的緩動,也就是先快后慢;
- easeInOut:前半段從0開始加速,后半段減速到0的緩動。
在Threejs中使用Tween.js庫
繼續(xù)在前面章節(jié)的代碼基礎上進行實現(xiàn),由于我們是基于vue開發(fā)的,所以這里我們使用npm的方式安裝tween.js庫
在vue中安裝并引入tween.js庫
打開控制器,輸入npm install @tweenjs/tween.js
進行安裝,在components文件夾新建TweenView.vue文件,在該文件中引入tween.jsimport * as TWEEN from '@tweenjs/tween.js'
初始化場景
在使用tween.js實現(xiàn)動畫之前,先將threejs的初始化環(huán)境搭建好,并創(chuàng)建一個立方體
<template> <div id="scene"></div> </template> <script setup> import * as THREE from 'three' import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls' import * as TWEEN from '@tweenjs/tween.js' import { onMounted } from 'vue' let scene,camera,renderer,controls onMounted(()=>{ init() }) function init() { initScene() initCamera() initAxesHelper() initLight() initRenderer() initControls() initMesh() animate() window.addEventListener('resize',onWindowResize.bind(this)) } // 初始化場景 function initScene() { scene = new THREE.Scene() } // 初始化相機 function initCamera() { camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,1000) camera.position.set(0,2,2) } // 輔助軸 function initAxesHelper() { const axesHelper = new THREE.AxesHelper(1) scene.add(axesHelper) } // 燈光 function initLight() { const hesLight = new THREE.HemisphereLight(0xffffff,0x444444) hesLight.intensity = 0.3 scene.add(hesLight) const dirLight = new THREE.DirectionalLight() dirLight.position.set(5,5,5) scene.add(dirLight) const pointLight = new THREE.PointLight(0xffffff,1.5) pointLight.position.set(0,100,90) scene.add(pointLight) pointLight.color.setHSL(Math.random(),1,0.5) } // 初始化渲染器 function initRenderer() { renderer = new THREE.WebGLRenderer({antialias:true}) renderer.setPixelRatio(window.devicePixelRatio) renderer.setSize(window.innerWidth,window.innerHeight) document.querySelector('#scene').appendChild(renderer.domElement) renderer.shadowMap.enable = true } // 初始化軌道控制器 function initControls() { controls = new OrbitControls(camera,renderer.domElement) controls.minPolarAngle = 0 controls.maxPolarAngle = 80 / 360 * 2 * Math.PI controls.update() } // Mesh function initMesh() { const boxGeometry = new THREE.BoxGeometry(0.3,0.3,0.3) const boxMaterial = new THREE.MeshPhongMaterial({color:0x00ff00}) const boxMesh = new THREE.Mesh(boxGeometry,boxMaterial) scene.add(boxMesh) } function animate() { const delta = clock.getDelta() renderer.render(scene,camera) controls.update(delta) requestAnimationFrame(animate) } function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight camera.updateProjectionMatrix() renderer.setSize(window.innerWidth,window.innerHeight) } </script> <style scoped> </style>
實例化Tween對象
實例化Tween對象并將物體當前的位置作為參數(shù)傳入該對象
const tween = new TWEEN.Tween(mesh.position)
使用.to()方法指定移動終點和時間
使用.to()方法指定移動的終點和時間
tween.to({x:3,y:0,z:0},2000)
調用.onUpdate()方法更新動畫,
調用.onUpdate()方法更新動畫,在回調函數(shù)中設置相機的.lookAt()方法,
tween.onUpdate(function(){ camera.lookAt(0,0,0) })
開啟動畫
使用.start()方法開啟動畫
tween.start()
刷新查看瀏覽器, 發(fā)現(xiàn)物體已經(jīng)按照我們給定的終點坐標進行了移動
給場景添加地面輔助線
為了更好的看到效果,給場景中添加地面輔助線,定義initGridHelper()方法,在init()函數(shù)中調用
// 輔助地面 function initGridHelper () { const gridHelper = new THREE.GridHelper(10,10) scene.add(gridHelper) }
使用.chain()方法對多段動畫進行串聯(lián)執(zhí)行
繼續(xù)對上面的物體運動進行研究,我們在物體移動到指定位置后,再給定一個目標點位置,使其繼續(xù)移動;
新建一個tween2對象,仍然將mesh.position作為參數(shù)傳入,調用tween2.to方法,指定終點坐標和時間
然后通過調用.chain()方法,將tween2作為參數(shù)傳遞給tween.chain()方法,這樣tween在執(zhí)行完第一段代碼后,會接著執(zhí)行tween2的代碼,實現(xiàn)多段動畫的連續(xù)執(zhí)行
const tween2 = new TWEEN.Tween(mesh.position) tween2.to({x:3,y:0,z:3},2000) tween.chain(tween2) tween.start()
使用tween執(zhí)行縮放動畫
tweenjs不僅僅能實現(xiàn)移動動畫,它能實現(xiàn)很多動畫功能,這里我們接著上面的動畫在物體移動到tween2指定的終點時,再對齊進行一個縮放動畫
我們先定義一個對象,里面給一個參數(shù)s為1,代表當前的縮放比例是1
const scaleParam = { s:1}
我們創(chuàng)建一個新的tween3對象然后我們創(chuàng)建一個新的tween3對象,將上面的scaleParam 作為參數(shù)傳入
const tween3 = new TWEEN.Tween(scaleParam)
調用.to方法調用tween3.to()方法,將對象s設置為10,時間設置為2000
tween3.to({s:10},2000)
調用.onUpdate()方法調用.onUpdate()方法,在.onUpdate()方法的回調函數(shù)中設置mesh在x軸的縮放值為s
tween3.onUpdate(function(){ mesh.scale.x = scaleParam.s })
調用.chain()方法調用tween2.chain()方法,將tween3作為參數(shù)傳入,表示tween2動畫執(zhí)行完后執(zhí)行tween3動畫
tween2.chain(tween3) tween.start()
刷新瀏覽器,可以看到物體按照我們預期的效果實現(xiàn)了動畫
使用緩動動畫
使用緩動動畫可以是我們的動畫看起來更真實自然,前面講過,tweenjs已經(jīng)為我們封裝了常見的緩動動畫,我們使用使只需要調用就可以了,常見的緩動動畫曲線如下圖所示
給立方體運動的動畫添加緩動動畫我們可以給上面的立方體添加緩動動畫,使其看起來更真實,我們在立方體的第一段動畫(tween)和第二段動畫(tween2)時讓其先快后慢
const tween = new TWEEN.Tween(mesh.position) tween.to({x:3,y:0,z:0},2000) tween.onUpdate(function(){ camera.lookAt(0,0,0) }).easing(TWEEN.Easing.Sinusoidal.InOut) const tween2 = new TWEEN.Tween(mesh.position) tween2.to({x:3,y:0,z:3},2000).easing(TWEEN.Easing.Sinusoidal.InOut) tween.chain(tween2) const scaleParam = { s:1} const tween3 = new TWEEN.Tween(scaleParam) tween3.to({s:10},2000) tween3.onUpdate(function(){ mesh.scale.x = scaleParam.s }) tween2.chain(tween3) tween.start()
刷新瀏覽器看效果,符合我們的要求
好了,關于tweenjs和threejs結合創(chuàng)建動畫就先說到這里,其實關于tween和threejs結合的動畫還有很多,比如可以結合tween實現(xiàn)物體顏色的變化、透明度的變化等,具體各位小伙伴可以自己摸索。
總結
到此這篇關于Threejs與Tween.js結合創(chuàng)建動畫的文章就介紹到這了,更多相關Threejs與Tween.js創(chuàng)建動畫內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java前端javascript生成動態(tài)表格示例演示
這篇文章主要為大家介紹了java前端javascript生成動態(tài)表格的實現(xiàn)示例及演示,2022-03-03