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的实现步骤

  1. 实现闪光的伪元素
.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);
  1. 实现动画

已经完成了闪光伪元素的实现,接下来就是要让元素动起来。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之后的效果如下图:

实际就是伪元素从图片上平移划过的效果:

  1. 动画位置和时间调整
    以上已经实现了动画的主体功能,还要继续调整优化动画的起始和终止位置、动画的循环时间。
  • 上面的实例图片,实际上已经对伪元素的位置做了调整,主要就是要让伪元素起始位置在图片左边外部,终止位置在图片右边外部,不能覆盖图片;使用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/