一颗红心,三手准备,分别基于图片(img)/SCSS(样式)/SVG动画实现动态拉轰的点赞按钮特效

news2025/1/31 18:43:00

华丽炫酷的动画特效总能够让人心旷神怡,不能自已。艳羡之余,如果还能够探究其华丽外表下的实现逻辑,那就是百尺竿头,更上一步了。本次我们使用图片、SCSS样式以及SVG图片动画来实现“点赞”按钮的动画特效,并比较不同之处。

图片实现

最简单,也最容易理解的实现方式就是使用图片。曾几何时,几乎所有前端特效都需要借助图片来完成。

实现原理很简单,通过不同的关键帧来“拼接”一段完整的动画影片,每一帧即该动画的每一个瞬间“状态”。

首先声明必要的盒子模型:

<div class="heart"></div>

这里以div为例子,声明伪类对象heart。

随后通过样式对heart伪类进行控制:

.heart {  
  cursor: pointer;  
  height: 50px;  
  width: 50px;  
  background-image:url( 'https://abs.twimg.com/a/1446542199/img/t1/web_heart_animation.png');  
  background-position: left;  
  background-repeat:no-repeat;  
  background-size:2900%;  
}  
  
.heart:hover {  
  background-position:right;  
}  
  
.is_animating {  
  animation: heart-burst .8s steps(28) 1;  
}  
  
@keyframes heart-burst {  
  from {background-position:left;}  
  to { background-position:right;}  
}

这里指定背景图片位置,只显示最左侧的背景元素,鼠标悬停时则只显示最右侧背景元素,然后当鼠标点击div时,触发@keyframes heart-burst动画,从左侧移动至右侧,一共进行28帧的侧移动作:

这样就完成了一段流畅的动画特效:

See the Pen <a href=“https://codepen.io/v3ucom/pen/yLjNERX”> Untitled</a> by 刘悦的技术博客 (<a href=“https://codepen.io/v3ucom”>@v3ucom</a>) on <a href=“https://codepen.io”>CodePen</a>.

需要注意的是,这里需要借助JavaScript绑定单击事件,所以需要引入zepto.min.js文件

https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js

通过zepto.min.js库就可以很方便的操作页面节点:

$(".heart").on('click touchstart', function(){  
  $(this).toggleClass('is_animating');  
});  
  
$(".heart").on('animationend', function(){  
  $(this).toggleClass('is_animating');  
});

逻辑是单击事件触发动画,动画执行过程中再次点击则移除动画效果。

此种方式依赖多帧背景图、CSS动画以及JavaScript事件绑定,显然成本有些高,同时多帧图片平铺导致体积过大,也会占用系统带宽,得不偿失。

纯SCSS(样式)实现

使用纯CSS样式也可以完成这样的特效,但CSS3原生语法太过复杂,这里我们使用SCSS语法,SCSS是 CSS3的超集,在保证兼容性的前提下,允许使用变量、 嵌套、 混合、导入等特性, 在编写逻辑复杂的CSS代码时,可以简化逻辑,提高CSS的代码可读性。

首先还是创建基本盒子模型:

<input id="toggle-heart" type="checkbox"/>  
<label for="toggle-heart">❤</label>

这里通过复选框和标签元素来控制点赞按钮的状态。

随后编写SCSS逻辑:

$bubble-d: 4.5rem; // bubble diameter  
$bubble-r: .5*$bubble-d; // bubble-radius  
  
@mixin bubble($ext) {  
  transform: scale(1);  
  border-color: #cc8ef5;  
  border-width: $ext;  
}  
  
body {  
  display: flex;  
  justify-content: center;  
  margin: 0;  
  height: 100vh;  
}  
  
[id='toggle-heart'] {  
  position: absolute;  
  left: -100vw;  
    
  &:checked + label {  
    color: #e2264d;  
    will-change: font-size;  
    animation: heart 1s cubic-bezier(.17, .89, .32, 1.49);  
      
    &:before, &:after {  
      animation: inherit;  
      animation-timing-function: cubic-bezier(.21, .61, .35, 1);  
    }  
      
    &:before {  
      will-change: transform, border-width, border-color;  
      animation-name: bubble;  
    }  
  }  
}  
  
