公交车上荫蒂添的好舒服的电影-公用玩物(np双xing总受)-公用小荡货芊芊-公与妇仑乱hd-攻把受做哭边走边肉楼梯play-古装一级淫片a免费播放口

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

requestAnimationFrame和使用場景舉例

freeflydom
2024年8月15日 9:26 本文熱度 1525

一項新技術新的技術方案的提出,一定是為了解決某個問題的,或者是對某種方案的優(yōu)化,比如window.requestAnimationFrame這個api...

requestAnimationFrame官方介紹

requestAnimationFrame用處概述

window.requestAnimationFrame() 告訴瀏覽器——你希望執(zhí)行一個動畫,并且要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動畫。該方法需要傳入一個回調(diào)函數(shù)作為參數(shù),該回調(diào)函數(shù)會在瀏覽器下一次重繪之前執(zhí)行...

官方文檔對應截圖

官方文檔:developer.mozilla.org/zh-CN/docs/…

大致看了以后,我們可以知道:

requestAnimationFrame這個api主要是用來做動畫的。

requestAnimationFrame這個api主要是用來做動畫的。

requestAnimationFrame這個api主要是用來做動畫的。

其實顧名思義,我們翻譯這個英文單詞,也能大致明白。request(請求)Animation(動畫)Frame(幀)

關于前端動畫的兩個問題:

1.前端動畫方案有哪些?

2.為何偏偏要使用這個新的api來做動畫(或者說這個api較之前做動畫的方式優(yōu)點有哪些)?

1.前端動畫方案有哪些?

