Laya Tween

游戏开发中的缓动动画是提升游戏UI体验的重要因素之一,比如对话框弹出和关闭、按钮动效出现于消失、道具飞入背包等,可以使用LayaAir引擎提供的Tween缓动类与Ease类实现。LayaAir引擎的Tween类与Ease类结合使用,能基本满足游戏开发的缓动效果。

  • Tween缓动类用来实现目标对象属性的缓动,比如目标对象的x轴或y轴的缓动距离等目标值的设置,以及缓动开始、停止、清理等设置。
  • Ease类用来定义大量的缓动函数以便实现Tween动画的具体缓动效果

Tween

结构描述
Packagelaya.utils.Tween
ClassLaya.Tween

例如:水平来回移动图片

4933701-3184cf96b292a136.png
水平来回移动图片
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(){
        //从起始点移动到中心点
        //Laya.Tween.to(this.sprite, {x:Laya.stage.width>>1}, 3000);
        
        //从中心点移动到起始点
        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;
    }
}
//启动
new Test();
属性描述
repeat:number = 1重播次数,默认为1,为0则表示无限循环播放。
update:Handler更新回调,缓动数值发生变化时,回调变化的值。
存取器描述
set progress(v:number):void设置当前执行比例
方法描述
clear():void停止并清理当前缓动
complete():void立即结束缓动并到终点
from():Tweenprops属性缓动到当前状态
pause():void暂停缓动,可以通过resumerestart重新开始。
recover():void回收到对象池
restart():void重新开始暂停的缓动
resume():void恢复暂停的缓动
setStartTime(startTime:number):void设置开始时间
to():Tween缓动对象的props属性到目标值

静态属性

缓动类Tween提供了较多的方法,常用的是from()和to()方法,这两个方法的参数设置完全相同,但效果有所不同,from()是从缓动目标点向初始位置产生运动,即从缓动目标位置来看,to()是从初始位置向缓动目标位置产生运动,即到缓动目标位置去。

//从`props`属性缓动到当前状态
Laya.Tween.from(
  target:any, 
  props:any, 
  duration:number, 
  ease?:Function, 
  complete?:Handler, 
  delay?:number, 
  coverBefore?:boolean, 
  autoRecover?:boolean
):Tween

// 缓动对象的props属性到目标值
Laya.Tween.to(
  target:any, 
  props:any, 
  duration:number, 
  ease?:Function, 
  complete?:Handler, 
  delay?:number, 
  coverBefore?:boolean, 
  autoRecover?:boolean
):Tween
参数描述
target:any目标对象,即将更改属性值的对象。
props:any目标对象变化的属性值
duration:number耗费的毫秒时间
ease:Function = null缓动类型,默认为匀速运动。
complete:Handler = null结束回调函数
delay:number = 0延迟执行毫秒时间
coverBefore:boolean = false是否覆盖之前的缓动
autoRecover:boolean = true是否自动回收,默认为true表示缓动结束后自动回收到对象池。

props属性

props是目标对象改变产生缓动效果的属性,可以影响缓动效果的运动轨迹。目标对象的公共属性都可以进行设置,比如常见的坐标位置、透明度、旋转、轴心点、宽高等其它属性。

ease 缓动函数

Ease类定义了大量的缓动函数,以便实现Tween动画的具体缓动效果,即Tween缓动动画的具体动画类型由Ease进行指定。

缓动函数描述
Laya.Ease.backIn开始时往后运动然后反向朝目标移动
Laya.Ease.backInOut开始运动时是向后跟踪,再倒转方向并朝目标移动,稍微过冲目标再次倒转方向,回来朝目标移动。
Laya.Ease.backOut开始运动时朝目标移动,稍微过冲再倒转方向回来朝着目标。
Laya.Ease.bounceIn以零速率开始运动,执行时加速。类似球向地板跌落又弹起到逐渐减小的回弹运动。

例如:逐字缓动掉落效果


4933701-37eb1516abe38a8f.png
逐字缓动掉落
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 width = 400;
        //分解字节串为字符并为其创建文本对象
        let str = "JunChow";
        let len = str.length;
        for(let i=0; i<len; i++){
            //为单个字符创建文本
            let txt = this.createText(str.charAt(i));
            //设置单个字符的坐标位置
            let x = (Laya.stage.width - width >> 1) +  (width / len * i);
            txt.x = x;
            //增加动效
            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;
    }
}
//启动
new Test();

例如:加载图片并设置缓动效果

4933701-f6fc46694ab259ed.png
缓动
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){
            //创建并加载图片到舞台显示
            let img = new Laya.Image();
            img.loadImage(url);
            Laya.stage.addChild(img);
            //缓动对象的props属性到目标值
            Laya.Tween.to(
                //缓动对象
                img, 
                //变化属性目标值
                {x:Laya.stage.width - img.texture.width>>1, y:Laya.stage.height-img.texture.height>>1}, 
                //花费的毫秒时间
                3000, 
                //缓动类型
                Laya.Ease.elasticOut, 
                //结束后回调函数
                Laya.Handler.create(this, function(){
                    //创建文本
                    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);
                }), 
                //延迟执行毫秒时间
                1000
            )
        },[url]));
    }
}
//启动
new Test();

封装类库

使用TypeScript封装动画效果类库

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

    }
    /**
     * 类似苹果系统上图标上下抖动的效果
     * @param target {Sprite} 抖动对象
     * @param initY {number} 抖动对象初始Y轴坐标位置
     * @param callback {Function} 抖动完毕后回调函数
     * @param thisObj {any} 回调函数this对象
     */
    shake(target, initY, callback, thisObj){
        //抖动频率[时间, 移动距离]
        let data = [[20, 300], [15, 300], [10, 300], [5, 300]];
        let index = 0;
        //执行抖动
        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();
                    }));
                }));
            }
        }
    }
    /**
     * 向上移动淡出效果
     * @param target {Sprite} 淡出对象
     * @param duration {number} 淡出时长单位毫秒
     * @param ease {Function} 淡出函数
     * @param callback {Function} 淡出完成回调函数
     * @param thisObj {any} 回调函数this对象
     * @param args {Array} 回调传参
     */
    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));
        }
    }
    /**
     * 文本数字增减渐变效果
     * @param begin {number} 开始的数值
     * @param end {number} 渐变到的数值
     * @param callback {Function} 淡出完成回调函数
     * @param thisObj {any} 回调函数的this对象
     */
    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} 目标节点对象
     * @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)));
    }
    /**
     * 停止动画 节点归位
     * 停止动画后容器位置初始化到原始位置,避免可能出现位置改变引起的bug。
     * @param target {Sprite} 目标节点
     * @param x {number} X轴坐标位置
     * @param y {number} Y轴坐标位置
     */
    clear(target, x=null, y=null){
        Laya.Tween.clearAll(target);
        if(x!==null && y!==null){
            target.pos(x, y);
        }
    }
    /**
     * 点击放大缩小
     * @param target {Sprite} 目标节点
     * @param fix 若中心点不是锚点则需修改位置
     */
    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;
                }
            }));
        }));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值