2021SC@SDUSC山东大学软件学院软件工程应用与实践——claygl(源代码分析5)

2021SC@SDUSC

目录

一.clay.animation.TrackClip类概述

二.clay.animation.TrackClip类的作用

三.clay.animation.TrackClip类源码分析

1.new TrackClip(opts opt)

2.additiveBlend(clip1, clip2)

3.addTrack(track)

4.blend1D(clip1, clip2, w)

5.blend2D(clip1, clip2, clip3, f, g)

6.copy(clip)

7.pause()

8.resume()

9.removeTarck(track)

10.setEasing(easing)

11.setLoop(loop)

12.setTime(time) → {string}

13.step(time) → {string}

14.subtractiveBlend(clip1, clip2)

15.getSubClip(startTime, endTime, isLoop) → {clay.animation.TrackClip}


一.clay.animation.TrackClip类概述

    clay.animation.TrackClip继承自clay.animation.Clip,是剪辑Clip的动画轨迹形式TrackClip,可为动画添加轨迹剪辑。

二.clay.animation.TrackClip类的作用

    TrackClip类能够进行创建一个动画的轨迹剪辑,克隆轨迹剪辑,暂停轨迹剪辑的播放,恢复二维剪辑的播放,设置轨迹剪辑的缓动效果,设置轨迹剪辑的循环次数,设置轨迹剪辑的播放时间,截取轨道剪辑的子剪辑,进行两个蒙版剪辑的加减法混合添加,轨道剪辑的一维和二维蒙版剪辑添加以及插入轨迹剪辑等操作。

三.clay.animation.TrackClip类源码分析

1.new TrackClip(opts opt)

    该函数为TrackClip类的构造函数,其参数opts,类型为object(对象),参数opts对象内含有的成员变量如下:

变量名变量类型是否必须构造后默认值描述
namestring''剪辑的名称
targetobjectopts.target目标对象
lifenumber1000动画的生命时长
delaynumber0剪辑的时长
gapnumber0剪辑的间隔
playbackRationumber1播放的速度
loopboolean | numberfalseboolean表示是否循环,number表示循环的次数
easingstring | function缓动效果
onframefunctionnoop动画的帧
onfinishfunctionnoop剪辑结束
onrestartfunctionnoop剪辑开始
tracksArray.<clay.animation.SamplerTrack>[]空数组帧轨迹动画

其源码如下:

var TrackClip = function (opts) {
    opts = opts || {};
    Clip.call(this, opts);
    /**
     *
     * @type {clay.animation.SamplerTrack[]}
     */
    this.tracks = opts.tracks || [];
    this.calcLifeFromTracks();
}

    从源码中可以看到,TrackClip共有1个成员变量,在构造函数中接收一个object类型的参数,该参数内共有11个成员变量。TrackClip类继承Clip类,当将opts赋给构造函数后,首先调用父类Clip的构造函数,使用父类Clip的构造方法获得成员变量和值,然后将opts内的其它成员变量的值赋给TrackClip对象,若其中一些成员变量为空,则使用Clip的默认值。

2.additiveBlend(clip1, clip2)

    该函数能够将两个蒙版剪辑的混合添加到本剪辑中,实现两个剪辑的合并添加效果。

    参数有clip1和clip2,分别表示需要合并的两个蒙版剪辑,类型为clay.animation.TrackClip

    其源代码为:

TrackClip.prototype.additiveBlend = function (clip1, clip2) {
    for (var i = 0; i < this.tracks.length; i++) {
        var c1 = clip1.tracks[i];
        var c2 = clip2.tracks[i];
        var tClip = this.tracks[i];
        tClip.additiveBlend(c1, c2);
    }
}

    从源代码可以看出,该函数对本剪辑的track数组进行遍历,同时,将两个参数的蒙版剪辑混合添加到本剪辑中,从而实现本剪辑的蒙版效果。

3.addTrack(track)

    该函数能够将一个剪辑添加到本剪辑中,实现剪辑的添加。

    参数为track,表示需要添加的剪辑,类型为clay.animation.SamplerTrack。

    其源代码为:

TrackClip.prototype.addTrack = function (track) {
    this.tracks.push(track);
    this.calcLifeFromTracks();
}

    从源代码可以看出,该函数将形式参数track剪辑添加到本剪辑的tracks数组中,然后调用calcLifeFromTracks()方法,其代码如下:

