关于前端:巧用-transition-实现短视频-APP-点赞动画

5次阅读

共计 4811 个字符,预计需要花费 13 分钟才能阅读完成。

在各种短视频界面上,咱们常常会看到相似这样的点赞动画:

十分的有意思,有意思的交互会让用户更违心进行互动。

那么,这么乏味的点赞动画,有没有可能应用纯 CSS 实现呢?那当然是必须的,本文,就将奇妙的借助 transition,仅仅应用 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 这里大段代码:

  1. #{random() * 2500 + 1500}ms 生成 1500ms ~ 4000ms 之间的随机数,示意动画的继续时长
  2. #{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

咱们以一个表情为例子:

  1. 默认它的透明度为 opacity: 0.1
  2. 点击的时候,它的透明度霎时变成 opacity: 1
  3. 而后,通过 transition-delayopacity: 1 的状态放弃一段时间后
  4. 逐步再隐没,变回 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 呢?就会是这样:

好,咱们联合一下下面两个动画:

  1. 咱们将所有的表情,默认的透明度改为 0.1
  2. 被点击的时候,透明度变成 1
  3. 透明度在 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);
    }
}

这里,须要留神的是:

  1. 点赞的按钮,通过了父元素 .g-wrap 的伪元素实现,这样的益处是,子元素 li 的 :active 点击事件,是能够冒泡传给父元素的,这样每次子元素被点击,咱们都能够放大一次点赞按钮,用于实现点击反馈;
  2. 略微批改一下缓动函数,让整体成果更为平衡正当。

这样,咱们就失去了题图一开始的成果,利用纯 CSS 实现的点赞动画:

残缺的代码,你能够戳这里:CodePen Demo — Like Animation

一点瑕疵

当然,这个计划是有一点点问题的。

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

这是因为 CSS 计划的实质是通过点击一个通明表情,让它变成不通明。而点击过快的话,会导致两次或者屡次点击,点在了同一个元素上,这样,就无奈实现一个点击,产生一个表情。所以下面代码中批改缓动 cubic-bezier(.46,.53,.51,.62) 的目标也是在于,让元素动画后期静止更快,这样能够有利于适配更快的点击速率。

  1. 不仅仅是点击按钮,点击按钮上方也能呈现成果

这样也很好了解,因为实质是个障眼法,所以点击按钮上方,只有是元素静止门路的中央,也是会有元素显形的。这个硬要解决也能够,通过再叠加一层通明元素在按钮上方,通过层级关系屏蔽掉点击事件。

  1. 表情的随机只是伪随机

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

  1. CSS 版本的点赞成果是单机版

无奈多用户联动,可能是影响能不能理论应用最为要害的因素。

不过,总而言之,应用纯 CSS 实现的计划,整体成果还是不错的。

最初

好了,本文到此结束,心愿本文对你有所帮忙 :)

更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。

如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。

正文完
 0