首頁  >  文章  >  web前端  >  手把手教你用 transition 實作短影片 APP的讚動畫

手把手教你用 transition 實作短影片 APP的讚動畫

青灯夜游
青灯夜游轉載
2022-09-07 10:45:022021瀏覽

怎麼使用純 CSS 實現有趣的讚動畫?以下這篇文章就帶大家了解巧妙借助 transition實現讚動畫的方法,希望對大家有幫助!

手把手教你用 transition 實作短影片 APP的讚動畫

在各種短視訊介面上,我們經常會看到類似這樣的讚動畫:

非常的有意思,有意思的互動會讓使用者更願意互動。

那麼,這麼有趣的讚動畫,有沒有可能使用純 CSS 實作呢?那當然是必須的,本文,就將巧妙的借助 transition,僅僅使用 CSS 完成這麼一個讚動畫。 【推薦學習:css影片教學

實作不同表情的不斷上升

如果使用純 CSS 實作這一整套動畫的話。我們首先需要實現一段無限循環的,大量不同的表情不斷向上漂浮的動畫

像是這樣:

這個整體還是比較容易實現的,核心原理就是同一個動畫,設定不同的transition-durationtransition-dalay,和一定範圍內的旋轉角度。

我們首先要實現多個表情,一個 DOM 標籤放入一個隨機的表情。

我們可以手動一個一個的新增:

<ul class="g-wrap">
    <li>?</li>
    <li>❤️</li>
    <li>?</li>
    // ... 随机设置不同的表情符号,共 50 个
    <li>...</li>
</ul>

當然,我個人覺得這樣太麻煩。我習慣利用 SASS 的循環函數及隨機函數,利用偽元素的 content 去隨機產生不同表情。像是這樣:

<ul class="g-wrap">
    <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-delayopacity: 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 class="g-wrap">
    <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

一点瑕疵

当然,这个方案是有一点点问题的。

  • 1、就是如果当点击的速率过快,是无法实现一个点击,产生一个表情的

这是由于 CSS 方案的本质是通过点击一个透明表情,让它变成不透明。而点击过快的话,会导致两次或者多次点击,点在了同一个元素上,这样,就无法实现一个点击,产生一个表情。所以上面代码中修改缓动 cubic-bezier(.46,.53,.51,.62) 的目的也是在于,让元素动画前期运动更快,这样可以有利于适配更快的点击速率。

  • 2、不仅仅是点击按钮,点击按钮上方也能出现效果

这样也很好理解,由于本质是个障眼法,所以点击按钮上方,只要是元素运动路径的地方,也是会有元素显形的。这个硬要解决也可以,通过再叠加一层透明元素在按钮上方,通过层级关系屏蔽掉点击事件。

  • 3、表情的随机只是伪随机

利用 SASS 随机的方案在经过编译后是不会产生随机效果的。所以,这里只能是伪随机,基于 DOM 的个数,当 DOM 数越多,整体而言,随机的效果越好。基本上 50 个 DOM 是比较足够的。

  • 4、CSS 版本的点赞效果是单机版

无法多用户联动,可能是影响能不能实际使用最为关键的因素。

不過,總而言之,使用純 CSS 實現的方案,整體效果還是不錯的。

(學習影片分享:web前端

以上是手把手教你用 transition 實作短影片 APP的讚動畫的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除