主要分類為css動畫js動畫,如下細分:

  • css動畫

    • transition過渡動畫

    • animation直接動畫(搭配@keyframes

  • js動畫

    • setIntervalsetTimeout定時器(比如不停地更改dom元素的位置,使其運動起來)

    • canvas動畫,搭配js中的定時器去運動起來(canvas只是一個畫筆,然后我們通過定時器會使用這個畫筆去畫畫-動畫)

    • requestAnimationFrame動畫(js動畫中的較好方案)

另有svg動畫標簽,不過工作中這種方式是比較少的,這里不贅述

2.為何偏偏要使用這個新的api來做動畫(或者說這個api較之前做動畫的方式優(yōu)點有哪些)?

在工作中,做動畫最優(yōu)的方案無疑是css動畫,但是某些特定場景下,css動畫無法實現(xiàn)我們所需要的需求,此時,我們就要考慮使用js去做動畫了

canvas動畫本質(zhì)也是定時器動畫

使用定時器動畫干活,實際上是可以的,但是存在一個最大的問題,就是動畫會抖動動畫會抖動動畫會抖動,體驗效果不是非常好。

而,使用requestAnimationFrame去做動畫,就不會抖動就不會抖動就不會抖動

這里筆者寫一個demo動畫(分別是上述兩種方式實現(xiàn)dom元素向右平移)給大家看一下,就知道具體的區(qū)別。我們先看一下效果圖:(紅色dom是定時器實現(xiàn)、綠色domrequestAnimationFrame實現(xiàn))

因為筆者的gif錄制軟件的問題,看著都有點卡,實際上,大家把下方代碼復制一份跑起來看的話,會發(fā)現(xiàn)定時器動畫在微微顫抖,而requestAnimationFrame動畫卻穩(wěn)如老狗

<!DOCTYPE html>

<html>

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>requestAnimationFrame_yyds</title>

<style>

body {

box-sizing: border-box;

background-color: #ccc;

}


.box1,

.box2 {

position: absolute;

width: 160px;

height: 160px;

line-height: 160px;

text-align: center;

color: #fff;

font-size: 13px;

}

.box1 {

top: 40px;

background: red;

}

.box2 {

top: 210px;

background: green;

}

</style>

</style>

</head>

<body>

<button>let's go!</button>

<div>定時器動畫</div>

<div>請求動畫幀</div>

<script>

// 動畫思路:不斷修改dom元素的left值,使其運動起來(動畫)

let box1 = document.querySelector('.box1')

let box2 = document.querySelector('.box2')


// setInterval定時器方式

function setIntervalFn() {

let timer = null

box1.style.left = '0px'

timer = setInterval(() => {

let leftVal = parseInt(box1.style.left)

if (leftVal >= 720) {

clearInterval(timer)

} else {

box1.style.left = leftVal + 1 + 'px'

}

}, 17)

}


// requestAnimationFrame請求動畫幀方式

function requestAnimationFrameFn() {

let timer = null // 可注掉

box2.style.left = '0px'

function callbackFn() {

let leftVal = parseInt(box2.style.left)

if (leftVal >= 720) {

// 不再繼續(xù)遞歸調(diào)用即可,就不會繼續(xù)執(zhí)行了,下面這個加不加都無所謂,因為影響不到

// cancelAnimationFrame取消請求動畫幀,用的極少,看下,下文中的回到頂部組件

// 大家會發(fā)現(xiàn)并沒有使用到這個api(這樣寫只是和clearInterval做一個對比)

// 畢竟,正常情況下,requestAnimationFrame會自動停下來

cancelAnimationFrame(timer) // 可注掉(很少用到)

} else {

box2.style.left = leftVal + 1 + 'px'

window.requestAnimationFrame(callbackFn)

}

}

window.requestAnimationFrame(callbackFn)

}


// 動畫綁定

let btn = document.querySelector('.btn')

btn.addEventListener('click', () => {

setIntervalFn()

requestAnimationFrameFn()

})

</script>

</body>

</html>


Chrome瀏覽器查看當前幀數(shù)命令:1. F12打開控制臺2. command + shift + p調(diào)出輸入面板3. 在Run輸入框中輸入:Show frames per second(FPS) meter回車即可

通過上述的例子,我們可以回答這個問題了:

  • 面試官問:requestAnimationFrame比定時器好在哪里?

  • 候選人答:好在比較穩(wěn)定,動畫不卡頓

  • 面試官說:你回去等通知吧...

所以在這里,我們還要順帶延伸一下,為什么定時器會卡,而requestAnimationFrame不會卡。在說這個問題之前,這里再提一下,requestAnimationFrame的語法規(guī)則

requestAnimationFrame的語法規(guī)則

一言以蔽之:requestAnimationFramejs中的setTimeout定時器函數(shù)基本一致,不過setTimeout可以自由設置間隔時間,而requestAnimationFrame的間隔時間是由瀏覽器自身決定的,大約是17毫秒左右

1.requestAnimationFrame我們可以在控制臺輸入window,然后展開查看其身上的屬性,就能找到了,如下圖:

2.由上圖我們可以看到,requestAnimationFrame本質(zhì)上是一個全局window對象上的一個屬性函數(shù),函數(shù)是要被執(zhí)行的,要被調(diào)用的。所以我們使時,直接:window.requestAnimationFrame(callBack)即可。

3.和定時器一樣其接收的參數(shù)callback也是一個函數(shù),即下一次重繪之前更新動畫幀所調(diào)用的函數(shù),即在這個函數(shù)體中,我們可以寫對應的邏輯代碼(和定時器類似)

4.requestAnimationFrame也有返回值,返回值是一個整數(shù),主要是定時器的身份證標識,可以使用 window.cancelAnimationFrame()來取消回調(diào)函數(shù)執(zhí)行,相當于定時器中的clearTimeout()

5.二者也都是只執(zhí)行一次,想要繼續(xù)執(zhí)行,做到類似setInterval的效果,需要寫成遞歸的形式(上述案例中也提到了)

為什么定時器會卡,而requestAnimationFrame不會卡

為什么定時器會卡

  • 我們在手機或者電腦顯示屏上看東西時,顯示屏會默默的不停地干活(刷新畫面)

  • 這個刷新值得是每秒鐘刷新次數(shù),普通顯示器的刷新率約為60Hz(每秒刷新60次),高檔的有75Hz、90Hz、120Hz、144Hz等等

  • 刷新率次數(shù)越高,顯示器顯示的圖像越清晰、越流暢、越絲滑

  • 不刷新就是靜態(tài)的畫面,刷新比較低就是卡了PPT的感覺

  • 動畫想要絲滑流暢,需要卡住時間點進行代碼操作(代碼語句賦值、瀏覽器重繪)

  • 所以只需要每隔1000毫秒的60分之一(60HZ)即約為17毫秒,進行一次動畫操作即可

  • 只要卡住這個17毫秒,每隔17毫秒進行操作,就能確保動畫絲滑

  • 但是定時器的回調(diào)函數(shù),會受到js的事件隊列宏任務、微任務影響,可能設定的是17毫秒執(zhí)行一次,但是實際上這次是17毫秒、下次21毫秒、再下次13毫秒執(zhí)行,所以并不是嚴格的卡住了這個60HZ的時間

  • 沒有在合適的時間點操作,就會出現(xiàn):類似這樣的情況:不變不變不變...

  • 于是就出現(xiàn)了,繪制不及時的情況,就會有抖動的出現(xiàn)(以上述案例,位置和時間沒有線性對應更新變化導致看起來抖動)

js執(zhí)行代碼是很快的,可能不到一毫秒,大家可以使用相應console的api去測試,如下:

console.time()

let box1 = document.querySelector('.box1')

box1.style.left = '100px'

console.timeEnd()


// js執(zhí)行耗時結果:default: 0.044189453125 ms


為何requestAnimationFrame不會卡

requestAnimationFrame能夠做到,精準嚴格的卡住顯示器刷新的時間,比如普通顯示器60HZ它會自動對應17ms執(zhí)行一次,比如高級顯示器120HZ,它會自動對應9ms執(zhí)行一次。

當然requestAnimationFrame只會執(zhí)行一次,想要使其多次執(zhí)行,要寫成遞歸的形式。上述案例也給出了遞歸寫法

至于為何requestAnimationFrame能夠卡住時間,其底層原理又是啥?本文暫且按下不表。

所以,這就是requestAnimationFrame的好處。

所以,上述內(nèi)容驗證了:一項新技術新的技術方案的提出,一定是為了解決相關的問題的。

所以,window.requestAnimationFrame這個api就是解決了定時器不精準的問題的。

這就是其產(chǎn)生的原因。

requestAnimationFrame應用場景舉例-回到頂部組件

比如:回到頂部組件,就是使用requestAnimationFrame實現(xiàn)的。

下面是筆者封裝的回到頂部組件效果圖和代碼

效果圖:

也可以去筆者的網(wǎng)站上去看效果哦:ashuai.work:8888/#/myBack

代碼:

<template>

  <transition name="fade-transform">

    <div

      v-show="visible"

     

      :style="{

        bottom: bottom + 'px',

        right: right + 'px',

      }"

      @click="goToTop"

    >

      <slot></slot>

    </div>

  </transition>

