clip-path CSS 属性可以创建一个只有元素的部分区域可以显示的剪切区域。区域内的部分显示,区域外的隐藏。剪切区域是被引用内嵌的URL定义的路径或者外部 SVG 的路径。
也就是说,使用clip-path可以将一个容器切成我们想要的样子。
例如这样:
<div>TXET</div>
div { margin: auto; padding: 10px; line-height: 1.2; font-size: 60px; background: #ddd; }
正常是这样的:
使用clip-path剪裁为一个平行四边形:
div { margin: auto; padding: 10px; line-height: 1.2; font-size: 60px; background: #ddd; + clip-path: polygon(35% 0, 85% 0, 75% 100%, 25% 100%); }
结果如下:
那么,思路就有了,我们可以将一个文字复制几个副本,重叠在一起,再分别裁剪这几个副本进行位移动画即可。
使用 clip-path 实现文字断裂动画我们还是使用元素的::before、::after两个伪元素复制两份副本,再分别使用clip-path进行剪裁,再使用 transform 进行控制。
核心代码:
<div data-text="Text Crack"> <span>Text Crack</span> </div>
div { position: relative; animation: shake 2.5s linear forwards; } div span { clip-path: polygon(10% 0%, 44% 0%, 70% 100%, 55% 100%); } div::before, div::after { content: attr(data-text); position: absolute; top: 0; left: 0; } div::before { animation: crack1 2.5s linear forwards; clip-path: polygon(0% 0%, 10% 0%, 55% 100%, 0% 100%); } div::after { animation: crack2 2.5s linear forwards; clip-path: polygon(44% 0%, 100% 0%, 100% 100%, 70% 100%); } // 元素晃动,断裂前摇 @keyframes shake { ... } @keyframes crack1 { 0%, 95% { transform: translate(-50%, -50%); } 100% { transform: translate(-55%, -45%); } } @keyframes crack2 { 0%, 95% { transform: translate(-50%, -50%); } 100% { transform: translate(-45%, -55%); } }
可以得到这样的效果:
clip-path 的 Glitch ArtOK,继续,有了上面的铺垫之后,接下来,我们把这个效果作用于图片之上,并且再添加上动画。
随便选一张图片:
哇哦,非常的赛博朋克。
实现动画的关键在于:
使用元素的两个伪元素,生成图片的两个副本
使用clip-path对两个副本图片元素进行裁剪,然后进行位移、transform变换、添加滤镜等一系列操作。
简单贴一下伪代码:
$img: "https://mzz-files.oss-cn-shenzhen.aliyuncs.com///uploads/U1002433/0cb5e044a1f0f7fc15f61264ee97ac1f.png"; div { position: relative; width: 658px; height: 370px; background: url($img) no-repeat; animation: main-img-hide 16s infinite step-end; } div::before, div::after { position: absolute; width: 658px; height: 370px; top: 0; left: 0; background: inherit; } div::after { content: ""; animation: glitch-one 16s infinite step-end; } div::before { content: ""; animation: glitch-two 16s infinite 1s step-end; } @keyframes glitch-one { @for $i from 20 to 30 { #{$i / 2}% { left: #{randomNum(200, -100)}px; clip-path: inset(#{randomNum(150, 30)}px 0 #{randomNum(150, 30)}px); } } 15.5% { clip-path: inset(10px 0 320px); left: -20px; } 16% { clip-path: inset(10px 0 320px); left: -10px; opacity: 0; } .... } @keyframes glitch-two { @for $i from 40 to 50 { #{$i / 2}% { left: #{randomNum(200, -100)}px; clip-path: inset(#{randomNum(180)}px 0 #{randomNum(180)}px); } } 25.5% { clip-path: inset(10px 0 320px); left: -20px; } 26% { clip-path: inset(10px 0 320px); left: -10px; opacity: 0; } ... } @keyframes main-img-hide { 5% { filter: invert(1); } ... }
由于动画部分代码量太多,所以使用了 SASS 循环函数随机生成了部分。如果手动控制,效果其实还会更好,当然,调试动画消耗的时间会更多。
看看效果,虽然 CSS 能力有限,但实际的效果也不是说那么的差:
总结