直播系統中網頁類似app頁面切換動畫的實現方式

雲豹科技程式設計師發表於2021-10-10

直播系統app開啟一個頁面時,有時會看到這麼一種動畫:當前頁的某些元素跳到下一個頁面上。

那麼直播系統網頁端有沒有辦法實現這種類似於直播系統app端頁面切換的動畫效果呢?經過探索,發現谷歌瀏覽器已經提供了這麼一個實驗性API:

documentTransition

它是一種新的指令碼API的提議,允許在單頁應用程式(SPA)和多頁應用程式(MPAs)中使用一組簡單的過渡動畫。這個特性的靈感來自於Material Design原則中列出的過渡。其目的是支援類似於Android Activity transitions的過渡動畫效果。

瀏覽器開啟該功能API

由於該特性是實驗功能,需要手動開啟。在瀏覽器中輸入

chrome://flags/#document-transition

然後將documentTransition設定為Enabled啟用。
在這裡插入圖片描述

設定完之後我們重啟下瀏覽器,然後開啟控制檯輸入:

'documentTransition' in document

結果列印為true的話,說明我們瀏覽器已經成功開啟該實驗功能API。
在這裡插入圖片描述

如何理解該API

該API提案可以分為兩部分:根轉換(root transition)和共享元素轉換(shared element transition)。
根轉換(root transition)
根轉換可以理解為直播系統"頁面“在載入時的動畫過渡效果,如直播系統iOS端點選跳轉下一個頁面時,下一個頁面是從右到左推入的。下面程式碼實現該效果(注意:效果跟直播系統APP差異較大,總體效果是能看出“頁面”是從右到左推入的,請自行執行程式碼在瀏覽器中檢視效果):

<!DOCTYPE html><html lang="en">
  <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>rootTransition示例</title>
  </head>
  <style>
    .list {
      height: 100vh;
    }
    .details {
      height: 100vh;
      background-color: aquamarine;
    }
    .hide {
      display: none;
    }
  </style>
  <body>
    <div class="list">
      列表頁      <button id="btn">點選去詳情頁</button>
    </div>
    <div class="details hide">詳情頁</div>
    <script>
      const btn = document.querySelector('#btn')
      const details = document.querySelector('.details')
      const list = document.querySelector('.list')
      btn.addEventListener('click', () => {
        navigateToDetailsPage()
      })
      async function navigateToDetailsPage() {
        await document.documentTransition.prepare({
          rootTransition: "cover-left",
        });
        details.classList.remove('hide')
        list.classList.add('hide')
        document.documentTransition.start();
      }
    </script>
  </body></html>

以上就是一個root transition的例子,它的使用模型可以概括如下:

// 使用者點選按鈕切換頁面時執行async function navigateToSettingsPage() {
  // 捕捉當前頁面狀態,進行動畫準備
  await document.documentTransition.prepare({
    rootTransition: 'cover-left', // “頁面”切換效果
  });
  // 執行更新DOM操作,顯示下一頁的內容
  updateDOMForNextPage();
  // 呼叫start開始執行動畫
  await document.documentTransition.start();
  // 動畫結束}

支援的動畫效果
rootTransition支援以下屬性:

  • reveal-left: 舊內容從中心向指定方向滑動,顯示新內容。
  • reveal-right
  • reveal-up
  • reveal-down
  • cover-left: 新內容沿指定方向從邊緣滑動,覆蓋舊內容。
  • cover-right
  • cover-up
  • cover-down
  • explode: 舊內容通過成長和變得更加透明而“爆炸”,並揭示出新的內容。
  • implode: 新內容會“內爆”,從大的一面收縮,變得不透明,轉換舊內容。

共享元素轉換(shared element transition)
共享元素就是使用者頭像及名字,可以看到這兩個元素從直播系統當前頁到下一頁載入完時是一直處於可視狀態的,並且從直播系統當前頁顯示位置大小到下一頁顯示位置大小有一個平滑過渡的效果。

如何使用shared element