</template>


<script>

export default {

  name: "myBack",

  props: {

    bottom: {

      type: Number,

      default: 72,

    },

    right: {

      type: Number,

      default: 72,

    },

    // 回到頂部出現(xiàn)的滾動高度位置

    showHeight: {

      type: Number,

      default: 240,

    },

    // 擁有滾動條的那個dom元素的id或者class,用于下方選中操作更改滾動條滾動距離

    scrollBarDom: String,

  },

  data() {

    return {

      visible: false,

      scrollDom: null,

    };

  },

  mounted() {

    if (document.querySelector(this.scrollBarDom)) {

      this.scrollDom = document.querySelector(this.scrollBarDom);

      // 不用給window綁定監(jiān)聽滾動事件,給對應滾動條元素綁定即可

      this.scrollDom.addEventListener("scroll", this.isShowGoToTop, true);

    }

  },

  beforeDestroy() {

    // 最后要解除監(jiān)聽滾動事件

    this.scrollDom.removeEventListener("scroll", this.isShowGoToTop, true);

  },

  methods: {

    isShowGoToTop() {

      // 獲取滾動的元素,即有滾動條的那個元素

      if (this.scrollDom.scrollTop > 20) {

        this.visible = true;

      } else {

        this.visible = false;

      }

    },

    goToTop() {

      // 獲取滾動的元素,即有滾動條的那個元素

      let scrollDom = document.querySelector(this.scrollBarDom);

      // 獲取垂直滾動的距離,看看滾動了多少了,然后不斷地修改滾動距離直至為0

      let scrollDistance = scrollDom.scrollTop;


      /**

       * window.requestAnimationFrame兼容性已經(jīng)可以了,正常都有的

       * */

      if (window.requestAnimationFrame) {

        let fun = () => {

          scrollDom.scrollTop = scrollDistance -= 36;

          if (scrollDistance > 0) {

            window.requestAnimationFrame(fun); // 只執(zhí)行一次,想多次執(zhí)行需要再調(diào)用

          } else {

            scrollDom.scrollTop = 0;

          }

        };

        window.requestAnimationFrame(fun);

        return;

      }


      /**

       * 沒有requestAnimationFrame的話,就用定時器去更改滾動條距離,使之滾動

       * */

      let timer2 = setInterval(() => {

        scrollDom.scrollTop = scrollDistance -= 36;

        if (scrollDistance <= 0) {

          clearInterval(timer2);

          scrollDom.scrollTop = 0;

        }

      }, 17);

    },

  },

};

