Laya Tween

游戲開發(fā)中的緩動(dòng)動(dòng)畫是提升游戲UI體驗(yàn)的重要因素之一,比如對(duì)話框彈出和關(guān)閉、按鈕動(dòng)效出現(xiàn)于消失、道具飛入背包等,可以使用LayaAir引擎提供的Tween緩動(dòng)類與Ease類實(shí)現(xiàn)。LayaAir引擎的Tween類與Ease類結(jié)合使用,能基本滿足游戲開發(fā)的緩動(dòng)效果。

  • Tween緩動(dòng)類用來實(shí)現(xiàn)目標(biāo)對(duì)象屬性的緩動(dòng),比如目標(biāo)對(duì)象的x軸或y軸的緩動(dòng)距離等目標(biāo)值的設(shè)置,以及緩動(dòng)開始、停止、清理等設(shè)置。
  • Ease類用來定義大量的緩動(dòng)函數(shù)以便實(shí)現(xiàn)Tween動(dòng)畫的具體緩動(dòng)效果

Tween

結(jié)構(gòu) 描述
Package laya.utils.Tween
Class Laya.Tween

例如:水平來回移動(dòng)圖片

水平來回移動(dòng)圖片
class Test {
    constructor() {
        Laya.init(Laya.Browser.clientWidth, Laya.Browser.clientHeight, Laya.WebGL);
        this.initStage();
        this.run();
    }
    initStage(){
        Laya.stage.alignH = Laya.Stage.ALIGN_CENTER;
        Laya.stage.alignV = Laya.Stage.ALIGN_MIDDLE;
        Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
        Laya.stage.bgColor = "#000000";
    }
    run(){
        this.drawLine();
        this.createSprite("res/image/bomb.png");
        this.tweenTo();
    }
    tweenTo(){
        //從起始點(diǎn)移動(dòng)到中心點(diǎn)
        //Laya.Tween.to(this.sprite, {x:Laya.stage.width>>1}, 3000);
        
        //從中心點(diǎn)移動(dòng)到起始點(diǎn)
        this.sprite.x = 0;
        this.sprite.y = Laya.stage.height>>1;
        Laya.Tween.from(this.sprite, {x:Laya.stage.width>>1, y:Laya.stage.height>>1}, 3000);
    }
    drawLine(){
        let fromX = Laya.stage.width >> 1;
        let fromY = 0;
        let toX = Laya.stage.width >> 1;
        let toY = Laya.stage.height;
        let lineColor = "#111111";
        let lineWidth = 1;
        Laya.stage.graphics.drawLine(fromX, fromY, toX, toY, lineColor, lineWidth);
        
        fromX = 0;
        fromY = Laya.stage.height >> 1;
        toX = Laya.stage.width;
        toY = Laya.stage.height >> 1;
        Laya.stage.graphics.drawLine(fromX, fromY, toX, toY, lineColor, lineWidth);
    }
    createSprite(skin){
        this.sprite = new Laya.Sprite();
        this.sprite.loadImage(skin, Laya.Handler.create(this, function(){
            let texture = Laya.loader.getRes(skin);
            this.sprite.pivot(texture.width>>1, texture.height>>1);
            this.sprite.pos(texture.width>>1, Laya.stage.height>>1);
        }));
        Laya.stage.addChild(this.sprite);
        return this.sprite;
    }
}
//啟動(dòng)
new Test();
屬性 描述
repeat:number = 1 重播次數(shù),默認(rèn)為1,為0則表示無限循環(huán)播放。
update:Handler 更新回調(diào),緩動(dòng)數(shù)值發(fā)生變化時(shí),回調(diào)變化的值。
存取器 描述
set progress(v:number):void 設(shè)置當(dāng)前執(zhí)行比例
方法 描述
clear():void 停止并清理當(dāng)前緩動(dòng)
complete():void 立即結(jié)束緩動(dòng)并到終點(diǎn)
from():Tween props屬性緩動(dòng)到當(dāng)前狀態(tài)
pause():void 暫停緩動(dòng),可以通過resumerestart重新開始。
recover():void 回收到對(duì)象池
restart():void 重新開始暫停的緩動(dòng)
resume():void 恢復(fù)暫停的緩動(dòng)
setStartTime(startTime:number):void 設(shè)置開始時(shí)間
to():Tween 緩動(dòng)對(duì)象的props屬性到目標(biāo)值

靜態(tài)屬性

緩動(dòng)類Tween提供了較多的方法,常用的是from()和to()方法,這兩個(gè)方法的參數(shù)設(shè)置完全相同,但效果有所不同,from()是從緩動(dòng)目標(biāo)點(diǎn)向初始位置產(chǎn)生運(yùn)動(dòng),即從緩動(dòng)目標(biāo)位置來看,to()是從初始位置向緩動(dòng)目標(biāo)位置產(chǎn)生運(yùn)動(dòng),即到緩動(dòng)目標(biāo)位置去。

