在各種短視頻界面上,我們經常會看到類似這樣的點贊影片:
非常的有意思,有意思的互動會讓用戶更愿意進行互動,
那么,這么有趣的點贊影片,有沒有可能使用純 CSS 實作呢?那當然是必須的,本文,就將巧妙的借助 transition,僅僅使用 CSS 完成這么一個點贊影片,
實作不同表情的不斷上升
如果使用純 CSS 實作這一整套影片的話,我們首先需要實作一段無限回圈的,大量不同的表情不斷向上漂浮的影片,
像是這樣:
這個整體還是比較容易實作的,核心原理就是同一個影片,設定不同的 transition-duration,transition-dalay,和一定范圍內的旋轉角度,
我們首先要實作多個表情,一個 DOM 標簽放入一個隨機的表情,
我們可以手動一個一個的添加:
<ul >
<li>??</li>
<li>??</li>
<li>??</li>
// ... 隨機設定不同的表情符號,共 50 個
<li>...</li>
</ul>
當然,我個人覺得這樣太麻煩,我習慣利用 SASS 的回圈函式及隨機函式,利用偽元素的 content 去隨機生成不同表情,像是這樣:
<ul >
<li></li>
<li></li>
<li></li>
// ... 共50個空標簽
</ul>
$expression: "??", "??", "??", "??", "??", "??", "??", "??", "????", "??", "??", "??", "??", "??";
.g-wrap {
position: relative;
width: 50px;
height: 50px;
}
@for $i from 1 to 51 {
li:nth-child(#{$i}) {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
&::before {
content: nth($expression, random(length($expression)));
position: absolute;
font-size: 50px;
}
}
}
這樣,我們就能得到 50 個疊加在一起的表情:
因為透明度為 1 的緣故,只能看到最上面的幾個表情,實際上這里疊加了 50 個不同的表情,
這里的核心就是 content: nth($expression, random(length($expression))),我們利用了 SASS 的 random 和 length 和 nth 等方法,隨機的將 $expression 串列中的表情,添加給了不同的 li 的 before 偽元素的 content 內,
接下來,我們需要讓它們動起來,
這個簡單,添加一個無限的 transform: translate() 影片即可:
@for $i from 1 to 51 {
li:nth-child(#{$i}) {
animation: move 3000ms infinite linear;
}
}
@keyframes move {
100% {
transform: translate(0, -250px);
}
}
效果如下:
OK,由于 50 個元素都疊加在一起,所以我們需要將影片區分開來,我們給它們添加隨機的影片時長,并且,賦予不同的負 transition-delay 值:
@for $i from 1 to 51 {
li:nth-child(#{$i}) {
animation: move #{random() * 2500 + 1500}ms infinite #{random() * 4000 / -1000}s linear;
}
}
@keyframes move {
100% {
transform: translate(0, -250px);
}
}
效果如下:
效果已經非常接近我們想要的了!這里有一點點的跳躍,需要理解 move #{random() * 2500 + 1500}ms infinite #{random() * 4000 / -1000}s linear 這里大段代碼:
#{random() * 2500 + 1500}ms生成 1500ms ~ 4000ms 之間的亂數,表示影片的持續時長#{random() * 4000 / -1000}s生成 -4000ms ~ 0s 之間的亂數,表示負的影片延遲量,這樣做的目的是為了讓影片提前進行
如果你對負的
transition-delay的作用還不了解,可以看看我的這篇文章 -- 深入淺出 CSS 影片
到這,還是不夠隨機,我們再通過隨機添加一個較小的旋轉角度,讓整體的效果更加的隨機:
@for $i from 1 to 51 {
li:nth-child(#{$i}) {
transform: rotate(#{random() * 80 - 40}deg);
animation: move #{random() * 2500 + 1500}ms infinite #{random() * 4000 / -1000}s linear;
}
}
@keyframes move {
100% {
transform: rotate(0) translate(0, -250px);
}
}
這里 transform: rotate(#{random() * 80 - 40}deg) 的作用就是隨機生成 -40deg ~ 40deg 的亂數,產生一個隨機的角度,
至此,我們就得到了這樣一個效果:
利用 transition 化腐朽為神奇
到這里,很多同學可能還不明白,明明是點贊一次產生一個表情,為什么需要一次生成這么多不斷運動的表情效果呢?
這是因為,由于 CSS 沒法直接正面做到點擊一次,生成一個表情,所以我們需要換一種思路實作,
如果這些表情一直都是在運動的,只不過不點擊的時候,它們的透明度都為 0,我們要做的,就是當我們點擊的時候,讓它們從 opacity: 0 變到 opacity: 1,
要實作這一點,我們需要巧妙的用到 transition,
我們以一個表情為例子:
- 默認它的透明度為
opacity: 0.1 - 點擊的時候,它的透明度瞬間變成
opacity: 1 - 然后,通過
transition-delay讓opacity: 1的狀態保持一段時間后 - 逐漸再消失,變回
opacity: 0.1
看上去有億點點復雜,代碼會更容易理解:
li {
opacity: .1;
transition: 1.5s opacity 0.8s;
}
li:active {
opacity: 1;
transition: .1s opacity;
}
效果如下:
一定要理解上面的代碼!巧妙地利用 transition 在正常狀態和 active 狀態下的變化,我們實作了這種巧妙的點擊效果,
如果我們把初始的 opacity: 0.1 改成 opacity: 0 呢?就會是這樣:
好,我們結合一下上面兩個影片:
- 我們將所有的表情,默認的透明度改為
0.1 - 被點擊的時候,透明度變成
1 - 透明度在
1維持一段時間,逐漸消失
代碼如下:
@for $i from 1 to 51{
li:nth-child(#{$i}) {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
transform: rotate(#{random() * 80 - 40}deg);
animation: move #{random() * 2500 + 1500}ms infinite #{random() * 4000 / -1000}s linear;
opacity: .1;
transition: 1.5s opacity .8s;
&::before {
content: nth($expression, random(length($expression)));
position: absolute;
}
}
li:active {
opacity: 1;
transition: .1s opacity;
}
}
@keyframes move {
100% {
transform: rotate(0) translate(0, -250px);
}
}
效果如下:
嘿,是不是有那么點意思了!
好最后一步,我們通過一個點擊按鈕引導用戶點擊,并且給與一個點擊反饋,每次點擊的時候,點贊按鈕放大 1.1 倍,同時,我們把默認表情的透明度從 opacity: 0.1 徹底改為 opacity: 0,
這樣,整個影片的完整的核心代碼:
<ul >
<li></li>
<li></li>
<li></li>
// ... 共50個空標簽
</ul>
$expression: "??", "??", "??", "??", "??", "??", "??", "??", "????", "??", "??", "??", "??", "??";
.g-wrap {
position: relative;
width: 50px;
height: 50px;
&::before {
content: "????";
position: absolute;
width: 50px;
height: 50px;
transition: 0.1s;
}
&:active::before {
transform: scale(1.1);
}
}
@for $i from 1 to 51 {
li:nth-child(#{$i}) {
position: absolute;
width: 50px;
height: 50px;
transform: rotate(#{random() * 80 - 40}deg);
animation: move #{random() * 2500 + 1500}ms infinite #{random() * 4000 / -1000}s cubic-bezier(.46,.53,.51,.62);
opacity: 0;
transition: 1.5s opacity .8s;
&::before {
content: nth($expression, random(length($expression)));
position: absolute;
}
}
li:active {
transition: .1s opacity;
opacity: 1!important;
}
}
@keyframes move {
100% {
transform: rotate(0) translate(0, -250px);
}
}
這里,需要注意的是:
- 點贊的按鈕,通過了父元素
.g-wrap的偽元素實作,這樣的好處是,子元素 li 的:active點擊事件,是可以冒泡傳給父元素的,這樣每次子元素被點擊,我們都可以放大一次點贊按鈕,用于實作點擊反饋, - 稍微修改一下緩動函式,讓整體效果更為均衡合理
這樣,我們就得到了題圖一開始的效果,利用純 CSS 實作的點贊影片:
完整的代碼,你可以戳這里:CodePen Demo -- Like Animation
一點瑕疵
當然,這個方案是有一點點問題的,
- 就是如果當點擊的速率過快,是無法實作一個點擊,產生一個表情的
這是由于 CSS 方案的本質是通過點擊一個透明表情,讓它變成不透明,而點擊過快的話,會導致兩次或者多次點擊,點在了同一個元素上,這樣,就無法實作一個點擊,產生一個表情,所以上面代碼中修改緩動 cubic-bezier(.46,.53,.51,.62) 的目的也是在于,讓元素影片前期運動更快,這樣可以有利于適配更快的點擊速率,
- 不僅僅是點擊按鈕,點擊按鈕上方也能出現效果
這樣也很好理解,由于本質是個障眼法,所以點擊按鈕上方,只要是元素運動路徑的地方,也是會有元素顯形的,這個硬要解決也可以,通過再疊加一層透明元素在按鈕上方,通過層級關系屏蔽掉點擊事件,
- 表情的隨機只是偽隨機
利用 SASS 隨機的方案在經過編譯后是不會產生隨機效果的,所以,這里只能是偽隨機,基于 DOM 的個數,當 DOM 數越多,整體而言,隨機的效果越好,基本上 50 個 DOM 是比較足夠的,
- CSS 版本的點贊效果是單機版
無法多用戶聯動,可能是影響能不能實際使用最為關鍵的因素,
不過,總而言之,使用純 CSS 實作的方案,整體效果還是不錯的,
最后
怎樣,其實也不是很難吧?好了,本文到此結束,希望本文對你有所幫助 ??
更多精彩 CSS 技術文章匯總在我的 Github -- iCSS ,持續更新,歡迎點個 star 訂閱收藏,
如果還有什么疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/503197.html
標籤:Html/Css
下一篇:JS-陣列
