我正在参加“掘金挑战守则”。
我正在参加“掘金挑战守则”。详情请见: 掘金挑战赛来了!
华丽酷炫的动画特效总能让人感到轻松愉快,情不自禁。羡慕之余,如果也能在它华丽的外表下探寻实现逻辑,那将是成功,又向前迈进了一步。这次我们使用图像、SCSS 样式和 SVG 图像动画来为“Like”按钮设置动画,并比较差异。
图像实现
最简单和最容易理解的实现是使用图像。曾几何时,几乎所有的前端特效都需要借助图片来完成。
实现原理非常简单。一部完整的动画电影是通过不同的关键帧“拼接”出来的,每一帧都是动画每一个瞬间的“状态”。
首先声明必要的盒子模型:
<div class= "heart"></div>
复制代码
这里我们以div为例,声明伪类对象heart。
然后 heart 伪类由样式控制:
。心 {
光标:指针;
高度:50px;
宽度:50px;
背景图像:url('https://abs.twimg.com/a/1446542199/img/t1/web_heart_animation.png');
背景位置:左;
背景重复:不重复;
背景大小:2900%;
}
.heart:悬停{
背景位置:对;
}
.is_animating {
动画:心爆。 8s步骤( 28) 1;
}
@keyframes 心跳加速{
从{背景位置:左;}
到{背景位置:右;}
}
复制代码
这里指定了背景图片位置,只显示最左边的背景元素,鼠标悬停时只显示最右边的背景元素,然后当鼠标点击div时,触发@keyframes heart-burst动画,从左向右移动,总共进行了28帧横向移动:
这样就完成了流畅的动画效果:
需要注意的是点击事件需要与JavaScript绑定,所以需要引入zepto.min.js文件
https://cdnjs.cloudflare.com/ajax /libs/zepto /1.2.0/zepto.min.js
复制代码
通过 zepto.min.js 库,可以方便的操作页面节点:
$(".heart")。 on( '点击触摸启动', function(){
$(这个)。 toggleClass('is_animating');
});
$(".heart")。 on('动画结束',函数(){
$(这个)。 toggleClass('is_animating');
});
复制代码
逻辑是点击事件触发动画,在动画执行过程中再次点击会移除动画效果。
此方法依赖于多帧背景图像、CSS 动画和 JavaScript 事件绑定。显然,成本有点高。同时,多帧图像平铺导致体积过大,占用系统带宽,得不偿失。
纯 SCSS(样式)实现
这种特效也可以用纯CSS样式来做,但是CSS3的原生语法太复杂了。这里我们使用 SCSS 语法。 SCSS 是 CSS3 的超集。在保证兼容性的前提下,允许变量、嵌套、混合、导入。等特性,在编写复杂的 CSS 代码时,可以简化逻辑,提高 CSS 代码的可读性。
首先让我们创建基本的盒子模型:
<input id= "toggle-heart" type= "checkbox"/>
<label for= "toggle-heart">❤</label>
复制代码
在这里,like 按钮的状态由复选框和标签元素控制。
然后编写SCSS逻辑:
$bubble-d:4.5rem; //气泡直径
$泡沫-r:。 5* $气泡-d; // 气泡半径
@mixin 气泡($ext){
变换:比例(1);
边框颜色:#cc8ef5;
边框宽度:$ext;
}
身体 {
显示:弯曲;
证明内容:中心;
边距:0;
高度:100vh;
}
[id='toggle-heart'] {
位置:绝对;
左: - 100vw;
& : 已检查 + 标签 {
颜色:#e2264d;
将改变:字体大小;
动画:heart 1s 三次贝塞尔曲线(. 17, . 89, . 32, 1.49);
&:之前,&:之后{
动画:继承;
动画定时功能:cubic-bezier(.21,.61,.35,1);
}
& :前 {
will-change:变换、边框宽度、边框颜色;
动画名称:气泡;
}
}
}
[for='toggle-heart'] {
对齐自我:中心;
位置:相对;
颜色:#aab8c2;
字体大小:2em;
光标:指针;
&:之前,&:之后{
位置:绝对;
z-index: - 1;
最高:50%;左:50%;
边界半径:50%;
内容: '';
}
& :前 {
box-sizing:边框框;
保证金:-$bubble -r;
边框:实心 $bubble -r #e2264d;
宽度:$气泡-d;高度:$气泡-d;
变换:比例(0);
}
}
@keyframes 心{
0%, 17.5% { 字体大小: 0; }
}
@keyframes 气泡 {
15% { @include 气泡($bubble -r); }
30%, 100% { @include 气泡(0); }
}
复制代码
这里先将checkbox按钮移出界面,然后定义气泡对象,其中bubble是指点击后会展开的紫色(#cc8ef5)气泡,直径为4.5rem,圆角:
泡泡-r:.5\泡泡-r:.5\
气泡 - r : . 5 \* 气泡-d
然后通过id选择器的toggle-heart状态判断元素的状态,触发heart和bubble动画,在一秒内动态改变heart元素和bubble元素的位置、大小和边框透明度完成动态特效。
然后添加烟花效果:
身体 {
显示:弯曲;
证明内容:中心;
边距:0;
高度:100vh;
背景:线性渐变(135度,#121721,#000);
字体:1em verdana,无衬线;
}
[id='toggle-heart'] {
位置:绝对;
左: - 100vw;
}
[id='toggle-heart']:检查+标签{
颜色:#e2264d;
过滤器:无;
将改变:字体大小;
-webkit- 动画:心脏 1s 三次贝塞尔曲线(0.17、0.89、0.32、1.49);
动画:心脏 1s 三次贝塞尔曲线(0.17、0.89、0.32、1.49);
}
[id= 'toggle-heart' ] :checked + label :before, [id= 'toggle-heart' ] :checked + label :after {
-webkit- 动画:继承;
动画:继承;
-webkit- 动画计时功能:缓出;
动画定时功能:缓出;
}
[id='toggle-heart'] :checked + label :before {
will-change:变换、边框宽度、边框颜色;
-webkit- 动画名称:气泡;
动画名称:气泡;
}
[id= 'toggle-heart' ] :checked + label :after {
will-change:不透明度,盒子阴影;
-webkit- 动画名称:火花;
动画名称:火花;
}
[id='toggle-heart']:焦点+标签{
文字阴影:0 0 3px 白色,0 1px 1px 白色,0 - 1px 1px 白色,1px 0 1px 白色, - 1px 0 1px 白色;
}
[for='toggle-heart'] {
对齐自我:中心;
位置:相对;
颜色:#888;
字体大小:2em;
过滤器:灰度(1);
-webkit 用户选择:无;
-moz 用户选择:无;
-ms 用户选择:无;
用户选择:无;
光标:指针;
}
[for= 'toggle-heart' ] :before, [for= 'toggle-heart' ] :after {
位置:绝对;
z-index: - 1;
最高:50%;
左:50%;
边界半径:50%;
内容: '';
}
[for= 'toggle-heart' ] :before {
box-sizing:边框框;
保证金: - 2.25rem;
边框:实心 2.25rem #e2264d;
宽度:4.5rem;
高度:4.5rem;
变换:比例(0);
}
[for='toggle-heart'] :after {
保证金:- 0.1875rem;
宽度:0.375rem;
高度: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.562 rem 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 心{
0%, 17.5% {
字体大小:0;
}
}
@keyframes 心{
0%, 17.5% {
字体大小:0;
}
}
@-webkit-keyframes 气泡 {
15% {
变换:比例(1);
边框颜色:#cc8ef5;
边框宽度:2.25rem;
}
30%, 100% {
变换:比例(1);
边框颜色:#cc8ef5;
边框宽度:0;
}
}
@keyframes 气泡 {
15% {
变换:比例(1);
边框颜色:#cc8ef5;
边框宽度:2.25rem;
}
30%, 100% {
变换:比例(1);
边框颜色:#cc8ef5;
边框宽度:0;
}
}
@-webkit-keyframes 闪闪发光{
0%, 20% {
不透明度:0;
}
25% {
不透明度: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 - 0re 1.03204m; 0re #ff
}
}
@keyframes 闪闪发光{
0%, 20% {
不透明度:0;
}
25% {
不透明度: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 - 0re 1.03204m; 0re #ff
}
}
复制代码
添加了一个新的 sparkles 对象,通过动态控制元素的颜色阴影来表达点击烟花的动态效果:
这里,为了增加效果的对比度,将背景设置为深色,并为like按钮添加亮边框:
[id='toggle-heart']:焦点+标签{
文字阴影:
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= "heart"/>
</label>
复制代码
然后定义样式:
:根 {
--尺寸:100像素;
--帧数:62;
}
html {
背景颜色:#15202B;
最小高度:100vh;
显示:弯曲;
证明内容:中心;
对齐项目:居中;
用户选择:无;
}
输入 {
显示:无;
}
。喜欢 {
显示:块;
宽度:var(--size);
高度:var(--size);
光标:指针;
边框半径:999px;
溢出:可见;
-webkit-tap-highlight-颜色:rgba(0,0,0,0);
-webkit-tap-highlight- 颜色:透明;
}
.壁炉{
背景图片:url('https://assets.codepen.io/23500/Hashflag-AppleEvent.svg');
背景尺寸:计算(var(--size)* var(--frames))var(--size);
背景重复:不重复;
背景位置x:计算(var(--size)*(var(--frames)* - 1 + 2));
背景位置-y: calc(var(--size) * 0.02);
宽度:var(--size);
高度:var(--size);
}
输入:检查 + .hearth {
动画:像 1s 步(计算(var(--frames)- 3));
动画填充模式:转发;
}
@keyframes 像 {
0% {
背景位置-x:0;
}
100% {
背景位置-x: calc( var(--size) * ( var(--frames) * - 1 + 3));
}
}
@媒体(悬停:悬停){
.like :hover {
背景颜色:#E1255E15;
.壁炉{
背景位置-x: calc( var(--size) * ( var(--frames) * - 1 + 1));
}
}
}
复制代码
和普通图片完全一样。 background-image用于控制背景SVG图片的顺序,进行背景横坐标的横向移动,但帧数增加到62帧:
这里可以看到像水平动画一样的@keyframes可以通过input:checked状态触发,不需要单独编写JavaScript逻辑。
结语
三种动画特效实现方式各有千秋,但从可维护性和成本控制的角度来看,SCSS显然是最优方案。
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。
这篇文章的链接: https://homecpp.art/4406/7155/2130
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明