巧用 transition 实现短视频 APP 点赞动画
在各种短视频界面上,我们经常会看到类似这样的点赞动画:
非常的有意思,有意思的交互会让用户更愿意进行互动。
那么,这么有趣的点赞动画,有没有可能使用纯 CSS 实现呢?那当然是必须的,本文,就将巧妙的借助 transition
,仅仅使用 CSS 完成这么一个点赞动画。
实现不同表情的不断上升
如果使用纯 CSS 实现这一整套动画的话。我们首先需要实现一段无限循环的,大量不同的表情不断向上漂浮的动画。
像是这样:
这个整体还是比较容易实现的,核心原理就是同一个动画,设置不同的 transition-duration
,transition-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-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 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
一点瑕疵
当然,这个方案是有一点点问题的。
- 就是如果当点击的速率过快,是无法实现一个点击,产生一个表情的
这是由于 CSS 方案的本质是通过点击一个透明表情,让它变成不透明。而点击过快的话,会导致两次或者多次点击,点在了同一个元素上,这样,就无法实现一个点击,产生一个表情。所以上面代码中修改缓动 cubic-bezier(.46,.53,.51,.62)
的目的也是在于,让元素动画前期运动更快,这样可以有利于适配更快的点击速率。
- 不仅仅是点击按钮,点击按钮上方也能出现效果
这样也很好理解,由于本质是个障眼法,所以点击按钮上方,只要是元素运动路径的地方,也是会有元素显形的。这个硬要解决也可以,通过再叠加一层透明元素在按钮上方,通过层级关系屏蔽掉点击事件。
- 表情的随机只是伪随机
利用 SASS 随机的方案在经过编译后是不会产生随机效果的。所以,这里只能是伪随机,基于 DOM 的个数,当 DOM 数越多,整体而言,随机的效果越好。基本上 50 个 DOM 是比较足够的。
- CSS 版本的点赞效果是单机版
无法多用户联动,可能是影响能不能实际使用最为关键的因素。
不过,总而言之,使用纯 CSS 实现的方案,整体效果还是不错的。
最后
怎样,其实也不是很难吧?好了,本文到此结束,希望本文对你有所帮助
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
巧用 transition 实现短视频 APP 点赞动画的更多相关文章
- 浅谈短视频APP的发展趋势
2014年6月20日,在AppAnnie最新发布5月应用指数中,美拍荣登“非游戏类iOS榜单”全球下载量第一位置,成为全球iOS应用商店最热门APP.能在<AppAnnie应用指数>这份A ...
- 短视频APP+不同类型社交应用发展分析+化妆品电商
短视频APP——昙花一现还是发展趋势? 在这个互联网与科技并行且飞速发展的时代,各种app不断涌入市场,其中短视频app便是一个典型,美拍,就成功入围2014年十大最火app.而短视频app也势必要成 ...
- 如何快速打造一款高清又极速的短视频APP?
整个短视频的市场规模一直在增长,网络数据显示2018年已经突破100亿大关,在2019年预测将超过200亿.纵观行业,在生活资讯.美食.搞笑.游戏.美妆等领域,短视频流量巨大但竞争激烈,但是在教育.财 ...
- 快速搭建一个“微视”类短视频 App
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯云视频发表于云+社区专栏 关注公众号"腾讯云视频",一键获取 技术干货 | 优惠活动 | 视频方案 " ...
- 【干货】零基础30分钟让你拥有一个完整属于自己的短视频APP系统
目录 一.附言: 1 二.购买域名和购买服务器: 2 三.搭建服务器环境: 5 四.配置APP前端部分: 8 1.工具以及文件准备: 9 2.配置后端接口地址 11 3.配置APP启动图和启动图标 ...
- 短视频APP是如何开启你的美好生活的?
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由腾讯视频云终端团队发表于云+社区专栏 常青, 2008 年毕业加入腾讯,一直从事客户端研发相关工作,先后参与过 PC QQ.手机QQ. ...
- 最快1天搭建短视频APP!阿里云短视频解决方案上线
短视频行业的发展前景乐观是毋庸置疑的,整个短视频的市场规模一直在增长,网络数据显示2018年已经突破100亿大关,在2019年预测将超过200亿.那么,对于短视频从业者来讲,要持续推动业务的发展,必须 ...
- 100行代码搞定抖音短视频App,终于可以和美女合唱了。
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由视频咖 发表于云+社区专栏 本文作者,shengcui,腾讯云高级开发工程师,负责移动客户端开发 最近抖音最近又带了一波合唱的节奏,老 ...
- 10分钟快速上车短视频风口:基于uniapp框架创建自己的仿抖音短视APP
在今年也就是第48次发布的<中国互联网络发展状况统计报告>有这样一个数据,21年的上半年以来,我国我国网民规模达10.11亿,其中短视频用户达8.88亿.碎片化的生活场景下,短视频成为人们 ...
随机推荐
- 我的 Java 学习&面试网站又又又升级了!
晚上好,我是 Guide. 距离上次介绍 JavaGuide 新版在线阅读网站已经过去 7 个多月了(相关阅读:官宣!我升级了!!!),这 7 个多月里不论是 JavaGuide 的内容,还是 Jav ...
- Vue 3.0 有哪些新特性值得我们提前了解
一.迎接 Vue 3.0 简介 Vue.js 作者兼核心开发者尤雨溪宣布 Vue 3.0 进入 Beta 阶段. 已合并所有计划内的 RFC 已实现所有被合并的 RFC Vue CLI 现在通过 ...
- nginx源码层面探究request_time、upstream_response_time、upstream_connect_time与upstream_header_time指标具体含义
背景概述 最近计划着重分析一下线上各api的HTTP响应耗时情况,检查是否有接口平均耗时.99分位耗时等相关指标过大的情况,了解到nginx统计请求耗时有四个指标:request_time.upstr ...
- 基于Svelte3.x桌面端UI组件库Svelte UI
Svelte-UI,一套基于svelte.js开发的桌面pc端ui组件库 最近一直忙于写svelte-ui,一套svelte3开发的桌面端ui组件库.在设计及功能上借鉴了element-ui组件库.所 ...
- 网络通讯之Socket-Tcp(一)
网络通讯之Socket-Tcp 分成3部分讲解: 网络通讯之Socket-Tcp(一): 1.如何理解Socket 2.Socket通信重要函数 网络通讯之Socket-Tcp(二): 1.简单So ...
- 面试突击62:group by 有哪些注意事项?
注意:本文以下内容基于 MySQL 5.7 InnoDB 数据库引擎. 1.group by 后面不能加 where 在 MySQL 中,所有的 SQL 查询语法要遵循以下语法顺序: select f ...
- 异构图神经网络笔记-Heterogeneous Graph Neural Network(KDD19)
自己讲论文做的异构图神经网络的ppt.再转变成博客有点麻烦,所以做成图片笔记. 论文链接:https://arxiv.org/abs/1903.07293
- Tapdata 实时数据融合平台解决方案(二):理解数据中台
作者介绍:TJ,唐建法,Tapdata 钛铂数据 CTO,MongoDB中文社区主席,原MongoDB大中华区首席架构师,极客时间MongoDB视频课程讲师. 数据中台定义: 以打通部门或数据孤岛的统 ...
- java中的内存划分和一个数组的内存图
内存概述 内存是计算机中的重要原件,临时存储区域,作用是运行程序.我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存 Java虚拟机要运行程序 ...
- 2018 CSP-J 初赛解析
做题记录与答案 今天这个做的是真的烂,60分,妙极了(微笑 可以看看人家的解析 选择: 选择好多不太懂的,一个个的来解析 先分析一下选择的知识点: 计算机基础 :T1.T3.T4.T5.T8 进制转换 ...