如何使用css3實現一個類在線直播的隊列動畫

以前在羣裏有個朋友問了這樣一個問題, 就是如何在小程序中實現相似直播平臺的用戶上線時的隊列動畫? 做爲一名前端工程師, 解決方案無非如下2種:javascript

  1. 使用javascript根據條件來控制元素的樣式實現隊列動畫
  2. 用純css3配合數據驅動模型來實現.

你們都知道在現代的Web開發中, 咱們能使用Css實現的效果儘可能不要用Js, 因此咱們應該優先考慮用Css3來實現,可是咱們要結合數據流才能實現真正的隊列動畫, 因此咱們能夠利用MVVM框架便捷的數據驅動模型來控制動畫的走向.css

又因爲動畫的核心在於Css3, 因此在小程序或者是Vue/React中實現其實原理都是類似的, 你們沒必要擔憂技術棧的問題. 如下是實現後的效果圖: html

若是以上gif沒法訪問, 能夠查看下面的靜態圖:

其實這種效果在不少地方都用到, 好比B站的彈幕, 某音樂平臺直播的粉絲上線動畫, 某音的直播等等, 而在Web端, 咱們又能怎麼實現它呢? 接下來筆者將帶你們一步步實現這樣的動畫效果.前端

正文

要想實現上面的動畫效果, 咱們須要先分析一下動畫, 上圖的動畫結構以下: vue

動畫一共分爲如下兩個過程:

  • 用戶進入動畫
  • 用戶淡出動畫

還有一個細節就是無論進入多少個用戶, 都是從同一個位置進入的, 此時上一個用戶位置會上移,以下圖所示: java

因此要想實現這樣的效果最好的方式就是使用定位,好比絕對定位( absolute)或者固定定位( fixed). 並設置其 bottom值, 以下代碼所示:

.animateWrap {
    position: absolute;
    bottom: 40%;
    left: 12px;
}
複製代碼

以上位置信息僅供參考,具體數值可根據自身需求來更改.設置bottom的好處是容器的子元素一旦增長, 會自動將上一個元素頂上去, 因此不須要咱們手動去設置其偏移值.node

實現進入動畫

咱們要想實現上圖的用戶進入動畫, 可使用Css3的過渡動畫transition,也可使用animation動畫, 因爲使用場景的便捷性這裏咱們採用animation動畫, 首先咱們先寫一下dom結構:react

<div className={styles.animateWrap}>
    <div className={styles.animate} key={item}><div className={styles.tx}><img src={tx} alt=""/></div><span>李老師上線</span></div>
    <div className={styles.animate} key={item}><div className={styles.tx}><img src={tx} alt=""/></div><span>李老師上線</span></div>
    <div className={styles.animate} key={item}><div className={styles.tx}><img src={tx} alt=""/></div><span>李老師上線</span></div>
  </div>
複製代碼

以上代碼表示建立了一個動畫容器, 而且添加了2個用戶, 這裏咱們定義一下關鍵動畫以下:css3

.animate {
      margin-bottom: 10px;
      border-radius: 20px;
      background-color: rgba(0,0,0, .3);
      animation: moveIn 1.2s;
    }
@keyframes moveIn {
  0% {
    transform: translateX(calc(-100% - 12px));
  }
  100% {
    transform: translateX(0);
  }
}
複製代碼

以上即實現了元素向右移入的動畫, 可是此時咱們看到的動畫是同時出現的, 咱們要應用到真實場景中, 必定是經過socket或者經過輪循拿到的異步數據, 所以咱們可使用setInterval來模擬這一過程. 還有一個細節是咱們動畫裏最多隻完整展現2條用戶數據, 多餘的數據會漸出隱藏, 所以咱們須要對數據進行截流, 代碼以下:程序員

const [user, setUser] = useState<Array<string>>([])
  useEffect(() => {
    let MAX_USER_COUNT = 2;
    let timer = setInterval(() => {
      setUser(prev => {
        prev.push(Date.now() + '')
        if(prev.length > MAX_USER_COUNT + 1){
          prev.shift()
          return [...prev]
        }else {
          return [...prev]
        }
      })
    }, 2000)
  }, [])
複製代碼

變量MAX_USER_COUNT用來控制最大展現的用戶數,能夠根據實際需求更改, setUser裏面的邏輯即爲截流邏輯, 當用戶數超過指定的最大值時, 會將頭部元素刪除.

以上即完成了數據流轉的過程, 咱們還須要處理的是用戶漸出邏輯和動畫.咱們先看看漸出的animation:

@keyframes moveOut {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}
複製代碼

其實動畫並不難, 咱們須要控制的是如何給頭部元素動態的添加這個動畫, 此時咱們最好的方案是經過類名, 即當知足漸出的條件時, 咱們須要給漸出的元素動態設置漸出類名, 條件以下:

  • user.length > MAX_USER_COUNT && i === 0 以上條件指的是當用戶數超過最大展現用戶數而且當且元素爲頭部元素時, 那麼咱們只須要根據這個條件來動態設置類名便可:
{
  user.map((item, i) => {
     return  <div className={classnames(styles.animate, user.length > 2 && i === 0 ? styles.hidden : '')} key={item}><div className={styles.tx}><img src={tx} alt=""/></div><span>李老師{item}上線</span></div> }) } 複製代碼

css代碼以下:

.hidden {
  opacity: 0;
  animation: moveOut 1.2s;
}
複製代碼

經過以上步驟咱們就實現了一個完整的類在線直播的隊列動畫, 動畫完整css代碼以下, 感興趣的盆友能夠學習參考一下:

.animateWrap {
    position: absolute;
    bottom: 40%;
    left: 12px;
    .animate {
      margin-bottom: 10px;
      border-radius: 20px;
      background-color: rgba(0,0,0, .3);
      animation: moveIn 1.2s;
      .tx {
        display: inline-block;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        overflow: hidden;
        vertical-align: middle;
        margin-right: 10px;
        img {
          width: 100%;
          height: 100%;
          object-fit: cover;
        }
      }
      span {
        margin-right: 12px;
        line-height: 36px;
        font-size: 14px;
        color: #fff;
      }
    }
    .hidden {
      opacity: 0;
      animation: moveOut 1.2s;
    }
    @keyframes moveIn {
      0% {
        transform: translateX(calc(-100% - 12px));
      }
      100% {
        transform: translateX(0);
      }
    }
    @keyframes moveOut {
      0% {
        opacity: 1;
      }
      100% {
        opacity: 0;
      }
    }
  }
複製代碼

最後

若是想學習更多前端技能,實戰學習路線, 歡迎在公衆號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。

更多推薦

相關文章
相關標籤/搜索