css实现闪光动效

😎demo展示
以上就是纯css实现的闪光效果,核心就是使用css的animation动画实现,无需编写任何js代码,实现简单且能保证性能、效果流畅。
🤠代码展示
直接上代码:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<style type="text/css">
.logo_flash {
position: relative;
margin: 0 auto;
}
.logo_flash {
width: 255px;
overflow: hidden;
}
.logo_flash:before {
background: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0));
transform: translate(-128%, 0) skewx(-25deg);
width: 150px;
height: 100%;
position: absolute;
left: 0px;
top: 0;
content: "";
animation: flashLights 4s ease-in infinite;
}
@keyframes flashLights {
0%, 75% {
transform: translate(-128%, 0) skewx(-25deg);
}
100% {
transform: translate(200%, 0) skewx(-25deg);
}
}
</style>
<body>
<div class="logo_flash">
<img src="./img/cat.jpg" width="255" alt="">
</div>
</body>
</html>
🤓代码解析
html部分就是一个div包含一个img元素,闪光动效实际就是利用css构造一个伪元素在图片上划过。
接下来按思路分析css的实现步骤:
- 实现闪光的伪元素
.logo_flash:before {
width: 10px;
height: 100%;
background: white;
position: absolute;
left: 50%;
top: 0;
content: "";
}
这样就实现了悬浮图片上的伪元素,但一个矩形的白色色块显然不能表现闪光。这里增加伪元素宽度、利用css线性渐变函数linear-gradient 做下修饰:
background: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0));
width: 100px;

然后利用tranform属性的skew函数倾斜转换,就完成了闪光伪元素的实现:
transform: skewx(-25deg);

- 实现动画
已经完成了闪光伪元素的实现,接下来就是要让元素动起来。css动画应用animation属性很容易实现,首先要先定义动画帧:
@keyframes flashLights {
0%{
transform: translate(-128%, 0) skewx(-25deg);
}
100% {
transform: translate(200%, 0) skewx(-25deg);
}
}
这里动画帧基本就是利用translate水平位移伪元素,然后将动画帧应用到伪元素animation属性:
animation: flashLights 4s ease-in infinite;
加上animation之后的效果如下图:
实际就是伪元素从图片上平移划过的效果:
- 动画位置和时间调整
以上已经实现了动画的主体功能,还要继续调整优化动画的起始和终止位置、动画的循环时间。
- 上面的实例图片,实际上已经对伪元素的位置做了调整,主要就是要让伪元素起始位置在图片左边外部,终止位置在图片右边外部,不能覆盖图片;使用left和tansform: translate来实现。
- 动画的循环时间调整主要在两方面:动画执行时间缩短(让动画的闪光更快);一次闪光之后,中间间隔小段时间。
@keyframes flashLights {
0%, 75% {
transform: translate(-128%, 0) skewx(-25deg);
}
100% {
transform: translate(200%, 0) skewx(-25deg);
}
}
animation: flashLights 4s ease-in infinite;
动画帧前75%的时间都是在起始位置静止的,后25%执行动画;这样就实现了4s的总时间内,前3秒作为间隔时间,后1s作为动画执行时间,同时实现了两方面的要求。
🤗对比分析
动画的平移还可以通过绝对定位的left属性实现,同样只需要改变left值实现闪光的平移。css代码如下:
.logo_flash:before {
background: -webkit-linear-gradient(0deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0));
transform: skewx(-25deg);
width: 150px;
height: 100%;
position: absolute;
left: -40%;
top: 0;
content: "";
animation: flashLights 4s ease-in infinite;
}
@keyframes flashLights {
0%,75% {
left: -40%;
top: 0;
}
100% {
left: 110%;
top: 0;
}
}
animation: flashLights 4s ease-in infinite;
同样可以实现闪光效果,看起来没有任何差别;那为什么要使用transform而不使用绝对定位呢?
这与浏览器的渲染机制有关,浏览器渲染动画每一帧必须经过以下步骤:
而想要获得流畅的动画效果,目标是每秒生成 60 帧,也就是每帧的预算约为 16 毫秒,但实际上,浏览器有整理工作要做,因此所有步骤需要在 10 毫秒内完成。如果无法符合此预算,帧率将下降产生卡顿。
因此需要在编码时,尽量减少以上帧渲染步骤的总时间,以减少浏览器开销、提高动画性能。
由于改变left属性的实现方案,改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成。所以此方案会经过帧渲染的全部步骤。
而使用transform的方案,不影响文档流、不依赖文档流、不会造成重排重绘(满足以上以上条件的css property只有transform和opacity)。更改一个既不要布局也不要绘制的属性,浏览器将跳到只执行合成:
这样动画的开销最小,性能也就最好。
可以通过Chrome devtools验证这个结论:
下图为使用改变left方案的performace时间统计:
下图为使用transform方案的performace时间统计:
对比发现,使用transform方案的动画确实比left方案少了,layout和paint步骤,直接跳到composite layers 步骤,渲染时间也相对更短。虽然,在实际显示效果和帧率下相差不大,但如果动画更加复杂或dom元素更多的情况下,两种方案的差别就会显现出来。
参考链接:
https://developers.google.com/web/fundamentals/performance/rail
https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/