[for='toggle-heart'] {  
  align-self: center;  
  position: relative;  
  color: #aab8c2;  
  font-size: 2em;  
  cursor: pointer;  
    
  &:before, &:after {  
    position: absolute;  
    z-index: -1;  
    top: 50%; left: 50%;  
    border-radius: 50%;  
    content: '';  
  }  
    
  &:before {  
    box-sizing: border-box;  
    margin: -$bubble-r;  
    border: solid $bubble-r #e2264d;  
    width: $bubble-d; height: $bubble-d;  
    transform: scale(0);  
  }  
}  
  
@keyframes heart {  
  0%, 17.5% { font-size: 0; }  
}  
  
@keyframes bubble {  
  15% { @include bubble($bubble-r); }  
  30%, 100% { @include bubble(0); }  
}

这里首先将复选框按钮移出界面,随后定义bubble对象,这里bubble指的是点击后膨胀的紫色(#cc8ef5)泡泡,直径是4.5rem,并且圆角修饰:KaTeX parse error: Undefined control sequence: \* at position 13: bubble-r: .5\̲*̲bubble-d

随后通过id选择器toggle-heart状态判断元素状态,触发heart和bubble动画,在一秒内动态的改变heart元素以及bubble元素的位置、大小以及边框透明度,从而完成动态特效。

接着添加烟花特效:

body {  
  display: flex;  
  justify-content: center;  
  margin: 0;  
  height: 100vh;  
  background: linear-gradient(135deg, #121721, #000);  
  font: 1em verdana, sans-serif;  
}  
  
[id='toggle-heart'] {  
  position: absolute;  
  left: -100vw;  
}  
[id='toggle-heart']:checked + label {  
  color: #e2264d;  
  filter: none;  
  will-change: font-size;  
  -webkit-animation: heart 1s cubic-bezier(0.17, 0.89, 0.32, 1.49);  
          animation: heart 1s cubic-bezier(0.17, 0.89, 0.32, 1.49);  
}  
[id='toggle-heart']:checked + label:before, [id='toggle-heart']:checked + label:after {  
  -webkit-animation: inherit;  
          animation: inherit;  
  -webkit-animation-timing-function: ease-out;  
          animation-timing-function: ease-out;  
}  
[id='toggle-heart']:checked + label:before {  
  will-change: transform, border-width, border-color;  
  -webkit-animation-name: bubble;  
          animation-name: bubble;  
}  
[id='toggle-heart']:checked + label:after {  
  will-change: opacity, box-shadow;  
  -webkit-animation-name: sparkles;  
          animation-name: sparkles;  
}  
[id='toggle-heart']:focus + label {  
  text-shadow: 0 0 3px white,  0 1px 1px white, 0 -1px 1px white,  1px 0 1px white, -1px 0 1px white;  
}  
  
[for='toggle-heart'] {  
  align-self: center;  
  position: relative;  
  color: #888;  
  font-size: 2em;  
  filter: grayscale(1);  
  -webkit-user-select: none;  
     -moz-user-select: none;  
      -ms-user-select: none;  
          user-select: none;  
  cursor: pointer;  
}  
[for='toggle-heart']:before, [for='toggle-heart']:after {  
  position: absolute;  
  z-index: -1;  
  top: 50%;  
  left: 50%;  
  border-radius: 50%;  
  content: '';  
}  
[for='toggle-heart']:before {  
  box-sizing: border-box;  
  margin: -2.25rem;  
  border: solid 2.25rem #e2264d;  
  width: 4.5rem;  
  height: 4.5rem;  
  transform: scale(0);  
}  
[for='toggle-heart']:after {  
  margin: -0.1875rem;  
  width: 0.375rem;  
  height: 0.375rem;  
  box-shadow: 0.32476rem -3rem 0 -0.1875rem #ff8080, -0.32476rem -2.625rem 0 -0.1875rem #ffed80, 2.54798rem -1.61656rem 0 -0.1875rem #ffed80, 1.84982rem -1.89057rem 0 -0.1875rem #a4ff80, 2.85252rem 0.98418rem 0 -0.1875rem #a4ff80, 2.63145rem 0.2675rem 0 -0.1875rem #80ffc8, 1.00905rem 2.84381rem 0 -0.1875rem #80ffc8, 1.43154rem 2.22414rem 0 -0.1875rem #80c8ff, -1.59425rem 2.562rem 0 -0.1875rem #80c8ff, -0.84635rem 2.50595rem 0 -0.1875rem #a480ff, -2.99705rem 0.35095rem 0 -0.1875rem #a480ff, -2.48692rem 0.90073rem 0 -0.1875rem #ff80ed, -2.14301rem -2.12438rem 0 -0.1875rem #ff80ed, -2.25479rem -1.38275rem 0 -0.1875rem #ff8080;  
}  
  
@-webkit-keyframes heart {  
  0%, 17.5% {  
    font-size: 0;  
  }  
}  
  
@keyframes heart {  
  0%, 17.5% {  
    font-size: 0;  
  }  
}  
@-webkit-keyframes bubble {  
  15% {  
    transform: scale(1);  
    border-color: #cc8ef5;  
    border-width: 2.25rem;  
  }  
  30%, 100% {  
    transform: scale(1);  
    border-color: #cc8ef5;  
    border-width: 0;  
  }  
}  
@keyframes bubble {  
  15% {  
    transform: scale(1);  
    border-color: #cc8ef5;  
    border-width: 2.25rem;  
  }  
  30%, 100% {  
    transform: scale(1);  
    border-color: #cc8ef5;  
    border-width: 0;  
  }  
}  
@-webkit-keyframes sparkles {  
  0%, 20% {  
    opacity: 0;  
  }  
  25% {  
    opacity: 1;  
    box-shadow: 0.32476rem -2.4375rem 0 0rem #ff8080, -0.32476rem -2.0625rem 0 0rem #ffed80, 2.1082rem -1.26585rem 0 0rem #ffed80, 1.41004rem -1.53985rem 0 0rem #a4ff80, 2.30412rem 0.85901rem 0 0rem #a4ff80, 2.08305rem 0.14233rem 0 0rem #80ffc8, 0.76499rem 2.33702rem 0 0rem #80ffc8, 1.18748rem 1.71734rem 0 0rem #80c8ff, -1.35019rem 2.0552rem 0 0rem #80c8ff, -0.60229rem 1.99916rem 0 0rem #a480ff, -2.44865rem 0.22578rem 0 0rem #a480ff, -1.93852rem 0.77557rem 0 0rem #ff80ed, -1.70323rem -1.77366rem 0 0rem #ff80ed, -1.81501rem -1.03204rem 0 0rem #ff8080;  
  }  
}  
@keyframes sparkles {  
  0%, 20% {  
    opacity: 0;  
  }  
  25% {  
    opacity: 1;  
    box-shadow: 0.32476rem -2.4375rem 0 0rem #ff8080, -0.32476rem -2.0625rem 0 0rem #ffed80, 2.1082rem -1.26585rem 0 0rem #ffed80, 1.41004rem -1.53985rem 0 0rem #a4ff80, 2.30412rem 0.85901rem 0 0rem #a4ff80, 2.08305rem 0.14233rem 0 0rem #80ffc8, 0.76499rem 2.33702rem 0 0rem #80ffc8, 1.18748rem 1.71734rem 0 0rem #80c8ff, -1.35019rem 2.0552rem 0 0rem #80c8ff, -0.60229rem 1.99916rem 0 0rem #a480ff, -2.44865rem 0.22578rem 0 0rem #a480ff, -1.93852rem 0.77557rem 0 0rem #ff80ed, -1.70323rem -1.77366rem 0 0rem #ff80ed, -1.81501rem -1.03204rem 0 0rem #ff8080;  
  }  
}

新增sparkles对象,通过动态的控制元素的彩色阴影来表现点击后的烟花动态效果:

See the Pen <a href=“https://codepen.io/v3ucom/pen/eYrNLWY”> Untitled</a> by 刘悦的技术博客 (<a href=“https://codepen.io/v3ucom”>@v3ucom</a>) on <a href=“https://codepen.io”>CodePen</a>.

这里为了增加效果对比度,将背景设置为深色,同时为点赞按钮增加亮色边框:

[id='toggle-heart']:focus + label {  
  text-shadow:   
    0 0 3px #fff,   
    0 1px 1px #fff, 0 -1px 1px #fff,   
    1px 0 1px #fff, -1px 0 1px #fff;  
}

大体上,利用transform属性控制元素的绝对定位、颜色、边框以及盒子模型阴影来完成此种特效,带宽资源占用层面,明显比图片更具优势。

SVG实现

SVG是矢量图形,不受像素的影响,从而使得它在不同的平台或者媒体下表现出的兼容性更好,与此同时,SVG对动画的支持较好,其DOM结构可以被其特定语法或者CSS控制,从而轻松的实现动画效果。

首先依然声明盒子模型:

<label class="like">  
  <input type="checkbox"/>  
  <div class="hearth"/>  
</label>

随后定义样式:

:root {  
  --size: 100px;  
  --frames: 62;  
}  
  
html {  
  background-color: #15202B;  
  min-height: 100vh;  
  display: flex;  
  justify-content: center;  
  align-items: center;  
  user-select: none;  
}  
  
input {  
  display: none;  
}  
  
.like {  
  display: block;  
  width: var(--size);  
  height: var(--size);  
  cursor: pointer;  
  border-radius: 999px;  
  overflow: visible;  
  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);  
  -webkit-tap-highlight-color: transparent;  
}  
  
.hearth {  
  background-image: url('https://assets.codepen.io/23500/Hashflag-AppleEvent.svg');  
  background-size: calc(var(--size) * var(--frames)) var(--size);  
  background-repeat: no-repeat;  
  background-position-x: calc(var(--size) * (var(--frames) * -1 + 2));  
  background-position-y: calc(var(--size) * 0.02);  
  width: var(--size);  
  height: var(--size);  
}  
  
input:checked + .hearth {  
  animation: like 1s steps(calc(var(--frames) - 3));    
  animation-fill-mode: forwards;  
}  
  
@keyframes like {  
  0% {  
    background-position-x: 0;  
  }  
  100% {  
    background-position-x: calc(var(--size) * (var(--frames) * -1 + 3));  
  }  
}  
  
@media (hover: hover) {  
  .like:hover {  
    background-color: #E1255E15;  
    .hearth {  
      background-position-x: calc(var(--size) * (var(--frames) * -1 + 1));  
    }  
  }  
}

和普通图片如出一辙,通过background-image来控制背景SVG图片的顺序,对背景的横坐标进行侧移动画操作,只不过帧数提高到62帧:

See the Pen <a href=“https://codepen.io/v3ucom/pen/MWGwXPv”> Untitled</a> by 刘悦的技术博客 (<a href=“https://codepen.io/v3ucom”>@v3ucom</a>) on <a href=“https://codepen.io”>CodePen</a>.

可以看到这里通过input:checked状态就可以触发@keyframes like横移动画,并不需要单独撰写JavaScript逻辑。

结语

三种动画特效实现方式各有千秋,但从可维护性以及成本控制角度上看,SCSS显然是最优解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CLM陆面过程模式

NCAR陆面模式CLM (Community Land Model)是地球系统模式CESM (Community Earth System Model)中的陆面过程模式分量&#xff0c;是在结合了BATS、LSM和IAP94等众多陆面模式的优点后&#xff0c;加入水文过程而开发出的综合性陆面模式&#xff0c;是目前国际上发展最为完善且得到…

java实现每日给女友微信发送早安等微信信息

大家好&#xff0c;我是雄雄。 前言 据说这个功能最近在抖音上很火&#xff0c;我没有抖音&#xff0c;没有看到。 但是我在掘金和CSDN上看了&#xff0c;相关案例确实很多&#xff0c;但是大家都是借助于了微信服务号&#xff0c;在我看来&#xff0c;效果很不佳。 其实我原…

如何在 Ubuntu 上将 ONLYOFFICE 文档集成至 Redmine

ONLYOFFICE 文档是一款符合 GNU AGPL v3.0 的开源办公套件。其中包含基于 Web 的查看器和协作编辑器&#xff0c;可用于处理文本文档、电子表格以及与 OOXML 格式高度兼容的演示文稿。 ONLYOFFICE 文档可与 Nextcloud、ownCloud、Seafile、Alfresco、Plone 等多种云服务进行集…

RabbitMQ(消息中间件)入门

目录 一. 什么是MQ&#xff1f; 二. 应用场景 三. 主流MQ框架 四. Docker安装部署RabbitMQ 1.查询镜像 2.获取镜像 3.运行镜像 四.进入RabbitMQ管理平台进行相关操作 五. RabbitMQ管理平台 1.Virtual Hosts 2.RabbitMQ关键名词 六. MQ的核心概念 七. springboot整合ra…

BiliBili 100+国际名校免费公开课整理分享

本资源这是一份公开课的目录&#xff0c;这里的视频大多来自 YouTube 等国内无法访问的网站&#xff0c;为了方便国内的朋友观看&#xff0c;作者将这些视频搬运到了BiliBili。 资源整理自网络&#xff0c;源地址&#xff1a;https://github.com/wenhan-wu/OpenCourseCatalog 所…

我今年大一,自学编程可行吗?

自学编程是可行的&#xff0c;但是你行不行就不好说了。 可能&#xff0c;这就是人生吧~ 建议你在自学编程之前&#xff0c;先看一下这几个问题&#xff1a; 1、我是一个意志坚定&#xff0c;抗压能力强&#xff0c;能耐得住寂寞的人吗&#xff1f;2、我对学编程是有规划还是只…

君子不玩物丧志,亦常以借物调心,网站集成二次元网页小组件(widget)石蒜模拟器,聊以赏玩

传世经典《菜根谭》中有言曰&#xff1a;“徜徉于山林泉石之间&#xff0c;而尘心渐息&#xff1b;夷犹于诗书图画之内&#xff0c;而俗气潜消。故君子虽不玩物丧志&#xff0c;亦常借物调心。”意思是&#xff0c;徜徉在林泉山石之间&#xff0c;能够摒弃杂念&#xff0c;留意…

C++程序设计——运算符重载(运算符重载的概念;运算符成员函数与友元函数;单目运算符重载;重载流运算符;双目运算符重载;赋值运算符重载)

目录 前言 一、运算符重的概念与意义 1.运算符重载 &#xff08;1&#xff09;函数重载 &#xff08;2&#xff09;运算符重载 2.运算符重载的意义 &#xff08;1&#xff09;例子引入 &#xff08;2&#xff09;意义 &#xff08;3&#xff09;运算符重载的限制 …

有人问,普通人学python有意义吗?看看这位大佬怎么说

普通人学python有意义吗&#xff1f; 现在随着python越来越火&#xff0c;尤其是它成为了人工智能的第一编程语言&#xff0c;还被纳入了中小学的教育中。并且python的应用范围很广泛&#xff0c;可以解决很多专业或非专业的问题。 但python真的适合普通人学习吗&#xff1f;…

STAMP算法实战

1.案例知识点 推荐系统任务描述:通过用户的历史行为(比如浏览记录、购买记录等等)准确的预测出用户未来的行为;好的推荐系统不仅如此,而且能够拓展用户的视野,帮助他们发现可能感兴趣的却不容易发现的item;同时将埋没在长尾中的好商品推荐给可能感兴趣的用户。STAMP推荐…

普通二本,去过阿里外包,到现在年薪40W+的高级测试工程师,我的两年转行心酸经历...

我是一个普通二本大学机械专业毕业&#xff0c;17年毕业&#xff0c;19年转行&#xff0c;目前做IT行业的软件测试已经有3年多&#xff0c;职位是高级软件测试工程师&#xff0c;坐标上海… 我想现在我也有一点资格谈论关于转行这个话题&#xff1b;希望你在决定转行之前&…

【网络工程】如何本地调试微信公众号开发教程(Nginx代理方法)

目录 前言 目的 通过Nginx代理实现本地调试微信公众号 实现工具 实现步骤 1.启动本地前端项目 2.首先配置Nginx 3.填写app.conf内容&#xff0c;把本地前端项目与域名形成映射。 4.把app.conf加入到Nginx配置中 5.打开我们安装好的SwitchHosts工具 6.右键管理员权限…

全球电子烟行业快速发展,我国监管政策趋严行业面临重构

一、电子烟在全球范围广泛流行 根据观研报告网发布的《2022年中国电子烟行业分析报告-行业现状与发展趋势分析》显示&#xff0c;电子烟是在最近几年出现的一种电子产品&#xff0c;电子烟宣传的健康无害、有一定满足感对消费者有绝佳的吸引力;电子烟的品味、档次、个性化是吸…

零基础编程学习指南!让你不再迷茫~

一篇初学者干货&#xff0c;请耐心看完&#xff0c;希望对你有帮助。 作为初学者的你&#xff0c;命中了以下问题吗&#xff1f; #张三丰&#xff1a;编程是什么&#xff0c;怎么编程&#xff1f; #张无忌&#xff1a;what&#xff0c;比土木工程好&#xff1f; #成昆&…

Linux限制磁盘与内存配额【超详细】

大家好&#xff0c;我是早九晚十二&#xff0c;目前是做运维相关的工作。写博客是为了积累&#xff0c;希望大家一起进步&#xff01; 我的主页&#xff1a;早九晚十二 文章目录Linux限制磁盘用量的方式什么是磁盘配额磁盘配额的条件安装quota工具配额步骤新建一个磁盘分区新建…

NVMe 原理 - 命令的处理

蛋蛋读NVMe之一 (ssdfans.com) NVMe 所处层次 NVMe是一种Host与SSD之间通讯的协议&#xff0c;它在协议栈中隶属高层。NVMe在协议栈中处于应用层或者命令层。 NVMe是为SSD所生的。NVMe出现之前&#xff0c;SSD绝大多数走的是AHCI和SATA的协议&#xff0c;后者其实是为传统HDD…

元宇宙产业委与中国传媒大学就“虚拟空间文化生产与管理微专业”课程深度合作

12月17日、18日两天下午&#xff0c;由中国移动通信联合会元宇宙产业工作委员会牵头&#xff0c;为中国传媒大学虚拟空间文化生产与管理微专业成功邀请5位行业内大咖级讲师&#xff0c;为校内、外在读本科生和研究生&#xff0c;以及对虚拟文化生产与管理感兴趣且获得学士学位的…

工控CTF之协议分析6——s7comm

协议分析 流量分析 主要以工控流量和恶意流量为主&#xff0c;难度较低的题目主要考察Wireshark使用和找规律&#xff0c;难度较高的题目主要考察协议定义和特征 简单只能简单得干篇一律&#xff0c;难可以难得五花八门 常见的工控协议有&#xff1a;Modbus、MMS、IEC60870、…

windows下安装make,使用makefile文件

文章目录前言Makefile简介make作用安装make&#xff1a;1.windows上安装&#xff1a;chocolatey一、Chocolatey介绍二、Chocolatey安装安装make配置make连接前言 本人在学习go-micro中&#xff0c;用到Makefile&#xff0c;本人之前用过Makefile&#xff0c;但是不知道为什么这…

【蓝桥杯】第12届Scratch国赛中级组第1题 -- 文字特效

[导读]&#xff1a;蓝桥杯大赛是工业和信息化部人才交流中心举办的全国性专业信息技术赛事。蓝桥杯大赛首席专家倪光南院士说&#xff1a;“蓝桥杯以考促学&#xff0c;塑造了领跑全国的人才培养选拨模式&#xff0c;并获得了行业的深度认可。” 春雷课堂计划推出Scratch蓝桥杯…