</script>


<style scoped>

.backWrap {

  position: fixed;

  cursor: pointer;

  width: 42px;

  height: 42px;

  background: #9cc2e5;

  border-radius: 4px;

  display: flex;

  justify-content: center;

  align-items: center;

  transition: all 0.5s;

}


// 過渡效果

.fade-transform-leave-active,

.fade-transform-enter-active {

  transition: all 0.36s;

}


.fade-transform-enter {

  opacity: 0;

  transform: translateY(-5px);

}

.fade-transform-leave-to {

  opacity: 0;

  transform: translateY(5px);

}

</style>


GitHub倉庫地址:github.com/shuirongshu…

另外,有一個做滾動的插件庫,叫做vue-seamless-scroll其內(nèi)部實現(xiàn)原理也是基于requestAnimationFrame實現(xiàn)的。感興趣的道友可以去看看

類比學習reduce循環(huán)解決了forEach循環(huán)可能需要一個初始變量的問題

我們類比一下學習,比如既然有了forEach循環(huán),為啥還又新推出一個reduce循環(huán)呢?

原因:某些場景下,reduce循環(huán)解決了forEach循環(huán)還需要再定義一個變量的問題。

似曾相識的感覺...

比如我們有一個需求,給一個數(shù)組求和。

forEach寫法

let arr = [1, 3, 5, 7, 9]

function forEachFn(params) {

    let total = 0

    params.forEach((num) => {

        total = total + num

    })

    return total

}

let res1 = forEachFn(arr)

console.log(res1);


reduce寫法

let arr = [1, 3, 5, 7, 9]

function reduceFn(params) {

    return params.reduce((temp, num) => {

        temp = temp + num

        return temp

    }, 0)

}

let res2 = reduceFn(arr)

console.log(res2);


通過上述兩段代碼,我們可以看到,reduce函數(shù)比forEach少寫了一個total變量,千萬不要小看這少寫的東西,某些情況下,會節(jié)省很多的工作量呢!


作者:水冗水孚
鏈接:https://juejin.cn/post/7190728064458817591
來源:稀土掘金
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處。



該文章在 2024/8/16 10:26:10 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務費用、相關報表等業(yè)務管理,結合碼頭的業(yè)務特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 国产粉色白浆在线观看 | 国产激情一区二区三区四区 | 3d动漫精品啪啪一区二区中文 | 国产综合成人久久大 | 国产超aⅴ男人的天堂 | 国产精品无码av片在线观看播放 | 国产精品免费观看 | 精品国产av| av无码一区二区三区波多野 | 不卡国产精品欧美一区二区 | av在线播放不卡 | 国产精品无码一区二区av | 国产精品中文久久久久久久 | 成人亚洲a片v一区二区三区蜜月 | 91福利在线视 | 国产日韩精品高潮一区二区 | 国产色婷亚洲99精品av在 | 国产精品福利区一区二区三区四 | 国产成人久久综合二区 | 国产成人无码免费网站 | 国产无套乱子伦精彩无码视频 | 国产做无码视频在线 | 国产成人精品日本亚洲网址 | 国产精品丝袜久久久久久不卡 | 国产精品国语对白露脸在线播放 | 91国产在线 | 精品欧洲av无码一区二区14 | 国产福利久久 | 2025亚洲韩国精品乱码 | 国产亚洲日本一区二区三 | 国产高清精品一区在线 | 国产一区二区久久 | 国模自拍日韩在线播放视频网站 | 69久久久a片无码国产精 | 国产精品国三级国产av | 精品无码一区二 | 国产人妻一区二区无码 | 精品无码av一区二区三区 | 福利二区三区第1页 | 国产91一区在线 | 超级乱淫片午夜电影网福利 |