//從`props`屬性緩動(dòng)到當(dāng)前狀態(tài)
Laya.Tween.from(
  target:any, 
  props:any, 
  duration:number, 
  ease?:Function, 
  complete?:Handler, 
  delay?:number, 
  coverBefore?:boolean, 
  autoRecover?:boolean
):Tween

// 緩動(dòng)對(duì)象的props屬性到目標(biāo)值
Laya.Tween.to(
  target:any, 
  props:any, 
  duration:number, 
  ease?:Function, 
  complete?:Handler, 
  delay?:number, 
  coverBefore?:boolean, 
  autoRecover?:boolean
):Tween
參數(shù) 描述
target:any 目標(biāo)對(duì)象,即將更改屬性值的對(duì)象。
props:any 目標(biāo)對(duì)象變化的屬性值
duration:number 耗費(fèi)的毫秒時(shí)間
ease:Function = null 緩動(dòng)類型,默認(rèn)為勻速運(yùn)動(dòng)。
complete:Handler = null 結(jié)束回調(diào)函數(shù)
delay:number = 0 延遲執(zhí)行毫秒時(shí)間
coverBefore:boolean = false 是否覆蓋之前的緩動(dòng)
autoRecover:boolean = true 是否自動(dòng)回收,默認(rèn)為true表示緩動(dòng)結(jié)束后自動(dòng)回收到對(duì)象池。

props屬性

props是目標(biāo)對(duì)象改變產(chǎn)生緩動(dòng)效果的屬性,可以影響緩動(dòng)效果的運(yùn)動(dòng)軌跡。目標(biāo)對(duì)象的公共屬性都可以進(jìn)行設(shè)置,比如常見的坐標(biāo)位置、透明度、旋轉(zhuǎn)、軸心點(diǎn)、寬高等其它屬性。

ease 緩動(dòng)函數(shù)

Ease類定義了大量的緩動(dòng)函數(shù),以便實(shí)現(xiàn)Tween動(dòng)畫的具體緩動(dòng)效果,即Tween緩動(dòng)動(dòng)畫的具體動(dòng)畫類型由Ease進(jìn)行指定。

緩動(dòng)函數(shù) 描述
Laya.Ease.backIn 開始時(shí)往后運(yùn)動(dòng)然后反向朝目標(biāo)移動(dòng)
Laya.Ease.backInOut 開始運(yùn)動(dòng)時(shí)是向后跟蹤,再倒轉(zhuǎn)方向并朝目標(biāo)移動(dòng),稍微過沖目標(biāo)再次倒轉(zhuǎn)方向,回來朝目標(biāo)移動(dòng)。
Laya.Ease.backOut 開始運(yùn)動(dòng)時(shí)朝目標(biāo)移動(dòng),稍微過沖再倒轉(zhuǎn)方向回來朝著目標(biāo)。
Laya.Ease.bounceIn 以零速率開始運(yùn)動(dòng),執(zhí)行時(shí)加速。類似球向地板跌落又彈起到逐漸減小的回彈運(yùn)動(dòng)。

例如:逐字緩動(dòng)掉落效果


逐字緩動(dòng)掉落
class Test {
    constructor() {
        Laya.init(Laya.Browser.clientWidth, Laya.Browser.clientHeight, Laya.WebGL);
        this.initStage();
        this.run();
    }
    initStage(){
        Laya.stage.alignH = Laya.Stage.ALIGN_CENTER;
        Laya.stage.alignV = Laya.Stage.ALIGN_MIDDLE;
        Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
        Laya.stage.bgColor = "#000000";
    }
    run(){
        //文字區(qū)域?qū)挾?        let width = 400;
        //分解字節(jié)串為字符并為其創(chuàng)建文本對(duì)象
        let str = "JunChow";
        let len = str.length;
        for(let i=0; i<len; i++){
            //為單個(gè)字符創(chuàng)建文本
            let txt = this.createText(str.charAt(i));
            //設(shè)置單個(gè)字符的坐標(biāo)位置
            let x = (Laya.stage.width - width >> 1) +  (width / len * i);
            txt.x = x;
            //增加動(dòng)效
            let y = Laya.stage.height >> 1;
            Laya.Tween.to(txt, {y:y}, 1000, Laya.Ease.elasticOut, null, i*1000);
        }
    }
    createText(char){
        let txt = new Laya.Text();
        txt.text = char;
        txt.font = "Impact";
        txt.fontSize = 100;
        txt.color = "#FFFFFF";
        Laya.stage.addChild(txt);
        return txt;
    }
}
//啟動(dòng)
new Test();

