CSS实现一个故障时钟效果
起因
最近公司事情不是太多,我趁着这段时间在网上学习一些Cool~的效果。今天我想和大家分享一个故障时钟的效果。很多时候,一个效果开始看起来很难,但是当你一步步摸索之后,就会发现其实它们只是由一些简单的效果组合而成的。

什么是故障效果(Glitch)
"glitch" 效果是一种模拟数字图像或视频信号中出现的失真、干扰或故障的视觉效果。它通常表现为图像的一部分或整体闪烁、抖动、扭曲、重叠或变形。这种效果常常被用来传达技术故障、数字崩溃、未来主义、复古风格等主题,也经常在艺术作品、音乐视频、电影、广告和网页设计中使用。Glitch 效果通常通过调整图像、视频或音频的编码、解码或播放过程中的参数来实现。 来自ChatGPT
可以看到关键的表现为一部分或整体闪烁、抖动、扭曲、重叠或变形,所以我们应该重点关注用CSS实现整体闪烁、抖动、扭曲、重叠或变形
CSS 实现闪烁
Glitch 闪烁通常是指图像或视频中出现的突然的、不规则的、瞬间的明暗变化或闪烁效果
那么我们有没有办法通过CSS来实现上述的效果,答案是通过随机不规则的clip-path来实现!
我们先来看看clip-path的定义与用法
clip-pathCSS 属性使用裁剪方式创建元素的可显示区域。区域内的部分显示,区域外的隐藏。
/* <basic-shape> values */
clip-path: inset(100px 50px);
clip-path: circle(50px at 0 100px);
clip-path: ellipse(50px 60px at 0 10% 20%);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
clip-path: path(
"M0.5,1 C0.5,1,0,0.7,0,0.3 A0.25,0.25,1,1,1,0.5,0.3 A0.25,0.25,1,1,1,1,0.3 C1,0.7,0.5,1,0.5,1 Z"
);
再想想所谓的Glitch故障闪烁时的效果是不是就是部分画面被切掉了~
span {  
display: block;  
position: relative;  
font-size: 128px;  
line-height: 1;  
animation: clock 1s infinite linear alternate-reverse;  
}
@keyframes clock {  
0%{  
clip-path: inset(0px 0px calc(100% - 10px) 0);  
}  
100%{  
clip-path: inset(calc(100% - 10px) 0px 0px 0);  
}  
}
此时的效果如下:

啥啥啥,这看着是什么呀根本不像闪烁效果嘛,先别急,想想我们闪烁效果的定义突然的、不规则的、瞬间的明暗变化,此时因为我们是在切割整体元素,如果我们再后面再重叠一个正常元素!
span {  
display: block;  
position: relative;  
font-size: 128px;  
line-height: 1;  
    //animation: clock 1s infinite linear alternate-reverse;  
    &:before{  
display: block;  
content: attr(data-time);  
position: absolute;  
top: 0;  
color: $txt-color;  
background: $bg-color;  
overflow: hidden;  
width: 720px;  
height: 128px;  
    }  
    &:before {  
left: -2px;  
animation: c2 1s infinite linear alternate-reverse;  
    }  
}
@keyframes c2 {  
0%{  
clip-path: inset(0px 0px calc(100% - 10px) 0);  
    }  
100%{  
clip-path: inset(calc(100% - 10px) 0px 0px 0);  
    }  
}

可以看到通过手动偏移了-2px后然后不断剪裁元素已经有了一定的闪烁效果,但是目前的闪烁效果过于呆滞死板,我们通过scss的随机函数优化一下效果。
@keyframes c2 {  
@for $i from 0 through 20 {  
        #{percentage($i / 20)} {  
            $y1: random(100);  
            $y2: random(100);  
clip-path: polygon(0% $y1 * 1px, 100% $y1 * 1px, 100% $y2 * 1px, 0% $y2 * 1px); 
        }  
    }  
23% {  
transform: scaleX(0.8);  
    }  
}
此时效果如下

可以看到闪烁的效果已经很强烈了,我们依葫芦画瓢再叠加一个元素上去使得故障效果再强烈一些。
span {  
display: block;  
position: relative;  
font-size: 128px;  
line-height: 1;  
    &:before,  
    &:after {  
display: block;  
content: attr(data-time);  
position: absolute;  
top: 0;  
color: $txt-color;  
background: $bg-color;  
overflow: hidden;  
width: 720px;  
height: 128px;  
    }  
    &:before {  
left: calc(-#{$offset-c2});  
text-shadow: #{$lay-c2} 0 #{$color-c2};  
animation: c2 1s infinite linear alternate-reverse;  
    }  
    &:after {  
left: #{$offset-c1};  
text-shadow: calc(-#{$lay-c1}) 0 #{$color-c1};  
animation: c1 2s infinite linear alternate-reverse;  
    }  
}

此时我们已经通过:before和:after叠加了相同的元素并且一个设置蓝色一个设置红色,让故障效果更真实!
CSS 实现扭曲效果
上述的效果已经非常贴近我们传统意义上理解的Glitch效果了,但是还差了一点就是通常表现为图像的一部分或整体闪烁、抖动、扭曲、重叠或变形中的扭曲和变形,碰巧的是CSS实现这个效果非常容易,来看看~
skewX()函数定义了一个转换,该转换将元素倾斜到二维平面上的水平方向。它的结果是一个<transform-function>数据类型。

Cool~最后一块拼图也被补上了~~
@keyframes is-off {  
0%, 50%, 80%, 85% {  
opacity: 1;  
    }  
56%, 57%, 81%, 84% {  
opacity: 0;  
    }  
58% {  
opacity: 1;  
    }  
71%, 73% {  
transform: scaleY(1) skewX(0deg);  
    }  
72% {  
transform: scaleY(3) skewX(-60deg);  
    }  
91%, 93% {  
transform: scaleX(1) scaleY(1) skewX(0deg);  
color: $txt-color;  
    }  
92% {  
transform: scaleX(1.5) scaleY(0.2) skewX(80deg);  
color: green;  
    }  
}
来看看完整的效果和代码吧!
结语
春风若有怜花意,可否许我再少年。
来源:juejin.cn/post/7355302255409184807