以前在羣裏有個朋友問了這樣一個問題, 就是如何在小程序中實現相似直播平臺的用戶上線時的隊列動畫? 做爲一名前端工程師, 解決方案無非如下2種:javascript
你們都知道在現代的Web開發中, 咱們能使用Css實現的效果儘可能不要用Js, 因此咱們應該優先考慮用Css3來實現,可是咱們要結合數據流才能實現真正的隊列動畫, 因此咱們能夠利用MVVM框架便捷的數據驅動模型來控制動畫的走向.css
又因爲動畫的核心在於Css3, 因此在小程序或者是Vue/React中實現其實原理都是類似的, 你們沒必要擔憂技術棧的問題. 如下是實現後的效果圖: html
其實這種效果在不少地方都用到, 好比B站的彈幕, 某音樂平臺直播的粉絲上線動畫, 某音的直播等等, 而在Web端, 咱們又能怎麼實現它呢? 接下來筆者將帶你們一步步實現這樣的動畫效果.前端
要想實現上面的動畫效果, 咱們須要先分析一下動畫, 上圖的動畫結構以下: vue
還有一個細節就是無論進入多少個用戶, 都是從同一個位置進入的, 此時上一個用戶位置會上移,以下圖所示: java
.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.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;
}
}
}
複製代碼
若是想學習更多前端技能,實戰和學習路線, 歡迎在公衆號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。