第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
  • js 實(shí)現(xiàn)幀動(dòng)畫原理

    查看全部
  • img src

    div background


    查看全部
  • 和上一個(gè)差別不大

    Animation.prototype.changeSrc = function (el,imgList) {

    var me = this;

    var len = imgList.length;

    var taskFn;

    var type;

    if (len) {

    taskFn = function (next, time) {

    var index = Math.min(time / me.interval | 0 , len-1);

    el.src = imageList[index]

    //結(jié)束時(shí)跳到下一個(gè)

    if (index === len - 1) {

    next();

    }

    }

    type = TASK_ASYNC;

    } else {

    //這里的next就是全局方法 next

    taskFn = next;

    type = TASK_SYNC;

    }

    return this._add(taskFn,type)

    }


    查看全部
  • 接下來就是具體用timeline的各個(gè)接口了。


    Animation.prototype.changePosition = function (el, positions, imageUrl) {

    var me = this;

    var len = position.length;

    var taskFn;

    var type;

    if (len) {

    taskFn = function (next, time) {

    //next, time 是._asyncTask的時(shí)候,傳過來的

    //如果傳入了圖片地址,那么修改el的背景圖

    if (imageUrl) {

    el.style.backgoundImage = 'url(' + imageUrl + ')';

    }

    //如果當(dāng)前已經(jīng)執(zhí)行的回調(diào)次數(shù) 還沒到最大值( 設(shè)定中的動(dòng)畫執(zhí)行次數(shù))

    //那么選擇當(dāng)前已經(jīng)執(zhí)行的回調(diào)次數(shù)作為索引(從0開始數(shù),所以可以直接用)

    // |0 既 Math.floor

    var index = Math.min(time / me.interval | 0, len - 1)

    //是這樣[ 200 332 , 333 33,]的格式

    var position = positions[index].split(' ')

    el.style.backgoundPosition = position[0]+'px' +' '+ position[1]+'px'

    //動(dòng)畫循環(huán)完成了的時(shí)候。

    if (index === len - 1) {

    next();

    }

    }

    type = TASK_ASYNC;

    } else {

    //這里的next就是全局方法 next

    taskFn = next;

    type = TASK_SYNC;

    }

    return this._add(taskFn,type)

    }

    function next(callback) {

    callback && callback()

    }

    //異步方法是這樣的:


    Animation.prototype._asyncTask = function(task) {

    //設(shè)置timeline里面的每幀都調(diào)用的回調(diào)函數(shù)onenterframe。

    var enterFrame = function (time) {

    var me = this;

    var taskFn = task.taskFn;

    //回調(diào)函數(shù)的設(shè)置

    var next = function () {

    //停止當(dāng)前的

    me.timeline.stop()

    //執(zhí)行下一個(gè)

    me._next()

    }

    taskFn(next,time)

    }

    this.timeline.onenterframe = enterFrame;

    //通過this.prototype.start傳進(jìn)來的參數(shù)Interval傳給timeline

    this.timeline.start(this.interval)

    }



    查看全部
  • 創(chuàng)建Timeline實(shí)例,然后用在異步方法里。

    function Animation() {

    this.timeline = new Timeline();

    //來自用戶設(shè)定的時(shí)間間隔

    this.interval = 0;

    }

    Animation.prototype._asyncTask = function(task) {

    //設(shè)置timeline里面的每幀都調(diào)用的回調(diào)函數(shù)onenterframe。

    var enterFrame = function (time) {

    var me = this;

    var taskFn = task.taskFn;

    //回調(diào)函數(shù)的設(shè)置

    var next = function () {

    //停止當(dāng)前的

    me.timeline.stop()

    //執(zhí)行下一個(gè)

    me._next()

    }

    taskFn(next,time)

    }

    this.timeline.onenterframe = enterFrame;

    //通過this.prototype.start傳進(jìn)來的參數(shù)Interval傳給timeline

    this.timeline.start(this.interval)

    }



    查看全部
  • 我的筆記代碼并不是完全和視頻一致的。

    這一小節(jié)有趣的一點(diǎn)是做了setInterval的迭代式形式。 nextTick函數(shù),其中有requestAnimationFrame(nextTick)。

    其中不斷更新記錄上一幀結(jié)束的時(shí)間lastTick。

    而這樣的話,lastTick- startTime /interval 大概就是過了多少幀了。

    代碼:

    function startTimeline(timeline, startTime) {

    //設(shè)置實(shí)例上的數(shù)據(jù),儲(chǔ)存用

    timeline.startTime = startTime

    //為用requestAnimationFrame加上的callback.interval

    nextTick.interval = timeline.interval


    //記錄最后一次回調(diào)的時(shí)間戳

    var lastTick = +new Date();

    nextTick();

    //+new Date() == new Date().getTime()


    //其實(shí)這是一個(gè)迭代形式的setInterval

    //每一幀都執(zhí)行的函數(shù)哦

    function nextTick() {

    //判斷如果時(shí)間到interval設(shè)定了的時(shí)間了,就執(zhí)行回調(diào),

    var now = +new Date();

    timeline.animationHandler = requestAnimationFrame(nextTick)

    if (now - lastTick >= timeline.interval) {

    timeline.onenterframe(now - startTime)

    //并且更新最后一次回調(diào)的時(shí)間

    lastTick = now;

    }

    }

    }


    類:?

    function Timeline(interval) {

    //當(dāng)前動(dòng)畫的狀態(tài)。

    this.state = STATE_INITIAL;

    //當(dāng)前動(dòng)畫進(jìn)行時(shí)間。

    this.startTime = 0;

    //每次回調(diào)的時(shí)間間隔。

    this.interval = DEFAULT_INTERVAL;

    //setTimeout的ID

    this.animationHandler = 0;

    //動(dòng)畫開始了多久,暫停的時(shí)候儲(chǔ)存留待再次開始

    this.dur = 0;

    }


    /**

    ?* 動(dòng)畫停止

    ?*/

    Timeline.prototype.stop = function (interval) {

    if (this.state !== STATE_START) {

    return

    }

    this.state = STATE_STOP;

    //如果動(dòng)畫已經(jīng)開始了,那么記錄一下已經(jīng)開始多久了。

    if (this.stateTime) {

    this.dur = +new Date() - this.startTime

    }

    cancelAnimationFrame(this.animationHandler)

    }

    /**

    * 重新播放動(dòng)畫

    */

    Timeline.prototype.restart = function (interval) {

    if (this.state !== STATE_START) {

    return

    }

    if (!this.dur || this.interval) {

    return

    }

    this.state = STATE_START

    //從停止那一刻算起,開始動(dòng)畫

    startTimeline(this, +new Date() - this.dur)

    }





    查看全部
  • 這里是定義具體執(zhí)行異步函數(shù)的方法。

    首先是處理window.requestAnimationFrame 和window.cancelAnimationFrame的兼容性問題。這里使用的自執(zhí)行函數(shù),通過 || 返回經(jīng)過類型轉(zhuǎn)換后為true的值。如果不支持這個(gè)方法,就用setTimeout,如果用setTimeout,默認(rèn)的時(shí)間間隔是1000/60毫秒。


    代碼:


    var DEFAULT_INTERVAL = 1000/60

    //requestAnimationFrame每17毫秒會(huì)刷新一次。

    var requestAnimationFrame = (function () {

    //瀏覽器兼容

    return window.requestAnimationFrame ||

    window.webketRequestAnimationFrame ||

    window.mozRequestAnimationFrame ||

    window.oRequestAnimationFrame ||

    //如果不支持,則用setTimeout ,默認(rèn)為 1000/60 毫秒后

    function (callback) {

    return window.setTimeout(callback(),callback.interval || DEFAULT_INTERVAL)

    }

    })()

    var cancelAnimationFrame = (function () {

    return window.cancelAnimationFrame ||

    window.webketCancelAnimationFrame ||

    window.mozCancelAnimationFrame ||

    window.oCancelAnimationFrame ||

    //如果不支持,則用setTimeout ,默認(rèn)為 1000/60 毫秒后

    function (id) {

    return window.clearTimeout(id)

    }

    })()

    接下來定義class。


    查看全部
  • 總結(jié):

    這一個(gè)小節(jié)的內(nèi)容,是把需要的任務(wù)方法添加到任務(wù)隊(duì)列,然后將任務(wù)按照不同類型處理。

    這里需要注意的是,每一個(gè)任務(wù)函數(shù)都要有處理callback的能力,這樣才能next;

    第一個(gè)任務(wù),將任務(wù)添加到任務(wù)隊(duì)列,是這樣做的。在使用這個(gè)庫的時(shí)候,demo會(huì)首先調(diào)用Animation.prototype.loadImage()這個(gè)方法。而在代碼中,并不是直接調(diào)用預(yù)加載loadImage()方法,而是把這個(gè)方法定義為對(duì)象中的一個(gè)屬性,并定義它的類型,然后將完成的對(duì)象加入一個(gè)列表中,并且返回this。

    這個(gè)列表就是this.taskQueue.

    格式: [{taskFn: taskFn,

    ????????????type: type}]

    Animation.prototype._add 將任務(wù)加入到任務(wù)隊(duì)列中,

    最終this._add返回this。這個(gè)this也被Animation.prototype.loadImage()最終返回。

    代碼:

    Animation.prototype.loadImage = function (imageList) {

    var taskFn = function (next) {

    //為了保證不影響原對(duì)象。使用slice

    loadImage(imageList.slice(),next)

    }

    //設(shè)置為同步任務(wù)。

    var type = TASK_SYNC;

    //放到任務(wù)隊(duì)列中,同時(shí)返回由this._add()所返回的this

    return this._add(taskFn, type);

    }

    Animation.prototype._add = function (taskFn, type) {

    this.taskQueue.push({

    taskFn: taskFn,

    type: type

    })

    return this;

    }


    任務(wù)隊(duì)列taskQueue已經(jīng)有了。接下來就是執(zhí)行里面的任務(wù)了。

    通過調(diào)用Animation.prototype.start(),

    設(shè)置了任務(wù)執(zhí)行狀態(tài),以及時(shí)間間隔之后

    這里調(diào)用的是,Animation.prototype._runTasks

    _runTasks中,遍歷并沒有用for 語句,而是通過迭代。

    代碼:

    Animation.prototype.start = function (interval) {

    //當(dāng)開始的時(shí)候,如果已經(jīng)開始了,那么不動(dòng)作

    if (this.state === STATE_START) {

    return this;

    }

    //如果沒有任務(wù)

    if (!this.taskQueue, length) {

    return this;

    }

    this.state = STATE_START;

    this.interval = interval;

    this._runTasks();

    return this;

    }

    通過在this上定義一個(gè)值為0的index屬性,index會(huì)在完成任務(wù)的時(shí)候遞增,并且在Index == 任務(wù)隊(duì)列的長(zhǎng)度的時(shí)候,也就是執(zhí)行完所有任務(wù)的時(shí)候,停止執(zhí)行,釋放內(nèi)存等。

    代碼:

    function Animation() {

    //任務(wù)隊(duì)列

    this.taskQueue = [];

    //控制遍歷的計(jì)數(shù)器

    this.index = 0;

    //執(zhí)行狀態(tài)

    this.state = STATE_INITIAL

    }


    使用this.taskQueue[this.index]的形式取出當(dāng)前方法。

    index每次遞增都會(huì)重新調(diào)動(dòng)任務(wù)隊(duì)列的執(zhí)行函數(shù)_runTasks

    _runTasks里面的邏輯是,

    通過之前this._add的時(shí)候,設(shè)置的方法狀態(tài),來確定是異步還是同步。

    代碼:

    Animation.prototype._runTasks = function() {

    //所以呢,它應(yīng)該是接收一個(gè)任務(wù)隊(duì)列,然后按照異步或者同步的方式分別執(zhí)行。

    //在這里這個(gè)任務(wù)隊(duì)列在實(shí)例上的taskQueue

    if (!this.taskQueue.length || this.state !== STATE_START ) {

    return;

    }

    //任務(wù)執(zhí)行完畢,釋放內(nèi)存

    if (this.index === this.taskQueue.length) {

    this.dispose()

    return;

    }

    //由于由this.index控制遍歷,所以從當(dāng)前任務(wù)開始,this.index默認(rèn)為第一個(gè)

    //這里已經(jīng)是經(jīng)過this._add后,對(duì)象的形式{taskFn: taskFn, type: type}

    var task = this.taskQueue[this.index]

    //task可能是同步任務(wù)或者異步任務(wù),兩種任務(wù)執(zhí)行方式不同

    if (task.type === TASK_SYNC) {

    this._syncTask(task)

    } else if (task.type === TASK_ASYNC) {

    this._asyncTask(task)

    }

    }


    這里this.index++,以及_runTasks的再次調(diào)用,是在同步或者異步任務(wù)執(zhí)行完畢之后,由負(fù)責(zé)同步任務(wù)或者異步任務(wù)的函數(shù)來調(diào)用的。

    代碼:

    /*執(zhí)行同步任務(wù)的方法 */

    Animation.prototype._syncTask = function (task) {

    //保留this,因?yàn)闀?huì)在閉包中調(diào)用。

    var m = this

    //執(zhí)行完畢的回調(diào)

    var next = function () {

    me._next()

    }

    //取出要執(zhí)行的方法

    var taskFn = task.taskFn;

    //執(zhí)行它,并傳入回調(diào)。

    taskFn(next)

    }

    /*

    *切換到下一個(gè)任務(wù)的方法

    */

    Animation.prototype._next = function () {

    this.index++;

    //這里是遍歷。

    this._runTasks();

    }


    /**

    * 異步任務(wù)執(zhí)行方法

    */


    Animation.prototype._asyncTask = function(task) {

    //未待續(xù)完,使用requestAnimationFrame

    }


    Animation.prototype._runTasks 負(fù)責(zé)確定極限值的收尾工作,以及確定任務(wù)狀態(tài)并且執(zhí)行負(fù)責(zé)同步任務(wù)或者負(fù)責(zé)異步任務(wù)的函數(shù)。



    所有的數(shù)據(jù)都由實(shí)例來負(fù)責(zé)。在實(shí)例上定義。

    查看全部
  • 總結(jié)下,大概是這樣的邏輯

    預(yù)加載圖片流程

    • 由定義在proptotype上的LoadImage方法把數(shù)組交給真正去加載圖片的組件模塊。該數(shù)組為[{src:'imageurl'}] 這樣的格式。

    • 經(jīng)由該模塊之后,會(huì)返回一個(gè)數(shù)組,其中標(biāo)志了哪些圖片加載成功,哪些沒有。為了這樣做的話,就需要給圖片分別加一個(gè)對(duì)應(yīng)ID。

    • 在這個(gè)模塊中,會(huì)將數(shù)組中的對(duì)象遍歷取出來加載。為了這樣做,需要先排除錯(cuò)誤數(shù)據(jù),。不存在可以遍歷的對(duì)象,該對(duì)象不存在src,以及在Prototype上的屬性,如果是string的話,做類型轉(zhuǎn)換成Object。

      遍歷是用for in 語句。

    ????????for (var key in images) {}

    ????????在真正的加載過程中,首先要新建Image對(duì)象。將其綁定到window上。像前面說的,為Image加上ID,同時(shí)數(shù)據(jù)中的對(duì)象也要保存這個(gè)ID。

    ????????設(shè)置onload, onerror的處理后,設(shè)置Image對(duì)象的src,就會(huì)加載了。

    而為了全部加載成功之后之后調(diào)用callback回調(diào)函數(shù),需要進(jìn)行計(jì)數(shù)和確定完成的方法。

    在這里是遍歷的時(shí)候count ++ ,每次加載完成,無論失敗與否,都會(huì) --count ,

    當(dāng)然失敗與否在該對(duì)象上進(jìn)行的標(biāo)記不同,這里用

    status 為loaded 作為成功。status 為error作為失敗

    最后當(dāng)沒有圖片可以加載 的時(shí)候,就可以加載回調(diào)函數(shù)了。

    當(dāng)然還有對(duì)加載超時(shí)的優(yōu)化。

    這里我覺得比較特別的是,并沒有用var timer 而用了 timoutId 這個(gè)變量設(shè)置setTimeout

    這里分為兩種情況,所以最開始也設(shè)置了一個(gè)局部變量作為成功或者失敗的標(biāo)志位。var success

    如果加載成功,那么success為true, clearTimeout

    如果所有的遍歷和加載都完成了,而且success == false 的情況,當(dāng)然就是setTimeout了


    查看全部
  • https://github.com/ustbhuangyi/animation/tree/gh-pages/images

    查看全部
  • js實(shí)現(xiàn)幀動(dòng)畫

    查看全部
  • 幀動(dòng)畫原理

    查看全部
  • 老師聲音好好聽(≧?≦)講得好好
    查看全部
    0 采集 收起 來源:課程總結(jié)

    2018-04-06

  • 鏈?zhǔn)秸{(diào)用視作任務(wù)鏈
    查看全部
  • 調(diào)用方式
    查看全部
  • 編程接口3
    查看全部
  • 編程接口2
    查看全部
  • 編程接口
    查看全部
  • 需求分析
    查看全部
  • 設(shè)計(jì)過程
    查看全部
首頁上一頁1234567下一頁尾頁

舉報(bào)

0/150
提交
取消
課程須知
1、對(duì)前端基礎(chǔ)知識(shí)已經(jīng)掌握(html、js、css) 2、對(duì)前端面向?qū)ο缶幊逃幸欢私?/dd>
老師告訴你能學(xué)到什么?
1、什么是幀動(dòng)畫及網(wǎng)頁中常見的幾種幀動(dòng)畫方式 2、原生 JS 實(shí)現(xiàn)幀動(dòng)畫的原理 3、如何設(shè)計(jì)一個(gè)通用的幀動(dòng)畫解決方案 4、了解類似 promise的設(shè)計(jì)思想(異步任務(wù)鏈?zhǔn)秸{(diào)用) 5、面向?qū)ο蟮拈_發(fā)方式和模塊化開發(fā)思想 6、如何實(shí)現(xiàn)圖片預(yù)加載模塊

微信掃碼,參與3人拼團(tuán)

微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

友情提示:

您好,此課程屬于遷移課程,您已購買該課程,無需重復(fù)購買,感謝您對(duì)慕課網(wǎng)的支持!