0

0

手把手教你用 transition 实现短视频 APP的点赞动画

青灯夜游

青灯夜游

发布时间:2022-09-07 10:45:02

|

2230人浏览过

|

来源于segmentfault

转载

怎么使用纯 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

    Stable Diffusion Online
    Stable Diffusion Online

    基于Stable Diffusion搭建的AI绘图工具

    下载
  • 然后,通过 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前端

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

6

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

8

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

14

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

17

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

2

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

130

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

8

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

208

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 12.3万人学习

CSS3 教程
CSS3 教程

共18课时 | 6.3万人学习

Vue 教程
Vue 教程

共42课时 | 9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号