摘要:繪制變換曲線起飛以上函數(shù)就是我們基于內(nèi)置的實(shí)現(xiàn)的自定義變換。例如飛行動(dòng)畫結(jié)束后,將飛機(jī)復(fù)位。
如何運(yùn)行的?
new Vue({ el:"#app-1", data:{ position:{ distance:10, height:30, } }, methods:{ flying:function(){ var targetPos = {distance:300,height:120} var tween = new TWEEN.Tween(this.position) function animate(time){ var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if(!isFlying) cancelAnimationFrame(id); } tween.to(targetPos, 2000) tween.start() //內(nèi)部有個(gè)this._startTime,如果傳的time-this._startTime大于2000 //那么這個(gè)update只會(huì)執(zhí)行一次 // animate(3000) animate() }, } })
#app-1 p{ font-size: 2em; position: absolute; color:#fff; }
?
TWEEN作用就是對(duì)一個(gè)對(duì)象持續(xù)的進(jìn)行線性式的改動(dòng),比如對(duì)象原始狀態(tài)為{distance:10,height:30},最終狀態(tài)為{distance:300,height:120},我們?cè)O(shè)置個(gè)時(shí)間,TWEEN就在該時(shí)間內(nèi)把對(duì)象原始的狀態(tài)漸進(jìn)的變換成最終狀態(tài)。
在初始化實(shí)例new TWEEN.Tween(original-obj)時(shí)設(shè)置原始數(shù)據(jù)對(duì)象,在實(shí)例方法to(final-obj,time)中設(shè)置最終數(shù)據(jù)對(duì)象及時(shí)間。通過實(shí)例方法start()啟動(dòng)一個(gè)TWEEN。然后通過全局方法TWEEN.update(time)去改動(dòng)對(duì)應(yīng)時(shí)間的原始數(shù)據(jù)對(duì)象,每一刻的時(shí)間對(duì)應(yīng)著一份修改的數(shù)據(jù),大概像下面這樣:
調(diào)用update() | 調(diào)用后數(shù)據(jù)的改變 |
---|---|
TWEEN.update(20) | {distance:15,height:31} |
TWEEN.update(40) | {distance:25,height:33} |
TWEEN.update(70) | {distance:45,height:37} |
如修改下代碼:
flying:function(){ var targetPos = {distance:300,height:120} var tween = new TWEEN.Tween(this.position) // function animate(time){ // var id = requestAnimationFrame(animate); // var isFlying = TWEEN.update(time); // if(!isFlying) cancelAnimationFrame(id); // } tween.to(targetPos, 2000) tween.start() TWEEN.update(1500); //內(nèi)部有個(gè)this._startTime,如果傳的time-this._startTime大于2000 //那么這個(gè)update只會(huì)執(zhí)行一次 // animate(3000) // animate() },
點(diǎn)起飛,只會(huì)轉(zhuǎn)換到1500毫秒時(shí)的狀態(tài)。
結(jié)合requestAnimationFrame(fn)如果我們不傳參數(shù),那么它會(huì)根據(jù)start()的時(shí)間自動(dòng)計(jì)算好當(dāng)前的時(shí)間再修改該時(shí)間數(shù)據(jù)。因?yàn)樽詈髷?shù)據(jù)是要渲染成動(dòng)畫形式,我們不可能一行行去調(diào)用update()。
因此要結(jié)合一個(gè)神器requestAnimationFrame(fn),這個(gè)函數(shù)就是在瀏覽器每一幀重繪一次屏幕,非常的穩(wěn)定。在這里如果是60fps的情況下就是16ms(1000ms/60)調(diào)用一次animate(),然后我們?cè)谶@個(gè)animate()重繪循環(huán)中不停的調(diào)用update(),它就可以線性的修改數(shù)據(jù),渲染之后就形成動(dòng)畫。
TWEEN也可以鏈?zhǔn)秸{(diào)用函數(shù)。開始的代碼可以修改成:
flying:function(){ var targetPos = {distance:300,height:120} var tween = new TWEEN.Tween(this.position) .to(targetPos, 2000) .start(); function animate(time){ var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if(!isFlying) cancelAnimationFrame(id); } animate() },easing函數(shù)
前面默認(rèn)情況下,數(shù)據(jù)變換和時(shí)間成正比的(Linear.None),我們可以通過傳遞參數(shù)easing()改變這種默認(rèn)效果,內(nèi)置了許多變換效果。
給TWEEN加上Bounce.Out效果
var tween = new TWEEN.Tween(this.position) .to(targetPos, 2000) .easing(TWEEN.Easing.Bounce.Out) .start();自定義easing變換函數(shù)
TWEEN里最有特色的功能就是easing()參數(shù)可以是一個(gè)自定義的函數(shù),這樣可以實(shí)現(xiàn)變換的定制。
function customerFn(k){ return fn(k) //用k作基礎(chǔ)的自定義運(yùn)算 } tween.easing(customerFn);//寫好后傳給easing()函數(shù)就行
這個(gè)k是系統(tǒng)調(diào)用的,跟你無關(guān),它是一個(gè)在[0,1]范圍內(nèi)不停增長的值,速度與時(shí)間成正比,函數(shù)返回一個(gè)基于k進(jìn)行運(yùn)算后的值。比如簡單的像Linear.None那樣的默認(rèn)變換,就是不運(yùn)算直接返回k。
我們也可使用以有的變換做運(yùn)算,正如下面這樣做。
methods: { flying: function () { var targetPos = { distance: 300, height: 120 } /** 繪制變換曲線 */ var target = document.getElementById("target"); target.appendChild(this.createGraph("Noisy Exponential.InOut", noisyEasing) ); function noisyEasing(k) { return 0.3 * Math.random() + 0.7 * TWEEN.Easing.Bounce.Out(k); } var tween = new TWEEN.Tween(this.position) .to(targetPos, 2000) .easing(noisyEasing) .start(); function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } animate() }, createGraph:function( t, f, c ) { var div = document.createElement( "div" ); div.style.display = "inline-block"; div.style.width = "200px"; div.style.height = "120px"; var canvas = document.createElement( "canvas" ); canvas.width = 180; canvas.height = 100; var context = canvas.getContext( "2d" ); context.fillStyle = "rgb(250,250,250)"; context.fillRect( 0, 0, 180, 100 ); context.lineWidth = 0.5; context.strokeStyle = "rgb(230,230,230)"; context.beginPath(); context.moveTo( 0, 20 ); context.lineTo( 180, 20 ); context.moveTo( 0, 80 ); context.lineTo( 180, 80 ); context.closePath(); context.stroke(); context.lineWidth = 2; context.strokeStyle = "rgb(255,127,127)"; var position = { x: 5, y: 80 }; var position_old = { x: 5, y: 80 }; new TWEEN.Tween( position ).to( { x: 175 }, 2000 ).easing( TWEEN.Easing.Linear.None ).start(); new TWEEN.Tween( position ).to( { y: 20 }, 2000 ).easing( f ).onUpdate( function () { context.beginPath(); context.moveTo( position_old.x, position_old.y ); context.lineTo( position.x, position.y ); context.closePath(); context.stroke(); position_old.x = position.x; position_old.y = position.y; }).start(); div.appendChild( document.createTextNode( t ) ); div.appendChild( document.createElement( "br" ) ); div.appendChild( canvas ); return div; } }
?
以上noisyEasing(k)函數(shù)就是我們基于內(nèi)置的Bounce.Out實(shí)現(xiàn)的自定義變換。createGraph()函數(shù)是官方例子扣下來的,就是在頁面繪制下自定義變換的曲線。
這是內(nèi)置的Bounce.Out變換,其實(shí)就是做了一絲絲抖動(dòng)效果。
回調(diào)方法TWEEN的四種狀態(tài)啟動(dòng)、停止、更新和完成,每種下面都可以綁定一個(gè)回調(diào)函數(shù),onStart(fn)、onStop(fn)、onUpdate(fn)和onComplete(fn)。例如飛行動(dòng)畫結(jié)束后,將飛機(jī)復(fù)位。
new Vue({ el: "#app-2", data: { position: { distance: 10, height: 30, } }, methods: { flying: function () { var _this = this var targetPos = { distance: 300, height: 120 } var tween = new TWEEN.Tween(this.position) tween.to(targetPos, 5000) .easing(TWEEN.Easing.Circular.InOut) .onComplete(function () { _this.position.distance = 10 _this.position.height = 30 }) function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } tween.start() animate() } } })
由于閉包的關(guān)系,Vue里的this不能用鉤子函數(shù)里,因此定義了一個(gè)中間變量_this。
其實(shí)update()是最常用的鉤子,一般用來在每次修改后對(duì)頁面元素做數(shù)據(jù)綁定,但這里有Vue就不需要它了。
調(diào)用實(shí)例方法repeat(frequency)設(shè)置動(dòng)畫循環(huán)次數(shù),若參數(shù)為Infinity,則循環(huán)無限次。
new Vue({ el: "#app-3", data: { rotation: { x: 0, y: 0, z: 0 } }, methods: { rotate: function () { var tween_x= new TWEEN.Tween(this.rotation) .to({ x: 360 }) var tween_y = new TWEEN.Tween(this.rotation) .to({ y: 360 }).repeat(3) var tween_z = new TWEEN.Tween(this.rotation) .to({ z: 360 }).repeat(Infinity) function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } tween_x.start() tween_y.start() tween_z.start() animate() } } })
轉(zhuǎn)一圈 轉(zhuǎn)三圈 無限轉(zhuǎn)
可以使用tween.stop()停止動(dòng)畫,修改上段JS代碼:
methods: { rotate: function () { var tween_x= new TWEEN.Tween(this.rotation) .to({ x: 360 }) var tween_y = new TWEEN.Tween(this.rotation) .to({ y: 360 }).repeat(3).onComplete(function(){ //當(dāng)?shù)诙€(gè)tween動(dòng)畫完成時(shí),停止第三個(gè)tween運(yùn)行 tween_z.stop() }) var tween_z = new TWEEN.Tween(this.rotation) .to({ z: 360 }).repeat(Infinity) function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } tween_x.start() tween_y.start() tween_z.start() animate() } }
當(dāng)?shù)诙?dòng)畫的三圈轉(zhuǎn)完時(shí),停止第三個(gè)動(dòng)畫效果。
調(diào)用鏈條與鏈條循環(huán)使用tween_a.chain(tween_b)可以按順序的(先a后b)鏈?zhǔn)秸{(diào)用多個(gè)tween實(shí)例,如果接著調(diào)用tween_b.chain(tween_a)調(diào)用將進(jìn)入無限循環(huán)中(執(zhí)行a->b->a->b),如下:
new Vue({ el: "#app-4", data: { position: { x: 20, y: 0 } }, methods: { move: function () { console.log("aaa"); var tween_a = new TWEEN.Tween(this.position) .to({ x: 280, y: 0 }, 3000) var tween_b = new TWEEN.Tween(this.position) .to({ x: 280, y: 120 }, 3000) var tween_c = new TWEEN.Tween(this.position) .to({ x: 20, y: 120 }, 3000) var tween_d = new TWEEN.Tween(this.position) .to({ x: 20, y: 0 }, 3000) function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } tween_a.chain(tween_b) tween_b.chain(tween_c) tween_c.chain(tween_d) tween_d.chain(tween_a) tween_a.start() animate() } } })
YOYO
如果TWEEN有循環(huán)(調(diào)用repeat()),并調(diào)用tween.yoyou(true),那么在執(zhí)行下一次動(dòng)畫之前,動(dòng)畫會(huì)彈到起始位置。
el: "#app-5", data: { position: { x: 20 } }, methods: { move: function () { var tween = new TWEEN.Tween(this.position) .to({ x: 280 }, 1000).repeat(1).yoyo(true) function animate(time) { var id = requestAnimationFrame(animate); var isFlying = TWEEN.update(time); if (!isFlying) cancelAnimationFrame(id); } tween.start() animate() } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93579.html
摘要:可以指定一個(gè)具體值,而非增量,在之間。這是因?yàn)?,使進(jìn)度增加超過時(shí),會(huì)變成,之后又從重新開始。所以,當(dāng)為時(shí),我們停止調(diào)用。 依賴jQuery。 import nprogress from nprogress import nprogress/nprogress.css $(#btn-loading).on(click, function () { nprogress.start...
摘要:動(dòng)畫運(yùn)動(dòng)算法線性勻速運(yùn)動(dòng)效果二次方的緩動(dòng)三次方的緩動(dòng)四次方的緩動(dòng)五次方的緩動(dòng)正弦曲線的緩動(dòng)指數(shù)曲線的緩動(dòng)圓形曲線的緩動(dòng)指數(shù)衰減的正弦曲線緩動(dòng)超過范圍的三次方緩動(dòng)指數(shù)衰減的反彈緩動(dòng)。 requestAnimFrame兼容 window.requestAnimFrame = (function (callback,time) { return window.requestAnima...
摘要:首先引入一個(gè)概念就補(bǔ)間動(dòng)畫做動(dòng)畫時(shí)會(huì)用到類,利用它可以做很多動(dòng)畫效果,例如緩動(dòng)彈簧等等。代表的就是最后一幀減去初始值就是變化量,代表最后一幀的結(jié)束也是動(dòng)畫的結(jié)束。 一、理解tween.js 如果看到上面的已經(jīng)理解了,可以跳過下面的部分.下面為對(duì)Tween.js的解釋 下面就介紹如何使用這個(gè)Tween了,首先b、c、d三個(gè)參數(shù)(即初始值,變化量,持續(xù)時(shí)間)在緩動(dòng)開始前,是需要先確定好的。...
摘要:個(gè)人筆記在給在線簡歷添加特效過程中遇到的問題及解決方法二預(yù)覽點(diǎn)擊菜單滾動(dòng)動(dòng)畫首頁目標(biāo)位置當(dāng)作終點(diǎn)坐標(biāo)當(dāng)前滾動(dòng)到的距離當(dāng)做起點(diǎn)是步數(shù)分步是每次重復(fù)都加的變量既要清除又要毫秒除以幀就是每走一步的時(shí)間庫緩動(dòng)動(dòng)畫緩動(dòng)函數(shù)速查表庫搜索引入一個(gè)網(wǎng)站 (個(gè)人筆記)在給在線簡歷添加js特效過程中遇到的問題及解決方法 二 github預(yù)覽 點(diǎn)擊菜單滾動(dòng)動(dòng)畫首頁 let top = element.of...
閱讀 4240·2021-09-26 10:17
閱讀 883·2021-09-22 15:02
閱讀 3470·2021-09-06 15:00
閱讀 1064·2021-07-25 16:52
閱讀 2747·2019-08-29 16:16
閱讀 2523·2019-08-29 13:25
閱讀 1598·2019-08-26 13:51
閱讀 2194·2019-08-26 10:58