如何使用css3實(shí)現(xiàn)一個(gè)類在線直播的隊(duì)列動(dòng)畫(huà)的示例代碼

之前在群里有個(gè)朋友問(wèn)了這樣一個(gè)問(wèn)題, 就是如何在 小程序 中實(shí)現(xiàn)類似 直播平臺(tái) 的用戶上線時(shí)的 隊(duì)列動(dòng)畫(huà) ? 作為一名前端工程師, 解決方案無(wú)非以下2種:
- 使用 javascript 根據(jù)條件來(lái)控制元素的樣式實(shí)現(xiàn)隊(duì)列動(dòng)畫(huà)
- 用純 css3 配合數(shù)據(jù)驅(qū)動(dòng)模型來(lái)實(shí)現(xiàn).
大家都知道在現(xiàn)代的 Web 開(kāi)發(fā)中, 我們能使用 Css 實(shí)現(xiàn)的效果盡量不要用 Js , 所以我們應(yīng)該優(yōu)先考慮用 Css3 來(lái)實(shí)現(xiàn),但是我們要結(jié)合 數(shù)據(jù)流 才能實(shí)現(xiàn)真正的隊(duì)列動(dòng)畫(huà), 所以我們可以利用 MVVM框架 便捷的數(shù)據(jù)驅(qū)動(dòng)模型來(lái)控制動(dòng)畫(huà)的走向.
又由于動(dòng)畫(huà)的核心在于 Css3 , 所以在 小程序 或者是 Vue/React 中實(shí)現(xiàn)其實(shí)原理都是相似的, 大家不必?fù)?dān)心技術(shù)棧的問(wèn)題. 以下是實(shí)現(xiàn)后的效果圖:
其實(shí)這種效果在很多地方都用到, 比如 B站 的彈幕, 某音樂(lè)平臺(tái)直播的粉絲上線動(dòng)畫(huà), 某音的直播等等, 而在 Web端 , 我們又能怎么實(shí)現(xiàn)它呢? 接下來(lái)筆者將帶大家一步步實(shí)現(xiàn)這樣的動(dòng)畫(huà)效果.
正文
要想實(shí)現(xiàn)上面的動(dòng)畫(huà)效果, 我們需要先分析一下動(dòng)畫(huà), 上圖的動(dòng)畫(huà)結(jié)構(gòu)如下:
動(dòng)畫(huà)一共分為以下兩個(gè)過(guò)程:
- 用戶進(jìn)入動(dòng)畫(huà)
- 用戶淡出動(dòng)畫(huà)
還有一個(gè)細(xì)節(jié)就是不管進(jìn)入多少個(gè)用戶, 都是從同一個(gè)位置進(jìn)入的, 此時(shí)上一個(gè)用戶位置會(huì)上移,如下圖所示:
所以要想實(shí)現(xiàn)這樣的效果最好的方式就是使用定位,比如絕對(duì)定位( absolute )或者固定定位( fixed ). 并設(shè)置其 bottom
值, 如下代碼所示:
.animateWrap { position: absolute; bottom: 40%; left: 12px; }
以上位置信息僅供參考,具體數(shù)值可根據(jù)自身需求來(lái)更改.設(shè)置 bottom 的好處是容器的子元素一旦增加, 會(huì)自動(dòng)將上一個(gè)元素頂上去, 所以不需要我們手動(dòng)去設(shè)置其偏移值.
實(shí)現(xiàn)進(jìn)入動(dòng)畫(huà)
我們要想實(shí)現(xiàn)上圖的用戶進(jìn)入動(dòng)畫(huà), 可以使用 Css3 的過(guò)渡動(dòng)畫(huà) transition ,也可以使用 animation 動(dòng)畫(huà), 由于使用場(chǎng)景的便捷性這里我們采用 animation 動(dòng)畫(huà), 首先我們先寫(xiě)一下dom結(jié)構(gòu):
<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>
以上代碼表示創(chuàng)建了一個(gè)動(dòng)畫(huà)容器, 并且添加了2個(gè)用戶, 這里我們定義一下關(guān)鍵動(dòng)畫(huà)如下:
.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); } }
以上即實(shí)現(xiàn)了元素向右移入的動(dòng)畫(huà), 但是此時(shí)我們看到的動(dòng)畫(huà)是同時(shí)出現(xiàn)的, 我們要應(yīng)用到真實(shí)場(chǎng)景中, 一定是通過(guò) socket 或者通過(guò) 輪循 拿到的異步數(shù)據(jù), 因此我們可以使用 setInterval 來(lái)模擬這一過(guò)程. 還有一個(gè)細(xì)節(jié)是我們動(dòng)畫(huà)里最多只完整展示2條用戶數(shù)據(jù), 多余的數(shù)據(jù)會(huì)漸出隱藏, 因此我們需要對(duì)數(shù)據(jù)進(jìn)行截流, 代碼如下:
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 用來(lái)控制最大展示的用戶數(shù),可以根據(jù)實(shí)際需求更改, setUser 里面的邏輯即為截流邏輯, 當(dāng)用戶數(shù)超過(guò)指定的最大值時(shí), 會(huì)將頭部元素刪除.
以上即完成了數(shù)據(jù)流轉(zhuǎn)的過(guò)程, 我們還需要處理的是用戶漸出邏輯和動(dòng)畫(huà).我們先看看漸出的 animation :
@keyframes moveOut { 0% { opacity: 1; } 100% { opacity: 0; } }
其實(shí)動(dòng)畫(huà)并不難, 我們需要控制的是如何給頭部元素動(dòng)態(tài)的添加這個(gè)動(dòng)畫(huà), 此時(shí)我們最好的方案是通過(guò)類名, 即當(dāng)滿足漸出的條件時(shí), 我們需要給漸出的元素動(dòng)態(tài)設(shè)置漸出類名, 條件如下:
user.length > MAX_USER_COUNT && i === 0 以上條件指的是當(dāng)用戶數(shù)超過(guò)最大展示用戶數(shù)并且當(dāng)且元素為頭部元素時(shí), 那么我們只需要根據(jù)這個(gè)條件來(lái)動(dòng)態(tài)設(shè)置類名即可:
{ 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; }
通過(guò)以上步驟我們就實(shí)現(xiàn)了一個(gè)完整的類在線直播的隊(duì)列動(dòng)畫(huà), 動(dòng)畫(huà)完整 css 代碼如下, 感興趣的盆友可以學(xué)習(xí)參考一下:
.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; } } }
最后
到此這篇關(guān)于如何使用css3實(shí)現(xiàn)一個(gè)類在線直播的隊(duì)列動(dòng)畫(huà)的示例代碼的文章就介紹到這了,更多相關(guān)css3在線直播隊(duì)列動(dòng)畫(huà)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持腳本之家!
相關(guān)文章
css3實(shí)現(xiàn)動(dòng)畫(huà)的三種方式
這篇文章主要介紹了css3實(shí)現(xiàn)動(dòng)畫(huà)的三種方式,幫助大家更好的理解和學(xué)習(xí)css3,感興趣的朋友可以了解下2020-08-24- 有好多小伙伴私聊我問(wèn)我html5新特性 和用法,下面我給大家具體介紹一下html5都新加了哪些新特性,感興趣的朋友跟隨腳本之家小編一起看看吧2018-09-13
使用html5新特性輕松監(jiān)聽(tīng)任何App自帶返回鍵的示例
這篇文章主要介紹了使用html5新特性輕松監(jiān)聽(tīng)任何App自帶返回鍵的示例的相關(guān)資料,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-13- 這篇文章主要介紹了HTML5新特性之type=file文件上傳功能,需要的朋友可以參考下2018-02-02
- HTML5 只有一個(gè)簡(jiǎn)單的文檔類型:<!DOCTYPE html>,表示瀏覽器會(huì)按照標(biāo)準(zhǔn)模式解析。今天小編給大家?guī)?lái)了HTML5新特性之語(yǔ)義化標(biāo)簽,感興趣的朋友一起看看吧2017-10-31
- HTML5想必大家都很熟悉了,因?yàn)樘嗟拿襟w在討論這一技術(shù)。所以當(dāng)我們?cè)诿嬖嚽岸斯ぷ鞯臅r(shí)候,遇到html5相關(guān)的問(wèn)題一點(diǎn)也不意外,想要順利通過(guò)前端面試?下面這篇文章就來(lái)跟2017-09-05
- 這篇文章主要介紹了CSS3動(dòng)畫(huà)和HTML5新特性詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-31