例如:加載圖片并設(shè)置緩動(dòng)效果

緩動(dòng)
class Test {
    constructor() {
        Laya.init(Laya.Browser.clientWidth, Laya.Browser.clientHeight, Laya.WebGL);
        this.initStage();
        this.run();
    }
    initStage(){
        Laya.stage.alignH = Laya.Stage.ALIGN_CENTER;
        Laya.stage.alignV = Laya.Stage.ALIGN_MIDDLE;
        Laya.stage.scaleMode = Laya.Stage.SCALE_SHOWALL;
        Laya.stage.bgColor = "#000000";
    }
    run(){
        //加載圖片資源
        let url = "res/image/npc.png";
        Laya.loader.load(url, Laya.Handler.create(this, function(url){
            //創(chuàng)建并加載圖片到舞臺(tái)顯示
            let img = new Laya.Image();
            img.loadImage(url);
            Laya.stage.addChild(img);
            //緩動(dòng)對(duì)象的props屬性到目標(biāo)值
            Laya.Tween.to(
                //緩動(dòng)對(duì)象
                img, 
                //變化屬性目標(biāo)值
                {x:Laya.stage.width - img.texture.width>>1, y:Laya.stage.height-img.texture.height>>1}, 
                //花費(fèi)的毫秒時(shí)間
                3000, 
                //緩動(dòng)類型
                Laya.Ease.elasticOut, 
                //結(jié)束后回調(diào)函數(shù)
                Laya.Handler.create(this, function(){
                    //創(chuàng)建文本
                    let txt = new Laya.Text();
                    txt.font = "Impact";
                    txt.fontSize = 80;
                    txt.color = "#FFFF00";
                    txt.stroke = 1;
                    txt.strokeColor = "#EEEEEE";
                    txt.text = "Game Start";
                    txt.pos(Laya.stage.width-txt.width>>1, Laya.stage.height-txt.height>>1);
                    Laya.stage.addChild(txt);
                }), 
                //延遲執(zhí)行毫秒時(shí)間
                1000
            )
        },[url]));
    }
}
//啟動(dòng)
new Test();

封裝類庫

使用TypeScript封裝動(dòng)畫效果類庫