TrackClip.prototype.calcLifeFromTracks = function () {
    this.life = 0;
    for (var i = 0; i < this.tracks.length; i++) {
        this.life = Math.max(this.life, this.tracks[i].getMaxTime());
    }
}

    该方法对对本剪辑的tracks数组的长度进行遍历,获取tracks数组中每一帧中的最大时间,并把最大时间赋值给本对象的life成员变量,从而使本对象的时长随着剪辑的添加而改变,最终实现剪辑的添加。

4.blend1D(clip1, clip2, w)

    该函数的作用是对两个蒙版剪辑进行一维合并,添加到本剪辑中。

    参数有clip1和clip2,分别表示两个蒙版剪辑,参数类型为clay.animation.TrackClip,以及w位置,类型为number

    其源代码如下:

TrackClip.prototype.blend1D = function (clip1, clip2, w) {
    for (var i = 0; i < this.tracks.length; i++) {
        var c1 = clip1.tracks[i];
        var c2 = clip2.tracks[i];
        var tClip = this.tracks[i];
        tClip.blend1D(c1, c2, w);
    }
}

    从源代码可以看出,该函数遍历本对象的tracks数组,为其中的每一帧添加clip1和clip2蒙版剪辑的每一帧,通过调用blend1D函数进行实现,从而实现蒙版剪辑的合并和添加到本剪辑的效果,其中w指定位置。

5.blend2D(clip1, clip2, clip3, f, g)

    该函数的作用是对三个蒙版剪辑进行二维合并,添加到本剪辑中。

    参数有clip1,clip2和clip3,分别表示三个蒙版剪辑,参数类型为clay.animation.TrackClip,以及f和g位置,类型为number

    其源代码如下:

TrackClip.prototype.blend2D = function (clip1, clip2, clip3, f, g) {
    for (var i = 0; i < this.tracks.length; i++) {
        var c1 = clip1.tracks[i];
        var c2 = clip2.tracks[i];
        var c3 = clip3.tracks[i];
        var tClip = this.tracks[i];
        tClip.blend2D(c1, c2, c3, f, g);
    }
}

    从源代码可以看出,该函数遍历本对象的tracks数组,为其中的每一帧添加clip1,clip2和clip3蒙版剪辑的每一帧,通过调用blend2D函数进行实现,从而实现蒙版剪辑的合并和添加到本剪辑的效果,其中f和g指定二维位置。

6.copy(clip)

    该函数的作用是复制某一剪辑的位置,缩放和旋转,实现剪辑的行为复制。

    参数为clip,表示需要复制的剪辑,其类型为clay.animation.TrackClip

    其源代码为:

TrackClip.prototype.copy = function (clip) {
    for (var i = 0; i < this.tracks.length; i++) {
        var sTrack = clip.tracks[i];
        var tTrack = this.tracks[i];
        vec3.copy(tTrack.position, sTrack.position);
        vec3.copy(tTrack.scale, sTrack.scale);
        quat.copy(tTrack.rotation, sTrack.rotation);
    }
}

    从源代码中可以看出,该函数遍历本对象的tracks数组中的所有帧,同时遍历参数clip的所有帧,将clip中所有帧的position,scale和rotation,即位置,缩放和旋转复制到本对象的position,scale和rotation中,从而实现剪辑的复制。

7.pause()

    该函数能够暂停剪辑,从而实现剪辑的暂停,继承自clip类。

    无参数。

    其源代码为:

    pause: function () {
        this._paused = true;
    }

    从源代码可以看出,该函数将本对象的_paused设置为true,从而实现剪辑的暂停。

8.resume()

    该函数能够恢复剪辑,从而实现剪辑的恢复,继承自clip。

    无参数。

    其源代码为:

    resume: function () {
        this._paused = false;
    }

    从源代码中可以看出,该函数将本对象的_paused设置为false,从而实现剪辑的恢复

9.removeTarck(track)

    该函数能够清除某一个剪辑。

    参数为track,表示需要清除的部分剪辑,类型为clay.animation.SamplerTrack

    其源代码为:

TrackClip.prototype.removeTarck = function (track) {
    var idx = this.tracks.indexOf(track);
    if (idx >= 0) {
        this.tracks.splice(idx, 1);
    }
}

    从源代码可以看出,该函数获取参数track剪辑在本剪辑中的索引,如果索引大于等于0,即索引存在,则调用splice函数对本剪辑进行切分,从而清除特定的剪辑

10.setEasing(easing)

    该函数的作用是设置剪辑的缓动效果,继承自父类。

    参数为easing,表示缓动效果,类型为string或function。

     其源代码为:

    setEasing: function (easing) {
        if (typeof(easing) === 'string') {
            easing = Easing[easing];
        }
        this.easing = easing;
    }

    从源代码分析可得,该函数首先判断接收的形式参数easing类型是否为string,若是,则将内置的Easing数组中名为easing的方法赋给本对象的easing,若不是,则将easing方法赋给本对象的easing,从而实现内置或自定义的缓动效果。

11.setLoop(loop)

    该函数的作用是设置是否循环以及循环的时间,继承自父类。

    参数为loop,类型为number,表示循环的时间,类型为boolean,表示是否循环,为真则无限循环。

    其源代码为:

    setLoop: function (loop) {
        this._loop = loop;
        if (loop) {
            if (typeof loop === 'number') {
                this._loopRemained = loop;
            }
            else {
                this._loopRemained = Infinity;
            }
        }
    }

    从源代码中可以看出,首先将形参loop赋给本对象的_loop,如果loop为真,判断类型,若为number,则将loop赋值给本对象的_loopRemained,表示循环loop次,若为boolean则赋值Infinity,表示循环无数次。若loop为假,则不循环。

12.setTime(time) → {string}

   该函数能够在指定的时间开始动画,继承自父类。

    其参数为time,表示开始的时间,类型为number。

    其源代码为:

    setTime: function (time) {
        return this.step(time + this._startTime);
    }

    由源代码可知,该函数调用step()函数,step()函数如下所述,能够在指定时间播放剪辑,因此,setTime()将time和本对象的_startTime相加,赋给函数step(),表示设置当前播放剪辑的时间。

13.step(time) → {string}

    该函数能够在指定时间内添加一段剪辑,继承自父类。

    其参数为time,表示剪辑添加的时刻,类型为number

    其源代码为:

    step: function (time, deltaTime, silent) {
        if (!this._initialized) {
            this._startTime = time + this.delay;
            this._initialized = true;
        }
        if (this._currentTime != null) {
            deltaTime = time - this._currentTime;
        }
        this._currentTime = time;
        if (this._paused) {
            return 'paused';
        }
        if (time < this._startTime) {
            return;
        }
        // PENDIGN Sync ?
        this._elapse(time, deltaTime);
        var percent = Math.min(this._elapsedTime / this.life, 1);
        if (percent < 0) {
            return;
        }
        var schedule;
        if (this.easing) {
            schedule = this.easing(percent);
        }
        else {
            schedule = percent;
        }
        if (!silent) {
            this.fire('frame', schedule);
        }
        if (percent === 1) {
            if (this._loop && this._loopRemained > 0) {
                this._restartInLoop(time);
                this._loopRemained--;
                return 'restart';
            }
            else {
                // Mark this clip to be deleted
                // In the animation.update
                this._needsRemove = true;
                return 'finish';
            }
        }
        else {
            return null;
        }
    }

  由其源代码可知,当执行step()函数后,首先会判断是否初始化,若未初始化,即_initialized为false,则进行初始化,将本对象的_startTime设置为本对象的delay时间加上输入的时间time,并将_initialized设置为true,表示已经初始化。

    然后,判断本对象的_currentTime是否不为空,若不为空则将deltaTime的值设置为输入的时间time减去本对象的_currentTime的值。

    然后设置当前的时间_currentTime为输入的时间time。如果_paused为真,则返回‘pause’,表示本剪辑已暂停,若为假,则继续判断输入的时间time是否小于剪辑开始时间_starttime,若为真,表示输入不正确,返回,若为假,继续进行后面的操作。

    接下来执行elapse()函数,参数为输入的时间time和相减后的时间deltaTime,其代码为:

    _elapse: function (time, deltaTime) {
            this._elapsedTime += deltaTime * this.playbackRate;
        }

    该函数能够设置本对象的成员变量_elapsedTime的值增加deltaTime与本对象的成员变量playbackRate的乘积,表示为总剪辑添加一段时间的剪辑,这一段时间的剪辑的播放速度即为playbackRate的值。

    因此,向剪辑中添加一段时间后,将_elapsedTime与life的商和1对比,取小的值,并赋给创建的局部变量percent,如果percent小于0则返回,表示当前剪辑的百分比,百分比必须为正数。

    然后,创建一个局部变量schedule,如果easing缓动效果存在,将目前剪辑部分(当前百分比)的缓动效果赋值给schedule,否则将百分比赋给schedule,表示当前执行的动画,是缓动效果还是播放动画。

    下面,如果silent假,则执行fire()函数,其源代码为:

