1. 【CSS】1373- 實用的輪播效果實現(xiàn)方法

        共 8749字,需瀏覽 18分鐘

         ·

        2022-07-09 17:39

        今天,分享一個實際業(yè)務(wù)中能夠用得上的動畫技巧。

        巧用逐幀動畫,配合補間動畫實現(xiàn)一個無限循環(huán)的輪播效果,像是這樣:

        看到上述示意圖,有同學(xué)不禁會發(fā)問,這不是個非常簡單的位移動畫么?

        我們來簡單分析分析,從表面上看,確實好像只有元素的 transform: translate() 在位移,但是注意,這里有兩個難點:

        1. 這是個無限輪播的效果,我們的動畫需要支持任意多個元素的無限輪播切換
        2. 因為是輪播,所以,運行到最后一個的時候,需要動畫切到第一個元素

        到這里,你可以暫停思考一下,如果有 20 個元素,需要進行類似的無限輪播播報,使用 CSS 實現(xiàn),你會怎么去做呢?

        逐幀動畫控制整體切換

        首先,我需要利用到逐幀動畫效果,也被稱為步驟緩動函數(shù),利用的是 animation-timing-function 中,的 steps,語法如下:

        {
            /* Keyword values */
            animation-timing-function: step-start;
            animation-timing-function: step-end;
            /* Function values */
            animation-timing-functionsteps(6, start)
            animation-timing-function: steps(4, end);
        }

        如果你對 steps 的語法還不是特別了解,強烈建議你先看看我的這篇文章 -- 深入淺出 CSS 動畫[1],它對理解本文起著至關(guān)重要的作用。

        好的,還是文章以開頭的例子,假設(shè)我們存在這樣 HTML 結(jié)構(gòu):

        <div class="g-container">
          <ul>
            <li>Lorem ipsum 1111111</li>
            <li>Lorem ipsum 2222222</li>
            <li>Lorem ipsum 3333333</li>
            <li>Lorem ipsum 4444444</li>
            <li>Lorem ipsum 5555555</li>
            <li>Lorem ipsum 6666666</li>
          </ul>
        </div>

        首先,我們實現(xiàn)這樣一個簡單的布局:

        在這里,要實現(xiàn)輪播效果,并且是任意個數(shù),我們可以借助 animation-timing-function: steps()

        :root {
          // 輪播的個數(shù)
          --s6;
          // 單個 li 容器的高度
          --h36;
          // 單次動畫的時長
          --speed1.5s;
        }
        .g-container {
          width300px;
          heightcalc(var(--h) * 1px);
        }
        ul {
          display: flex;
          flex-direction: column;
          animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
        }
        ul li {
          width100%;
        }
        @keyframes move {
          0% {
            transformtranslate(00);
          }
          100% {
            transformtranslate(0, calc(var(--s) * var(--h) * -1px));
          }
        }

        別看到上述有幾個 CSS 變量就慌了,其實很好理解:

        1. calc(var(--speed) * var(--s)):單次動畫的耗時 * 輪播的個數(shù),也就是總動畫時長
        2. steps(var(--s)) 就是逐幀動畫的幀數(shù),這里也就是 steps(6),很好理解
        3. calc(var(--s) * var(--h) * -1px)) 單個 li 容器的高度 * 輪播的個數(shù),其實就是 ul 的總體高度,用于設(shè)置逐幀動畫的終點值

        上述的效果,實際如下:

        如果給容器添加上 overflow: hidden,就是這樣的效果:

        這樣,我們就得到了整體的結(jié)構(gòu),至少,整個效果是循環(huán)的。

        但是由于只是逐幀動畫,所以只能看到切換,但是每一幀之間,沒有過渡動畫效果。所以,接下來,我們還得引入補間動畫。

        利用補間動畫實現(xiàn)兩組數(shù)據(jù)間的切換

        我們需要利用補間動畫,實現(xiàn)動態(tài)的切換效果。

        這一步,其實也非常簡單,我們要做的,就是將一組數(shù)據(jù),利用 transform,從狀態(tài) A 位移到 狀態(tài) B。

        單獨拿出一個來演示的話,大致的代碼如下:

        <div class="g-container">
          <ul style="--s: 6">
            <li>Lorem ipsum 1111111</li>
            <li>Lorem ipsum 2222222</li>
            <li>Lorem ipsum 3333333</li>
            <li>Lorem ipsum 4444444</li>
            <li>Lorem ipsum 5555555</li>
            <li>Lorem ipsum 6666666</li>
          </ul>
        </div>
        :root {
          --h36;
          --speed1.2s;
        }
        ul li {
          height36px;
          animation: liMove calc(var(--speed)) infinite;
        }
        @keyframes liMove {
          0% {
            transformtranslate(00);
          }
          80%,
          100%  {
            transformtranslate(0, -36px);
          }
        }

        非常簡單的一個動畫:

        bgg1

        基于上述效果,我們?nèi)绻岩婚_始提到的 逐幀動畫 和這里這個 補間動畫 結(jié)合一下,ul 的整體移動,和 li 的 單個移動疊在在一起:

        :root {
          // 輪播的個數(shù)
          --s6;
          // 單個 li 容器的高度
          --h36;
          // 單次動畫的時長
          --speed1.5s;
        }
        .g-container {
          width300px;
          heightcalc(var(--h) * 1px);
        }
        ul {
          display: flex;
          flex-direction: column;
          animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
        }
        ul li {
          width100%;
          animation: liMove calc(var(--speed)) infinite;
        }
        @keyframes move {
          0% {
            transformtranslate(00);
          }
          100% {
            transformtranslate(0, calc(var(--s) * var(--h) * -1px));
          }
        }
        @keyframes liMove {
          0% {
            transformtranslate(00);
          }
          80%,
          100%  {
            transformtranslate(0, calc(var(--h) * -1px));
          }
        }

        就能得到這樣一個效果:

        Wow,神奇的化學(xué)反應(yīng)產(chǎn)生了!基于 逐幀動畫補間動畫 的結(jié)合,我們幾乎實現(xiàn)了一個輪播效果。

        當(dāng)然,有一點瑕疵,可以看到,最后一組數(shù)據(jù),是從第六組數(shù)據(jù) transform 移動向了一組空數(shù)據(jù):

        末尾填充頭部第一組數(shù)據(jù)

        實際開發(fā)過輪播的同學(xué)肯定知道,這里,其實也很好處理,我們只需要在末尾,補一組頭部的第一個數(shù)據(jù)即可:

        改造下我們的 HTML:

        <div class="g-container">
          <ul>
            <li>Lorem ipsum 1111111</li>
            <li>Lorem ipsum 2222222</li>
            <li>Lorem ipsum 3333333</li>
            <li>Lorem ipsum 4444444</li>
            <li>Lorem ipsum 5555555</li>
            <li>Lorem ipsum 6666666</li>
            <!--末尾補一個首條數(shù)據(jù)-->
            <li>Lorem ipsum 1111111</li>
          </ul>
        </div>

        這樣,我們再看看效果:

        Beautiful!如果你還有所疑惑,我們給容器加上 overflow: hidden,實際效果如下,通過額外添加的最后一組數(shù)據(jù),我們的整個動畫剛好完美的銜接上,一個完美的輪播效果:

        完整的代碼,你可以戳這里:CodePen Demo -- Vertical Infinity Loop[2]

        橫向無限輪播

        當(dāng)然,實現(xiàn)了豎直方向的輪播,橫向的效果也是一樣的。

        并且,我們可以通過在 HTML 結(jié)構(gòu)中,通過 style 內(nèi)填寫 CSS 變量值,傳入實際的 li 個數(shù),以達到根據(jù)不同 li 個數(shù)適配不同動畫:

        <div class="g-container">
          <ul style="--s: 6">
            <li>Lorem ipsum 1111111</li>
            <li>Lorem ipsum 2222222</li>
            <li>Lorem ipsum 3333333</li>
            <li>Lorem ipsum 4444444</li>
            <li>Lorem ipsum 5555555</li>
            <li>Lorem ipsum 6666666</li>
            <!--末尾補一個首尾數(shù)據(jù)-->
            <li>Lorem ipsum 1111111</li>
          </ul>
        </div>

        整個動畫的 CSS 代碼基本是一致的,我們只需要改變兩個動畫的 transform 值,從豎直位移,改成水平位移即可:

        :root {
          --w300;
          --speed1.5s;
        }
        .g-container {
          widthcalc(--w * 1px);
          overflow: hidden;
        }
        ul {
          display: flex;
          flex-wrap: nowrap;
           animation: move calc(var(--speed) * var(--s)) steps(var(--s)) infinite;
        }
        ul li {
          flex-shrink0;
          width100%;
          height100%;
          animation: liMove calc(var(--speed)) infinite;
        }
        @keyframes move {
          0% {
            transformtranslate(00);
          }
          100% {
            transformtranslate(calc(var(--s) * var(--w) * -1px), 0);
          }
        }
        @keyframes liMove {
          0% {
            transformtranslate(00);
          }
          80%,
          100%  {
            transformtranslate(calc(var(--w) * -1px), 0);
          }
        }

        這樣,我們就輕松的轉(zhuǎn)化為了橫向的效果:

        完整的代碼,你可以戳這里:CodePen Demo -- Horizontal Infinity Loop[3]

        輪播圖?不在話下

        OK,上面的只是文字版的輪播,那如果是圖片呢?

        沒問題,方法都是一樣的?;谏鲜龅拇a,我們可以輕松地將它修改一下后得到圖片版的輪播效果。

        代碼都是一樣的,就不再列出來,直接看看效果:

        完整的代碼,你可以戳這里:CodePen Demo -- Horizontal Image Infinity Loop[4]

        掌握了這個技巧之后,你可以將它運用在非常多只需要簡化版的輪播效果之上。

        再簡單總結(jié)一下,非常有意思的技巧:

        1. 利用 逐幀動畫,實現(xiàn)整體的輪播的循環(huán)效果
        2. 利用 補間動畫,實現(xiàn)具體的 *狀態(tài)A狀態(tài)B 的動畫效果
        3. 逐幀動畫 配合 補間動畫 構(gòu)成整體輪播的效果
        4. 通過向 HTML 結(jié)構(gòu)末尾補充一組頭部數(shù)據(jù),實現(xiàn)整體動畫的銜接
        5. 通過 HTML 元素的 style 標(biāo)簽,利用 CSS 變量,填入實際的參與循環(huán)的 DOM 個數(shù),可以實現(xiàn) JavaScript 與 CSS 的打通

        參考資料

        [1]

        深入淺出 CSS 動畫: https://github.com/chokcoco/iCSS/issues/141

        [2]

        CodePen Demo -- Vertical Infinity Loop: https://codepen.io/Chokcoco/pen/RwQVByx

        [3]

        CodePen Demo -- Horizontal Infinity Loop: https://codepen.io/Chokcoco/pen/JjpNBXY

        [4]

        CodePen Demo -- Horizontal Image Infinity Loop: https://codepen.io/Chokcoco/pen/GRQvqgq

        [5]

        Github -- iCSS: https://github.com/chokcoco/iCSS


        瀏覽 48
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 娇小xXXXBXBⅨ黑人XX | 精品国产一区二区三区麻豆小说 | 成人做爱在线 | 男人操女人的app | 伊人成人在线视频观看 |