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

為了賬號安全,請及時綁定郵箱和手機立即綁定
  • js 實現(xiàn)幀動畫原理

    查看全部
    0 采集 收起 來源:認識幀動畫

    2021-06-19

  • img src

    div background


    查看全部
    0 采集 收起 來源:認識幀動畫

    2019-12-21

  • 和上一個差別不大

    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é)束時跳到下一個

    if (index === len - 1) {

    next();

    }

    }

    type = TASK_ASYNC;

    } else {

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

    taskFn = next;

    type = TASK_SYNC;

    }

    return this._add(taskFn,type)

    }


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


    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的時候,傳過來的

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

    if (imageUrl) {

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

    }

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

    //那么選擇當前已經(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'

    //動畫循環(huán)完成了的時候。

    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) {

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

    var enterFrame = function (time) {

    var me = this;

    var taskFn = task.taskFn;

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

    var next = function () {

    //停止當前的

    me.timeline.stop()

    //執(zhí)行下一個

    me._next()

    }

    taskFn(next,time)

    }

    this.timeline.onenterframe = enterFrame;

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

    this.timeline.start(this.interval)

    }



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

    function Animation() {

    this.timeline = new Timeline();

    //來自用戶設定的時間間隔

    this.interval = 0;

    }

    Animation.prototype._asyncTask = function(task) {

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

    var enterFrame = function (time) {

    var me = this;

    var taskFn = task.taskFn;

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

    var next = function () {

    //停止當前的

    me.timeline.stop()

    //執(zhí)行下一個

    me._next()

    }

    taskFn(next,time)

    }

    this.timeline.onenterframe = enterFrame;

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

    this.timeline.start(this.interval)

    }



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

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

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

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

    代碼:

    function startTimeline(timeline, startTime) {

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

    timeline.startTime = startTime

    //為用requestAnimationFrame加上的callback.interval

    nextTick.interval = timeline.interval


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

    var lastTick = +new Date();

    nextTick();

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


    //其實這是一個迭代形式的setInterval

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

    function nextTick() {

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

    var now = +new Date();

    timeline.animationHandler = requestAnimationFrame(nextTick)

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

    timeline.onenterframe(now - startTime)

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

    lastTick = now;

    }

    }

    }


    類:?

    function Timeline(interval) {

    //當前動畫的狀態(tài)。

    this.state = STATE_INITIAL;

    //當前動畫進行時間。

    this.startTime = 0;

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

    this.interval = DEFAULT_INTERVAL;

    //setTimeout的ID

    this.animationHandler = 0;

    //動畫開始了多久,暫停的時候儲存留待再次開始

    this.dur = 0;

    }


    /**

    ?* 動畫停止

    ?*/

    Timeline.prototype.stop = function (interval) {

    if (this.state !== STATE_START) {

    return

    }

    this.state = STATE_STOP;

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

    if (this.stateTime) {

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

    }

    cancelAnimationFrame(this.animationHandler)

    }

    /**

    * 重新播放動畫

    */

    Timeline.prototype.restart = function (interval) {

    if (this.state !== STATE_START) {

    return

    }

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

    return

    }

    this.state = STATE_START

    //從停止那一刻算起,開始動畫

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

    }





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

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


    代碼:


    var DEFAULT_INTERVAL = 1000/60

    //requestAnimationFrame每17毫秒會刷新一次。

    var requestAnimationFrame = (function () {

    //瀏覽器兼容

    return window.requestAnimationFrame ||

    window.webketRequestAnimationFrame ||

    window.mozRequestAnimationFrame ||

    window.oRequestAnimationFrame ||

    //如果不支持,則用setTimeout ,默認為 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 ,默認為 1000/60 毫秒后

    function (id) {

    return window.clearTimeout(id)

    }

    })()

    接下來定義class。


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

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

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

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

    這個列表就是this.taskQueue.

    格式: [{taskFn: taskFn,

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

    Animation.prototype._add 將任務加入到任務隊列中,

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

    代碼:

    Animation.prototype.loadImage = function (imageList) {

    var taskFn = function (next) {

    //為了保證不影響原對象。使用slice

    loadImage(imageList.slice(),next)

    }

    //設置為同步任務。

    var type = TASK_SYNC;

    //放到任務隊列中,同時返回由this._add()所返回的this

    return this._add(taskFn, type);

    }

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

    this.taskQueue.push({

    taskFn: taskFn,

    type: type

    })

    return this;

    }


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

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

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

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

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

    代碼:

    Animation.prototype.start = function (interval) {

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

    if (this.state === STATE_START) {

    return this;

    }

    //如果沒有任務

    if (!this.taskQueue, length) {

    return this;

    }

    this.state = STATE_START;

    this.interval = interval;

    this._runTasks();

    return this;

    }

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

    代碼:

    function Animation() {

    //任務隊列

    this.taskQueue = [];

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

    this.index = 0;

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

    this.state = STATE_INITIAL

    }


    使用this.taskQueue[this.index]的形式取出當前方法。

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

    _runTasks里面的邏輯是,

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

    代碼:

    Animation.prototype._runTasks = function() {

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

    //在這里這個任務隊列在實例上的taskQueue

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

    return;

    }

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

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

    this.dispose()

    return;

    }

    //由于由this.index控制遍歷,所以從當前任務開始,this.index默認為第一個

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

    var task = this.taskQueue[this.index]

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

    if (task.type === TASK_SYNC) {

    this._syncTask(task)

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

    this._asyncTask(task)

    }

    }


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

    代碼:

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

    Animation.prototype._syncTask = function (task) {

    //保留this,因為會在閉包中調(diào)用。

    var m = this

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

    var next = function () {

    me._next()

    }

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

    var taskFn = task.taskFn;

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

    taskFn(next)

    }

    /*

    *切換到下一個任務的方法

    */

    Animation.prototype._next = function () {

    this.index++;

    //這里是遍歷。

    this._runTasks();

    }


    /**

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

    */


    Animation.prototype._asyncTask = function(task) {

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

    }


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



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

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

    預加載圖片流程

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

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

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

      遍歷是用for in 語句。

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

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

    ????????設置onload, onerror的處理后,設置Image對象的src,就會加載了。

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

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

    當然失敗與否在該對象上進行的標記不同,這里用

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

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

    當然還有對加載超時的優(yōu)化。

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

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

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

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


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

    查看全部
  • js實現(xiàn)幀動畫

    查看全部
    0 采集 收起 來源:認識幀動畫

    2018-05-12

  • 幀動畫原理

    查看全部
    0 采集 收起 來源:認識幀動畫

    2018-04-21

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

    2018-04-06

  • 鏈式調(diào)用視作任務鏈
    查看全部
  • 調(diào)用方式
    查看全部
  • 編程接口3
    查看全部
  • 編程接口2
    查看全部
  • 編程接口
    查看全部
  • 需求分析
    查看全部
  • 設計過程
    查看全部
首頁上一頁1234567下一頁尾頁

舉報

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

微信掃碼,參與3人拼團

微信客服

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

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

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

友情提示:

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