fire: function (eventType, arg) {
        var eventName = 'on' + eventType;
        if (this[eventName]) {
            this[eventName](this.target, arg);
        }
    }

    该函数将eventType参数前加上on字符串,形成一个局部变量eventName,如果本对象有eventName成员变量,则在eventName成员变量中加入本对象的target以及arg参数,而传入为frame,eventType为onframe,arg为schedule,表示onframe中添加键target和值schedule,实现剪辑中添加相应的行为,表示添加剪辑的帧。

    最后,判断percent百分比是否为100%,不是则返回null,是的话继续判断是否循环以及剩余循环次数是否为大于0,是的话执行_restartInLoop函数,其代码为

 _restartInLoop: function (time) {
        this._startTime = time + this.gap;
        this._elapsedTime = 0;
    }

    该函数接收time参数,将开始时间设置为time和本对象的gap相加,并把剪辑时间_elapsedTime设置为0,表示重新执行该剪辑。因此,结合而看,如果仍有循环次数,则重新执行剪辑,并将剩余的循环次数减1,返回‘restart’,表示重新开启,若循环次数已经完成,则设置成员变量_needsRemove为true,表示需要执行的剪辑已经完成,并返回‘finish’,表示完成,从而结束该函数。 可见,step()函数可在指定的时间上播放一段剪辑。

14.subtractiveBlend(clip1, clip2)

    该函数对两个蒙版剪辑进行减法混合,并添加到本剪辑中。

    参数有clip1和clip2,分别表示进行减法混合的两个剪辑,类型为clay.animation.TrackClip

    其源代码为:

TrackClip.prototype.subtractiveBlend = function (clip1, clip2) {
    for (var i = 0; i < this.tracks.length; i++) {
        var c1 = clip1.tracks[i];
        var c2 = clip2.tracks[i];
        var tClip = this.tracks[i];
        tClip.subtractiveBlend(c1, c2);
    }
}

    从源代码可以看出,该函数遍历本对象的tracks数组,为其中的每一帧添加clip1和clip2蒙版剪辑减法混合的每一帧,通过调用subtractiveBlend函数进行实现,从而实现蒙版剪辑的减法合并和添加到本剪辑的效果。

15.getSubClip(startTime, endTime, isLoop) → {clay.animation.TrackClip}

    该函数的作用是获取本剪辑的子剪辑,即截取本剪辑的一部分。

    参数为startTime,endTime,isLoop,分别表示开始时间,结束时间,是否循环,类型分别为number,number,boolean

    其源代码为:

TrackClip.prototype.getSubClip = function (startTime, endTime, isLoop) {
    var subClip = new TrackClip({
        name: this.name
    });
    for (var i = 0; i < this.tracks.length; i++) {
        var subTrack = this.tracks[i].getSubTrack(startTime, endTime);
        subClip.addTrack(subTrack);
    }
    if (isLoop !== undefined) {
        subClip.setLoop(isLoop);
    }
    subClip.life = endTime - startTime;
    return subClip;
}

    从该函数可以看出,首先创建一个与本剪辑同名的空剪辑,对本剪辑的tracks数组中的每一帧进行遍历,获取指定startTime和endTime之间的剪辑进行提取,并添加到新建的空剪辑subClip中,判断isLoop参数,若为真则设置subClip为无限循环,否则不循环,设置subClip的生命时长为endTime和startTime的差值,从而截取出本剪辑的子剪辑,并返回子剪辑,最终实现子剪辑的提取。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值