export default class Effect{
    private static _instance:Effect;
    public static getInstance():Effect{
        if(!this._instance){
            this._instance = new Effect();
        }
        return this._instance;
    }
    private _constructor(){

    }
    /**
     * 類似蘋果系統(tǒng)上圖標(biāo)上下抖動(dòng)的效果
     * @param target {Sprite} 抖動(dòng)對(duì)象
     * @param initY {number} 抖動(dòng)對(duì)象初始Y軸坐標(biāo)位置
     * @param callback {Function} 抖動(dòng)完畢后回調(diào)函數(shù)
     * @param thisObj {any} 回調(diào)函數(shù)this對(duì)象
     */
    shake(target, initY, callback, thisObj){
        //抖動(dòng)頻率[時(shí)間, 移動(dòng)距離]
        let data = [[20, 300], [15, 300], [10, 300], [5, 300]];
        let index = 0;
        //執(zhí)行抖動(dòng)
        toShake();
        function toShake(){
            if(index >= data.length){
                callback && callback.apply(thisObj, []);
            }else{
                let prop = {"y":initY - data[index][0]};
                let duration = data[index][1];
                let ease = null;
                Laya.Tween.to(target, prop, duration, ease, Laya.Handler.create(null, ()=>{
                    prop = {"y": initY};
                    Laya.Tween.to(target, prop, duration, ease, Laya.Handler.create(null, ()=>{
                        ++index;
                        toShake();
                    }));
                }));
            }
        }
    }
    /**
     * 向上移動(dòng)淡出效果
     * @param target {Sprite} 淡出對(duì)象
     * @param duration {number} 淡出時(shí)長(zhǎng)單位毫秒
     * @param ease {Function} 淡出函數(shù)
     * @param callback {Function} 淡出完成回調(diào)函數(shù)
     * @param thisObj {any} 回調(diào)函數(shù)this對(duì)象
     * @param args {Array} 回調(diào)傳參
     */
    flowout(target, duration=500, ease=null, callback=null, thisObj=null, args=null){
        let props = {y:target.y-150, alpha:0};
        if(callback){
            Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(thisObj, callback, args));
        }else{
            Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(target, target.removeSelf, args));
        }
    }
    /**
     * 文本數(shù)字增減漸變效果
     * @param begin {number} 開始的數(shù)值
     * @param end {number} 漸變到的數(shù)值
     * @param callback {Function} 淡出完成回調(diào)函數(shù)
     * @param thisObj {any} 回調(diào)函數(shù)的this對(duì)象
     */
    flownum(begin, end, callback, thisObj=null){
        let diff = Math.abs(end - begin);
        if(diff <= 0){
            return;
        }

        let cur = begin;
        let per = diff / (end - begin);
        
        let delay = 30;
        let timer = new Laya.Timer();
        timer.loop(delay, this, onLoop);
        function onLoop(){
            cur += per;
            --diff;
            if(diff < 0){
                timer.clearAll(this);
                timer = null;
            }else{
                callback && callback.apply(thisObj, [cur]);
            }
        }
    }
    /**
     * 閃爍
     * @param target {Sprite} 目標(biāo)節(jié)點(diǎn)對(duì)象
     * @param duration {number} 閃爍頻率
     */
    flicker(target, duration=700){
        target.alpha = 1;
        let props = {"alpha": 0};
        let ease = null;
        Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(null, function(){
            props = {"alpha": 1};
            Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(this, this.flicker, [target]));
        }.bind(this)));
    }
    /**
     * 停止動(dòng)畫 節(jié)點(diǎn)歸位
     * 停止動(dòng)畫后容器位置初始化到原始位置,避免可能出現(xiàn)位置改變引起的bug。
     * @param target {Sprite} 目標(biāo)節(jié)點(diǎn)
     * @param x {number} X軸坐標(biāo)位置
     * @param y {number} Y軸坐標(biāo)位置
     */
    clear(target, x=null, y=null){
        Laya.Tween.clearAll(target);
        if(x!==null && y!==null){
            target.pos(x, y);
        }
    }
    /**
     * 點(diǎn)擊放大縮小
     * @param target {Sprite} 目標(biāo)節(jié)點(diǎn)
     * @param fix 若中心點(diǎn)不是錨點(diǎn)則需修改位置
     */
    clickCubicInOut(target, fix=true){
        if(!target){
            return;
        }
        target.off(Laya.Event.MOUSE_DOWN, this, this.onCubicInOut);
        target.on(Laya.Event.MOUSE_DOWN, this, this.onCubicInOut, [target, fix]);
    }
    clearCubicInOut(target){
        if(!target){
            return;
        }
        target.off(Laya.Event.MOUSE_DOWN, this, this.onCubicInOut);
    }
    onCubicInOut(target, fix){
        if(target._aniButtonEffect){
            return;
        }
        target._aniButtonEffect = true;

        let x, y;
        if(fix){
            x = target.x;
            y = target.y;
        }else{
            x = target.x - ((target.width * 0.1) >> 1);
            y = target.y - ((target.height * 0.1) >> 1);
        }

        let scaleX = target.scaleX;
        let scaleY = target.scaleY;

        let props = {x:x, y:y, scaleX:scaleX * 1.1, scaleY:scaleY * 1.1};
        let duration = 100;
        let ease = null;
        Laya.Tween.to(target, props, duration, ease, Laya.Handler.create(this, ()=>{
            props.scaleX = scaleX;
            props.scaleY = scaleY;
            Laya.Tween.to(target, props, duration ,ease, Laya.Handler.create(this, ()=>{
                if(!target.destroyed){
                    target._aniButtonEffect = false;
                }
            }));
        }));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 【Android 動(dòng)畫】 動(dòng)畫分類補(bǔ)間動(dòng)畫(Tween動(dòng)畫)幀動(dòng)畫(Frame 動(dòng)畫)屬性動(dòng)畫(Property ...
    Rtia閱讀 6,380評(píng)論 1 38
  • 選擇qi:是表達(dá)式 標(biāo)簽選擇器 類選擇器 屬性選擇器 繼承屬性: color,font,text-align,li...
    love2013閱讀 2,430評(píng)論 0 11
  • 姓名:于幸欣 公司:揚(yáng)州市方圓建筑工程公司 【日精進(jìn)打卡第426天】 《六項(xiàng)精進(jìn)》誦讀5遍,共1920遍 《大學(xué)》...
    幸欣閱讀 101評(píng)論 0 0
  • 尊敬的各位家長(zhǎng)、親愛的老師同學(xué)們: 大家好!和著春的節(jié)拍,我們走進(jìn)操場(chǎng),走到陽光下,走向大自然,與春相伴,嬉...
    送柳音閱讀 533評(píng)論 0 0
  • 俗話說,日落而息,日出而作。早睡早起是順應(yīng)大自然規(guī)律的行為。 早睡早起身體好,這個(gè)道理誰都懂。但真正能夠落到實(shí)處還...
    國(guó)慶榮耀閱讀 286評(píng)論 0 0

友情鏈接更多精彩內(nèi)容