1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        你可能不知道的Animation動(dòng)畫(huà)技巧與細(xì)節(jié)

        共 7862字,需瀏覽 16分鐘

         ·

        2020-11-14 21:29

        引言

        在 web 應(yīng)用中,前端同學(xué)在實(shí)現(xiàn)動(dòng)畫(huà)效果時(shí)往往常用的幾種方案:

        1. css3 transition / animation - 實(shí)現(xiàn)過(guò)渡動(dòng)畫(huà)
        2. setInterval / setTimeout - 通過(guò)設(shè)置一個(gè)間隔時(shí)間來(lái)不斷的改變圖像的位置
        3. requestAnimationFrame - 通過(guò)一個(gè)回調(diào)函數(shù)來(lái)改變圖像位置,由系統(tǒng)來(lái)決定這個(gè)回調(diào)函數(shù)的執(zhí)行時(shí)機(jī),比定時(shí)修改的性能更好,不存在失幀現(xiàn)象

        在大多數(shù)需求中,css3 的 transition / animation 都能滿足我們的需求,并且相對(duì)于 js 實(shí)現(xiàn),可以大大提升我們的開(kāi)發(fā)效率,降低開(kāi)發(fā)成本。

        本篇文章將著重對(duì) animation 的使用做個(gè)總結(jié),如果你的工作中動(dòng)畫(huà)需求較多,相信本篇文章能夠讓你有所收獲:

        • Animation 常用動(dòng)畫(huà)屬性
        • Animation 實(shí)現(xiàn)不間斷播報(bào)
        • Animation 實(shí)現(xiàn)回彈效果
        • Animation 實(shí)現(xiàn)直播點(diǎn)贊效果 ??
        • Animation 與 Svg 又會(huì)擦出怎樣的火花呢??
          1. Loading 組件
          2. 進(jìn)度條組件
        • Animation steps() 運(yùn)用 ?
          1. 實(shí)現(xiàn)打字效果
          2. 繪制幀動(dòng)畫(huà)

        Animation 常用動(dòng)畫(huà)屬性

        介紹完 animation 常用屬性,為了將這些屬性更好地理解與運(yùn)用,下面將手把手實(shí)現(xiàn)一些 DEMO 具體講述

        Animation 實(shí)現(xiàn)不間斷播報(bào)

        實(shí)現(xiàn)不間斷播報(bào) DEMO [1]

        通過(guò)修改內(nèi)容在父元素中的 y 軸的位置來(lái)實(shí)現(xiàn)廣播效果

        @keyframes scroll {
        0%{
        transform: translate(0, 0);
        }
        100%{
        transform: translate(0, -$height);
        }
        }

        .ul {
        animation-name: scroll;
        animation-duration: 5s;
        animation-timing-function: linear;
        animation-iteration-count: infinite;
        /* animation: scroll 5s linear infinite; 動(dòng)畫(huà)屬性簡(jiǎn)寫(xiě) */
        }

        此處為了保存廣播滾動(dòng)效果的連貫性,防止?jié)L動(dòng)到最后一幀時(shí)沒(méi)有內(nèi)容,需要多添加一條重復(fù)數(shù)據(jù)進(jìn)行填充

        <div class="ul">
        <div class="li">小劉同學(xué)加入了凹凸實(shí)驗(yàn)室div>
        <div class="li">小鄧同學(xué)加入了凹凸實(shí)驗(yàn)室div>
        <div class="li">小李同學(xué)加入了凹凸實(shí)驗(yàn)室div>
        <div class="li">小王同學(xué)加入了凹凸實(shí)驗(yàn)室div>

        <div class="li">小劉同學(xué)加入了凹凸實(shí)驗(yàn)室div>
        div>

        Animation 實(shí)現(xiàn)回彈效果

        通過(guò)將過(guò)渡動(dòng)畫(huà)拆分為多個(gè)階段,每個(gè)階段的 top 屬性停留在不同的位置來(lái)實(shí)現(xiàn)

        實(shí)現(xiàn)回彈效果 DEMO[2]

        /* 規(guī)定動(dòng)畫(huà),改變top,opacity */
        @keyframes animate {
        0% {
        top: -100%;
        opacity: 0;
        }
        25% {
        top: 60;
        opacity: 1;
        }
        50% {
        top: 48%;
        opacity: 1;
        }
        75% {
        top: 52%;
        opacity: 1;
        }
        100%{
        top: 50%;
        opacity: 1;
        }
        }

        為了讓過(guò)渡效果更自然,這里通過(guò) cubic-bezier() 函數(shù)定義一個(gè)貝塞爾曲線來(lái)控制動(dòng)畫(huà)播放速度

        過(guò)渡動(dòng)畫(huà)執(zhí)行完后,為了將讓元素應(yīng)用動(dòng)畫(huà)最后一幀的屬性值,我們需要使用 animation-fill-mode: forwards

        .popup {
        animation-name: animate;
        animation-duration: 0.5s;
        animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
        animation-iteration-count: 1;
        animation-fill-mode: forwards;
        /* animation: animate 0.5s cubic-bezier(0.21, 0.85, 1, 1) 1 forwards; 動(dòng)畫(huà)屬性簡(jiǎn)寫(xiě) */
        }

        Animation 實(shí)現(xiàn)點(diǎn)贊效果

        實(shí)現(xiàn)點(diǎn)贊效果 DEMO [3]

        相信大多數(shù)同學(xué)都知道點(diǎn)贊效果,本文章會(huì)實(shí)現(xiàn)一個(gè)簡(jiǎn)易版的點(diǎn)贊效果,主要講述一下實(shí)現(xiàn)思路:

        1. 為了讓氣泡可以向上偏移,我們需要先實(shí)現(xiàn)一個(gè) y 軸方向上移動(dòng)的 @keyframes 動(dòng)畫(huà)
        /* 規(guī)定動(dòng)畫(huà),改變y軸偏移距離*/
        @keyframes animation-y {
        0%{
        transform: translate(-50%, 100px) scale(0);
        }
        50%{
        transform: translate(-50%, -100px) scale(1.5);
        }
        100%{
        transform: translate(-50%, -300px) scale(1.5);
        }
        }
        1. 為了讓氣泡向上偏移時(shí)顯得不太單調(diào),我們可以再實(shí)現(xiàn)一個(gè) x 軸方向上移動(dòng)的 @keyframes 動(dòng)畫(huà)
        /* 規(guī)定動(dòng)畫(huà),改變x軸偏移距離 */
        @keyframes animation-x {
        0%{
        margin-left: 0px;
        }
        25%{
        margin-left: 25px;
        }
        75%{
        margin-left: -25px;
        }
        100%{
        margin-left: 0px;
        }
        }

        這里我理解:

        • 雖然是修改 margin 來(lái)改變 x 軸偏移距離,但實(shí)際上與修改 transform沒(méi)有太大的性能差異
        • 因?yàn)橥ㄟ^(guò) @keyframes animation-y 中的 transform 已經(jīng)新建了一個(gè)渲染層 ( PaintLayers )
        • animation 屬性 可以讓該渲染層提升至 合成層(Compositing Layers) 擁有單獨(dú)的圖形層 ( GraphicsLayer ),即開(kāi)啟了硬件加速 ,不會(huì)影響其他渲染層的 paint、layout
        • 對(duì)于合成層(Compositing Layers)相關(guān)知識(shí)不是很了解的同學(xué),可以閱讀一下凹凸實(shí)驗(yàn)室(http://aotu.io)的文章《從瀏覽器渲染層面解析 css3 動(dòng)效優(yōu)化原理》
        • 如下圖所示:

        如筆者這里理解有誤,還請(qǐng)讀者大佬指出,感激不盡~

        1. 給氣泡應(yīng)用上我們所實(shí)現(xiàn)的兩個(gè) @keyframes 動(dòng)畫(huà)
        .bubble {
        animation: animation-x 3s -2s linear infinite,animation-y 4s 0s linear 1;
        /* 給 bubble 開(kāi)啟了硬件加速 */
        }
        1. 在點(diǎn)贊事件中,通過(guò) js 操作動(dòng)態(tài)添加/移除氣泡元素
        function like() {
        const likeDom = document.createElement('div');
        likeDom.className = 'bubble'; // 添加樣式
        document.body.appendChild(likeDom); // 添加元素
        setTimeout( () => {
        document.body.removeChild(likeDom); // 移除元素
        }, 4000)
        }

        Animation 與 Svg 繪制 loading/進(jìn)度條 組件 ?

        Animation 與 Svg 繪制 loading/進(jìn)度條 組件 ? DEMO [4]

        1. 首先,我們使用 svg 繪制一個(gè)圓周長(zhǎng)為2 * 25 * PI = 157 的圓
        <svg with='200' height='200' viewBox="0 0 100 100"  >
        <circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke="#0079f5" >circie>
        svg>
        1. 將實(shí)線圓繪制成虛線圓,這里需要用 stoke-dasharray:50, 50 (可簡(jiǎn)寫(xiě)為50) 屬性來(lái)繪制虛線, stoke-dasharray 參考資料[5]
        • 它的值是一個(gè)數(shù)列,數(shù)與數(shù)之間用逗號(hào)或者空白隔開(kāi),指定短劃線(50px)缺口(50px)的長(zhǎng)度。
        • 由于50(短劃線) + 50(缺口) + 50(段劃線) = 150, 150 < 157,無(wú)法繪制出完整的圓,所以會(huì)導(dǎo)致右邊存在缺口(7px)
        <svg with='200' height='200' viewBox="0 0 100 100"  >
        <circle cx="50" cy="50" r="25" fill="transparent" stroke-width="4" stroke-dasharray="50" stroke="#0079f5" >circie>
        svg>
        1. stroke-dashoffset 屬性可以使圓的短劃線和缺口產(chǎn)生偏移,添加 @keyframes 動(dòng)畫(huà)后能夠?qū)崿F(xiàn)從無(wú)到有的效果,stoke-dashoffset 參考資料[6]
        • 設(shè)置 stroke-dasharray="157 157",指定 短劃線(157px)缺口(157px) 的長(zhǎng)度。
        • 添加 @keyframes 動(dòng)畫(huà) 修改stroke-dashoffset值, 值為正數(shù)時(shí)逆時(shí)針偏移?,, 值為負(fù)數(shù)時(shí),順時(shí)針偏移?
        @keyframes loading {
        0%{
        stroke-dashoffset: 0;
        }
        100%{
        stroke-dashoffset: -157; /* 線條順時(shí)針偏移 */
        }
        }
        circle{
        animation: loading 1s 0s ease-out infinite;
        }
        1. 修改短劃線和缺口值
        • 為了讓 loading 組件線條可見(jiàn),我們需要一個(gè)50px的短劃線,設(shè)置 stroke-dasharray="50"
        • 為了讓短劃線發(fā)生偏移后可以完全消失,缺口需要大于或等于圓周長(zhǎng)157,設(shè)置 stroke-dasharray="50 157"
        • 添加 @keyframes 動(dòng)畫(huà),為了讓動(dòng)畫(huà)結(jié)束時(shí)仍處理動(dòng)畫(huà)開(kāi)始位置,需要修改 stroke-dashoffset:-207(短劃線+缺口長(zhǎng)度)
        • 進(jìn)度條也是類似原理,幫助理解 stroke-dashoffset 屬性,具體實(shí)現(xiàn)請(qǐng)查看示例[7]
        @keyframes loading {
        0%{
        stroke-dashoffset: 0;
        }
        100%{
        stroke-dashoffset: -207; /* 保證動(dòng)畫(huà)結(jié)束時(shí)仍處理動(dòng)畫(huà)開(kāi)始位置 */
        }
        }
        circle{
        animation: loading 1s 0s ease-out infinite;
        }

        Animation steps()運(yùn)用

        steps()animation-timing-function 的屬性值

        animation-timing-function : steps(number[, end | start])
        • steps 函數(shù)指定了一個(gè)階躍函數(shù),它接受兩個(gè)參數(shù)
        • 第一個(gè)參數(shù)接受一個(gè)整數(shù)值,表示兩個(gè)關(guān)鍵幀之間分幾步完成
        • 第二個(gè)參數(shù)有兩個(gè)值 start or end。默認(rèn)值為 end
        • step-start 等同于 step(1, start)。step-end 等同于 step(1, end)

        steps 適用于關(guān)鍵幀動(dòng)畫(huà),第一個(gè)參數(shù)將兩個(gè)關(guān)鍵幀細(xì)分為N幀,第二個(gè)參數(shù)決定從一幀到另一幀的中間間隔是用開(kāi)始幀還是結(jié)束幀來(lái)進(jìn)行填充。

        看下圖可以發(fā)現(xiàn):

        • steps(N, start)將動(dòng)畫(huà)分為N段,動(dòng)畫(huà)在每一段的起點(diǎn)發(fā)生階躍(即圖中的空心圓 → 實(shí)心圓),動(dòng)畫(huà)結(jié)束時(shí)停留在了第 N 幀
        • steps(N, end)將動(dòng)畫(huà)分為N段,動(dòng)畫(huà)在每一段的終點(diǎn)發(fā)生階躍(即圖中的空心圓 → 實(shí)心圓),動(dòng)畫(huà)結(jié)束時(shí)第 N 幀已經(jīng)被跳過(guò)(即圖中的空心圓 → 實(shí)心圓),停留在了 N+1 幀。

        實(shí)踐出真知!

        Animation 實(shí)現(xiàn)打字效果

        Animation 實(shí)現(xiàn)打字效果 DEMO[8]

        • 此處用英文字母(I'm an O2man.)舉例,一共有13個(gè)字符。[經(jīng)測(cè)試,多數(shù)中文字體每個(gè)字符寬高都相等]
        • steps(13)可以將 @keyframes 動(dòng)畫(huà)分為13階段運(yùn)行,且每一階段運(yùn)行距離相等。

        效果如下:

        /* 改變?nèi)萜鲗挾?*/
        @keyframes animate-x {
        0%{
        width: 0;
        }
        }

        p {
        width: 125px;
        overflow: hidden;
        border-right: 1px solid transparent;
        animation: animate-x 3s 0s steps(13) 1 forwards;
        }
        • 可以發(fā)現(xiàn)僅僅這樣還不夠,動(dòng)畫(huà)運(yùn)行過(guò)程中出現(xiàn)了字符被截?cái)嗟那闆r,為了保證每個(gè)階段運(yùn)行后能準(zhǔn)確無(wú)誤地顯示當(dāng)前所處階段的字符,我們還需要保證每個(gè)字符的width與動(dòng)畫(huà)每一階段運(yùn)行的距離相等
        • 設(shè)置Monaco字體屬性,用以保證每個(gè)字符的 width 相同,具體像素受fontSize屬性影響,示例中的字體寬度約為 9.6px,9.6px * 13(段數(shù)) = 124.8px (125px),所以當(dāng)我們?cè)O(shè)置容器寬度為 125px,即可的達(dá)成目的:每個(gè)字符的 width 與動(dòng)畫(huà)每一階段運(yùn)行的距離相等(約為 9.6px )。
        p {
        /* 設(shè)置 Monaco 字體屬性,字體大小為16px,用以保證每個(gè)字符的 width 相同,width 約為9.6p */
        font-family: Monaco;
        /* 9.6px * 13 = 124.8px (125px) */
        width: 125px ;
        font-size: 16px;
        overflow: hidden;
        border-right: 1px solid transparent;
        /* 同時(shí)應(yīng)用動(dòng)畫(huà) animate-x、cursor-x */
        animation: animate-x 3s 0s steps(13) 1 forwards,cursor-x 0.4s 0s linear infinite;
        }

        Animation 實(shí)現(xiàn)幀動(dòng)畫(huà) ?

        Animation 實(shí)現(xiàn)幀動(dòng)畫(huà) ? DEMO [9]

        • 這里我們拿到了一張47幀雪碧圖(css spirit)[10],設(shè)置背景圖
        .main {
        width: 260px;
        height: 200px;
        background: url(url) no-repeat;
        background-size: 100%;
        background-position: 0 0;
        }
        • 添加 @keyframes 修改 background-position,讓背景圖移動(dòng)
        @keyframes animate {
        0% {
        background-position: 0 0;
        }

        100% {
        background-position: 0 100%;
        }
        }
        .main{
        width: 260px;
        height: 200px;
        background: url(url) no-repeat;
        background-size: 100%;
        background-position: 0 0;
        animation: animate 2s 1s steps(47) infinite alternate;
        }
        • 同時(shí), css 還提供了animation-play-state用于控制動(dòng)畫(huà)是否暫停
        input:checked+.main{
        animation-play-state: paused;
        }

        文章篇幅較長(zhǎng),感謝大家的閱讀,希望各位看客能夠有所收獲~ ~ ~


        相關(guān)參考資料

        《Animation 常用動(dòng)畫(huà)屬性》[11]

        《CSS 參考手冊(cè)》[12]

        《steps 參考資料》[13]

        《SVG 學(xué)習(xí)之 stroke-dasharray 和 stroke-dashoffset 詳解》[14]

        《理解 CSS3 Animation 中的 steps》[15]

        《【譯】css 動(dòng)畫(huà)里的 steps 用法詳解》[16]

        《CSS Will Change》[17]

        ??愛(ài)心三連擊

        1.看到這里了就點(diǎn)個(gè)在看支持下吧,你的點(diǎn)贊,在看是我創(chuàng)作的動(dòng)力。

        參考資料

        [1]

        實(shí)現(xiàn)不間斷播報(bào) DEMO : https://codepen.io/awesomedevin/pen/wvMGEaY

        [2]

        實(shí)現(xiàn)回彈效果 DEMO: https://codepen.io/awesomedevin/pen/wvMGEaY

        [3]

        實(shí)現(xiàn)點(diǎn)贊效果 DEMO : https://codepen.io/awesomedevin/pen/dyGXEar

        [4]

        Animation 與 Svg 繪制 loading/進(jìn)度條 組件 ? DEMO : https://codepen.io/awesomedevin/pen/zYromBB

        [5]

        stoke-dasharray 參考資料: https://www.cnblogs.com/daisygogogo/p/11044353.html

        [6]

        stoke-dashoffset 參考資料: https://www.cnblogs.com/daisygogogo/p/11044353.html

        [7]

        示例: https://codepen.io/awesomedevin/pen/zYromBB

        [8]

        Animation 實(shí)現(xiàn)打字效果 DEMO: https://codepen.io/awesomedevin/pen/xxZEjjO

        [9]

        Animation 實(shí)現(xiàn)幀動(dòng)畫(huà) ? DEMO : https://codepen.io/awesomedevin/pen/JjGRMgN

        [10]

        雪碧圖(css spirit): https://img11.360buyimg.com/ling/jfs/t1/142743/11/2314/166268/5f046114Efb97efac/b327092864ed1f04.png

        [11]

        Animation 常用動(dòng)畫(huà)屬性: https://www.w3school.com.cn/cssref/index.asp

        [12]

        CSS 參考手冊(cè): https://www.w3school.com.cn/cssref/index.asp

        [13]

        steps 參考資料: https://segmentfault.com/a/1190000007042048

        [14]

        SVG 學(xué)習(xí)之 stroke-dasharray 和 stroke-dashoffset 詳解: https://www.cnblogs.com/daisygogogo/p/11044353.html

        [15]

        理解 CSS3 Animation 中的 steps: https://laixiazheteng.com/article/page/id/0gU2Wefas7hn

        [16]

        【譯】css 動(dòng)畫(huà)里的 steps 用法詳解: https://segmentfault.com/a/1190000007042048

        [17]

        CSS Will Change: https://developer.mozilla.org/zh-CN/docs/Web/CSS/will-change


        “在看轉(zhuǎn)發(fā)”是最大的支持

        瀏覽 60
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            开心激情综合网 | 欧美一级婬片AAAAAAA牛牛 | 99久热视频在线 | 欧美精品性爱视频 | 成人做爰黄 片免费看 | 99re视频这里只有精品 | 亚洲在线无码 | 日韩欧美视频在线 | 中文字幕日韩乱伦 | 波多野结衣视频在线播放 |