async function navigateToSettingsPage() {
  await document.documentTransition.prepare({
    rootTransition: 'cover-up',
    sharedElements: [element1, element2, element3],
  });
  // updateDOM
  await document.documentTransition.start({
    sharedElements: [element1, element4, element5],
  });}

sharedElements是一個陣列,裡面存放“跨頁”共享的元素,對應動圖的例子來說就是存放使用者的頭像及名字的dom。
需要注意的是:

1、在prepare及start方法中都要設定sharedElements屬性,並且是一一對應的關係。例如element2在切換到“下一頁”時,對應過渡到的就是element4所在位置。
2、需要配合css的contain屬性才能正常工作,通常設定為contain: paint;該屬性的作用是如果一個元素在視窗外或因其他原因導致不可見,則同樣保證它的子孫節點不會被顯示。詳見:contain

完整程式碼:

<!DOCTYPE html><html lang="en"><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>rootTransition示例</title></head><style>body{margin:0}.flex-center{display:flex;align-items:center;justify-content:center}.list{height:100vh}.details{height:100vh}.hide{display:none!important}.card{display:flex;align-items:center;margin:0 20px;box-shadow:0 0 50px #ccc;border-radius:12px;overflow:hidden}.card .desc{font-size:18px;color:#333;font-weight:bold;margin-left:20px}.details-desc{font-size:22px;color:limegreen}.list{display:flex;flex-direction:column;justify-content:center}.button-wrap{margin-top:20px;text-align:center}.back-btn{display:inline-block;width:100px;height:40px}.details-cover{display:block;width:100%}.details-desc{position:absolute;right:20px;top:20px}.cover,.details-cover,.desc,.details-desc{contain:paint}</style><body>
    <div class="list">
        <div class="card">
            <img class="cover"
                src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fstrip%2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" />
            <span class="desc">人生海海</span>
        </div>
        <div class="button-wrap">
            <button id="btn">點選去詳情頁</button>
        </div>
    </div>
    <div class="details hide">
        <div>
            <div style="position: relative;">
                <img class="details-cover"
                    src="http://p1-q.mafengwo.net/s18/M00/52/27/CoUBYGDMNO-AOlK4AAVHKFDW8_Y808.jpg?imageMogr2%2Fthumbnail%2F%21220x150r%2Fstrip%2Fgravity%2FCenter%2Fcrop%2F%21220x150%2Fquality%2F90" />
                <div class="details-desc">人生海海</div>
            </div>
            <div class="button-wrap">
                <button class="back-btn">返回</button>
            </div>
        </div>
    </div>
    <script>
        const btn = document.querySelector('#btn')
        const details = document.querySelector('.details')
        const list = document.querySelector('.list')
        const backBtn = document.querySelector('.back-btn')
        const cover = document.querySelector('.cover')
        const desc = document.querySelector('.desc')
        const detailsCover = document.querySelector('.details-cover')
        const detailsDesc = document.querySelector('.details-desc')
        btn.addEventListener('click', () => {
            navigateToDetailsPage()
        }, false)
        backBtn.addEventListener('click', () => {
            showList()
        }, false)
        async function navigateToDetailsPage() {
            await document.documentTransition.prepare({
                rootTransition: "cover-up",
                sharedElements: [
                    cover,
                    desc                ]
            });
            details.classList.remove('hide')
            list.classList.add('hide')
            document.documentTransition.start({
                sharedElements: [
                    detailsCover,
                    detailsDesc                ]
            });
        }
        async function showList() {
            await document.documentTransition.prepare({
                rootTransition: "implode",
                sharedElements: [
                    detailsCover,
                    detailsDesc                ]
            });
            details.classList.add("hide");
            list.classList.remove("hide");
            await document.documentTransition.start({
                sharedElements: [
                    cover,
                    desc                ]
            });
        }
    </script></body></html>

以上就是“直播系統網頁如何實現類似app的頁面切換動畫?”的全部內容,在直播哦系統開發時需要我們注意的細節點有很多,希望以上內容能對大家有幫助。

本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2795231/,如需轉載,請註明出處,否則將追究法律責任。

相關文章