查看原文
其他

牛B!纯 CSS 制作赛博朋克 2077 “故障风”按钮

(给程序员的那些事加星标

转自:CodingStarup

juejin.cn/post/6908565208596217863

大家好,我是 Steven。

虽然我不打机,但我都知道 赛博朋克 2077 这个游戏,在它的网页上,有一个 Available Now 的按钮,当游标移到它之上的时候,会有一个好像故障的毛刺效果。

这一期,我们就会模仿并且实现这个效果。

这个教程的视频版在

https://www.bilibili.com/video/BV15A411s7cX

编写 HTML 代码

打开 CodePen 编辑器 ( codepen.io ),在 HTML 的部份加入 <button> 标签,按钮的标题是 AVAILABLE NOW。

CSS 的部分

然后到 CSS 的部份,加入 body 标签,用 Flexbox 的方法将内容设定为上下左右置中。然后背景颜色,设定为黄色,加入 button 选择器,宽度设定为 380px,而高度设定为 86px,文字大小设定为 36px

然后我想换一种字型,到 Google Font 网站上,选择了 Bebas Neue 这个字型,将载入字体的代码贴到 HTML 内,然后将 CSS 字体的设定套用到 button 选择器内。

好了,将左下角变为斜角可以怎样做呢,一开始我想用 clip-path 去实现,但我想了又想,好像有一种更简单的方法,就是透过 linear-gradient 设定背景图片了。设定 background 是 linear-gradient(),角度设定为 45deg,然后由透明色的 50%,切换为红色的 50%,这样 50% 前的部份就会透明,而 50% 后的部份就是红色,做到一个颜色分割的效果。

那我们要将红色的部份占大多数,只需要将 50% 改为 5%,就可以做到左下的斜角了。

然后框线设定为 0,文字颜色设定为白色,letter-spacing 字距设定为 3px,然后我觉得文字的上下有点不对齐,设定 line-height 是 88px,这样就好一点了。

然后设定右边的亮蓝色边,将 box-shadow 设定为 6px 0px 0px #00E6F6,再将 outline 设定为 transparent,这样当点击按钮的时候,就不会有浏览器预设的按钮边框了。

现在按钮的样式大致上都实现了,那么怎样实现当游标移到它之上的时候,出现的那些毛刺效果呢?我们先在这个按钮上,重叠一个一模一样的按钮 要实现这一步,我会使用 Pseudo 伪类选择器。

实现变色层

加入 button::after 选择器,将 content 设定为 AVAILABLE NOW,然设 display 设定为 blockposition 设定为 absolute,当这里的 position 设定为 absolute,我们就回到 button 选择器里面,将 position 设定为 relative,这样它才可以根据按钮去定位,然后上下左右,都设定为 0,其余样式都与原来的按钮相同,所以在 button 选择器后面,加入逗号,button::after 就可以了。

这个叠在上面的按钮,我们会透过 clip-path(),裁剪其中一些部份出来,然后配合 transform 进行一些位移,再透过 animation 去达到动画的效果。所以我们会先在这一层做好变色的效果,首先是左下的斜角,会突显一些蓝色出来,将透明色的比例改为 3%,然后在中间加入一个亮蓝色,由 3% 至 5%,然后就是中间的文字,加入 text-shadow 文字阴影,在左边加入一个黄色,右边加入一个蓝色,大致上就是这样了。

图形切割

下一步就是处理图形分割的部份,加入 clip-path,套用 inset(),里面的设定值有 4 个,分别代表上右下左,即是要向内缩小多少的意思。先设定为 80% \-6px 0 0,右边设定为 -6px 的原因是,右边有一个亮蓝色的边框,由于它不计算在容器的范围内,所以要将右边设定为负数。

由于现在是完全重叠的状态,切割了也不明显,加入 transform: translate(-20px, 10px) 稍为移开一点,就可以清楚看到正在切割的是哪个部份了。先将这个切片储存到 CSS 变数中,名为 slice-1

第二个切片的数值是 50% \-6px 30% 0,储存为 slice-2。第三个切片的数值是 10% \-6px 85% 0,是上面的部份,储存为 slice-3。第四个切片的数值是 40% \-6px 43% 0,都是文字的部份,储存为 slice-4。再做多一个切片就好了,第五个的数值是 80% \-6px 5% 0,是下方的部份,储存为 slice-5

再新增一个预设值,50% 50% 50% 50%,储存为 slice-0,那我们这里 clip-path 的设定值改为 var(--slice-0),并且将 transform 移除就可以了。

其实这里所做的切片的位置和数量是挺随机的,大家可以根据想达到的效果自行更改数值。

动画制作

最后,制作动画的部份,新增 @keyframes glitch 定义一个动画名为 glitch,这里我分为 11 个部份,0%,10%,20%,如此类推,一直至到 100%。然后在每一个部份都设置 clip-path() 和 transform()clip-path() 就随机套用一个切片,而 transform() 就定义一些随机值,稍为移动一下就可以了。

@keyframes glitch {
  0% {
    clip-pathvar(--slice-1);
    transformtranslate(-20px, -10px);
  }
  
  10% {
    clip-pathvar(--slice-3);
    transformtranslate(10px10px);
  }
  
  20% {
    clip-pathvar(--slice-1);
    transformtranslate(-10px10px);
  }
  
  30% {
    clip-pathvar(--slice-3);
    transformtranslate(0px5px);
  }
  
  40% {
    clip-pathvar(--slice-2);
    transformtranslate(-5px0px);
  }
  
  50% {
    clip-pathvar(--slice-3);
    transformtranslate(5px0px);
  }
  
  60% {
    clip-pathvar(--slice-4);
    transformtranslate(5px10px);
  }
  
  70% {
    clip-pathvar(--slice-2);
    transformtranslate(-10px10px);
  }
  
  80% {
    clip-pathvar(--slice-5);
    transformtranslate(20px, -10px);
  }
  
  90% {
    clip-pathvar(--slice-1);
    transformtranslate(-10px0px);
  }
  
  100% {
    clip-pathvar(--slice-1);
    transformtranslate(0);
  }
}
复制代码

keyframes 的部份设定好了,加入 button:hover::after 选择器,当游标移到按钮之上的时候,触发动画,设定 animation,时间是 1 秒,动画名称是 glitch。试试看,基本上是可以了。

不过,这个是故障的效果呢,动画怎么会这么流畅,我们为它加一个设定,让它变得十分卡顿。设定 animation-timing-function 为 steps(2, end),数字越小,就越卡顿,大家可以试试。

我们来看看这个案例的完成效果

以上,就是要介绍的全部内容。



- EOF -


推荐阅读  点击标题可跳转

1、用 CSS 实现一个抽奖转盘,附详细代码和思路

2、基于 Vue 的前端架构,我做了这 15 点

3、一篇来自前端同学对后端接口的吐槽


关注「程序员的那些事」加星标,不错过圈内事

点赞和在看就是最大的支持❤️

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存