clip-path特效之赛博朋克按钮

2020-12-18  本文已影响0人  某时橙

part1 写在前面

codepen上的老哥,想象力可谓是天马行空,本该觉得了解clip-path的使用和用法的我看完这个按钮感觉理解又上升了一个新高度。
上按钮:

按钮.gif
你永远可以在codepen上亲自体验,地址:
https://codepen.io/jh3y/pen/PoGbxLp
下面要讲解代码思路,默认你已经完全了解clip-path动画的用法了,若对此有惑,可看我往期文章

part2 代码思路讲解:

源码:

Html部分

<button class="cybr-btn">
  Cyber<span aria-hidden>_</span>
  <span aria-hidden class="cybr-btn__glitch">Cyber_</span>
  <span aria-hidden class="cybr-btn__tag">R25</span>
</button>
<button class="cybr-btn">
  Buttons<span aria-hidden>_</span>
  <span aria-hidden class="cybr-btn__glitch">Buttons_</span>
  <span aria-hidden class="cybr-btn__tag">R25</span>
</button>
@font-face {
  font-family: Cyber;
  src: url("https://assets.codepen.io/605876/Blender-Pro-Bold.otf");
  font-display: swap;
}

* {
  box-sizing: border-box;
}

body {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  min-height: 100vh;
  font-family: 'Cyber', sans-serif;
  background: linear-gradient(90deg, #f5ed00 70%, #e6de00 70%), #fff700;
}

body .cybr-btn + .cybr-btn {
  margin-top: 2rem;
}

.cybr-btn {
  --primary: hsl(var(--primary-hue), 85%, calc(var(--primary-lightness, 50) * 1%));
  --shadow-primary: hsl(var(--shadow-primary-hue), 90%, 50%);
  --primary-hue: 0;
  --primary-lightness: 50;
  --color: hsl(0, 0%, 100%);
  --font-size: 26px;
  --shadow-primary-hue: 180;
  --label-size: 9px;
  --shadow-secondary-hue: 60;
  --shadow-secondary: hsl(var(--shadow-secondary-hue), 90%, 60%);
  --clip: polygon(0 0, 100% 0, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 70%);
  --border: 4px;
  --shimmy-distance: 5;
  --clip-one: polygon(0 2%, 100% 2%, 100% 95%, 95% 95%, 95% 90%, 85% 90%, 85% 95%, 8% 95%, 0 70%);
  --clip-two: polygon(0 78%, 100% 78%, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 78%);
  --clip-three: polygon(0 44%, 100% 44%, 100% 54%, 95% 54%, 95% 54%, 85% 54%, 85% 54%, 8% 54%, 0 54%);
  --clip-four: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0);
  --clip-five: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0);
  --clip-six: polygon(0 40%, 100% 40%, 100% 85%, 95% 85%, 95% 85%, 85% 85%, 85% 85%, 8% 85%, 0 70%);
  --clip-seven: polygon(0 63%, 100% 63%, 100% 80%, 95% 80%, 95% 80%, 85% 80%, 85% 80%, 8% 80%, 0 70%);
  font-family: 'Cyber', sans-serif;
  color: var(--color);
  cursor: pointer;
  background: transparent;
  text-transform: uppercase;
  font-size: var(--font-size);
  outline: transparent;
  letter-spacing: 2px;
  position: relative;
  font-weight: 700;
  border: 0;
  min-width: 300px;
  height: 75px;
  line-height: 75px;
  transition: background 0.2s;
}

.cybr-btn:hover {
  --primary: hsl(var(--primary-hue), 85%, calc(var(--primary-lightness, 50) * 0.8%));
}
.cybr-btn:active {
  --primary: hsl(var(--primary-hue), 85%, calc(var(--primary-lightness, 50) * 0.6%));
}

.cybr-btn:after,
.cybr-btn:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  clip-path: var(--clip);
  z-index: -1;
}

.cybr-btn:before {
  background: var(--shadow-primary);
  transform: translate(var(--border), 0);
}

.cybr-btn:after {
  background: var(--primary);
}

.cybr-btn__tag {
  position: absolute;
  padding: 1px 4px;
  letter-spacing: 1px;
  line-height: 1;
  bottom: -5%;
  right: 5%;
  font-weight: normal;
  color: hsl(0, 0%, 0%);
  font-size: var(--label-size);
}

.cybr-btn__glitch {
  position: absolute;
  top: calc(var(--border) * -1);
  left: calc(var(--border) * -1);
  right: calc(var(--border) * -1);
  bottom: calc(var(--border) * -1);
  background: var(--shadow-primary);
  text-shadow: 2px 2px var(--shadow-primary), -2px -2px var(--shadow-secondary);
  clip-path: var(--clip);
  animation: glitch 2s infinite;
  display: none;
}

.cybr-btn:hover .cybr-btn__glitch {
  display: block;
}

.cybr-btn__glitch:before {
  content: '';
  position: absolute;
  top: calc(var(--border) * 1);
  right: calc(var(--border) * 1);
  bottom: calc(var(--border) * 1);
  left: calc(var(--border) * 1);
  clip-path: var(--clip);
  background: var(--primary);
  z-index: -1;
}

@keyframes glitch {
  0% {
    clip-path: var(--clip-one);
  }
  2%, 8% {
    clip-path: var(--clip-two);
    transform: translate(calc(var(--shimmy-distance) * -1%), 0);
  }
  6% {
    clip-path: var(--clip-two);
    transform: translate(calc(var(--shimmy-distance) * 1%), 0);
  }
  9% {
    clip-path: var(--clip-two);
    transform: translate(0, 0);
  }
  10% {
    clip-path: var(--clip-three);
    transform: translate(calc(var(--shimmy-distance) * 1%), 0);
  }
  13% {
    clip-path: var(--clip-three);
    transform: translate(0, 0);
  }
  14%, 21% {
    clip-path: var(--clip-four);
    transform: translate(calc(var(--shimmy-distance) * 1%), 0);
  }
  25% {
    clip-path: var(--clip-five);
    transform: translate(calc(var(--shimmy-distance) * 1%), 0);
  }
  30% {
    clip-path: var(--clip-five);
    transform: translate(calc(var(--shimmy-distance) * -1%), 0);
  }
  35%, 45% {
    clip-path: var(--clip-six);
    transform: translate(calc(var(--shimmy-distance) * -1%));
  }
  40% {
    clip-path: var(--clip-six);
    transform: translate(calc(var(--shimmy-distance) * 1%));
  }
  50% {
    clip-path: var(--clip-six);
    transform: translate(0, 0);
  }
  55% {
    clip-path: var(--clip-seven);
    transform: translate(calc(var(--shimmy-distance) * 1%), 0);
  }
  60% {
    clip-path: var(--clip-seven);
    transform: translate(0, 0);
  }
  31%, 61%, 100% {
    clip-path: var(--clip-four);
  }
}

.cybr-btn:nth-of-type(2) {
  --primary-hue: 260;
}

不要被这么长一大串css给吓到了哈,还有一大串--Variable,var函数,hsl函数hh
我们来逐步拆解,接下来你最好在codepen上跟着我一步步调试,毕竟自己亲自动手收获的体验,才是理解最深刻的。
首先关注html部分
我们把

  <button class="cybr-btn">
        Cyber<span aria-hidden>_</span>
        <!-- <span aria-hidden class="cybr-btn__glitch">Cyber_</span> -->
        <span aria-hidden class="cybr-btn__tag">R25</span>
      </button>

cybr-btn__glitch给注释掉,你会发现按钮的特效部分消失了,
鼠标划上去只是亮度降低


无特效按钮.png

很显然,特效是在cybr-btn__glitch上实现的。

非特效部分

取消特效后的cybr-btn是如何布局的?
这里不细说,我永远相信阅读我文章的你已经拥有基本的css基础hh
但值得一提的是,这个盒子明显不是普通div的方方正正,如何实现?我相信你已经猜到了
利用clip-path即源码中的

 --clip: polygon(0 0, 100% 0, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 70%);

为了让你相信clip-path的神奇,我特地剖离了代码


如图所示

特效部分

cybr的特效速度太快啦!我们将它放慢


P2.gif

还是看不清楚?给你保姆级的体验
让特效彻底裸奔后的版本


P3.gif

我们谈谈裸奔版本的动画实现:
源码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            --primary: hsl(var(--primary-hue), 85%, calc(var(--primary-lightness, 50) * 1%));
            --shadow-primary: hsl(var(--shadow-primary-hue), 90%, 50%);
            --primary-hue: 0;
            --primary-lightness: 50;
            --color: hsl(0, 0%, 100%);
            --font-size: 26px;
            --shadow-primary-hue: 180;
            --label-size: 9px;
            --shadow-secondary-hue: 60;
            --shadow-secondary: hsl(var(--shadow-secondary-hue), 90%, 60%);
            --clip: polygon(0 0, 100% 0, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 70%);
            --border: 4px;
            --shimmy-distance: 5;
            --clip-one: polygon(0 2%, 100% 2%, 100% 95%, 95% 95%, 95% 90%, 85% 90%, 85% 95%, 8% 95%, 0 70%);
            --clip-two: polygon(0 78%, 100% 78%, 100% 100%, 95% 100%, 95% 90%, 85% 90%, 85% 100%, 8% 100%, 0 78%);
            --clip-three: polygon(0 44%, 100% 44%, 100% 54%, 95% 54%, 95% 54%, 85% 54%, 85% 54%, 8% 54%, 0 54%);
            --clip-four: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0);
            --clip-five: polygon(0 0, 100% 0, 100% 0, 95% 0, 95% 0, 85% 0, 85% 0, 8% 0, 0 0);
            --clip-six: polygon(0 40%, 100% 40%, 100% 85%, 95% 85%, 95% 85%, 85% 85%, 85% 85%, 8% 85%, 0 70%);
            --clip-seven: polygon(0 63%, 100% 63%, 100% 80%, 95% 80%, 95% 80%, 85% 80%, 85% 80%, 8% 80%, 0 70%);
            font-family: 'Cyber', sans-serif;
        }

        .ele-0 {

            width: 800px;
            height: 400px;
            position: absolute;
            animation: move-0 20s linear  0s;
            background-color: black;
            clip-path: var(--clip);
        }

        @keyframes move-0 {
            0% {
                clip-path: var(--clip-one);
            }

            2%,
            8% {
                clip-path: var(--clip-two);
                transform: translate(calc(var(--shimmy-distance) * -1%), 0);
            }

            6% {
                clip-path: var(--clip-two);
                transform: translate(calc(var(--shimmy-distance) * 1%), 0);
            }

            9% {
                clip-path: var(--clip-two);
                transform: translate(0, 0);
            }

            10% {
                clip-path: var(--clip-three);
                transform: translate(calc(var(--shimmy-distance) * 1%), 0);
            }

            13% {
                clip-path: var(--clip-three);
                transform: translate(0, 0);
            }

            14%,
            21% {
                clip-path: var(--clip-four);
                transform: translate(calc(var(--shimmy-distance) * 1%), 0);
            }

            25% {
                clip-path: var(--clip-five);
                transform: translate(calc(var(--shimmy-distance) * 1%), 0);
            }

            30% {
                clip-path: var(--clip-five);
                transform: translate(calc(var(--shimmy-distance) * -1%), 0);
            }

            35%,
            45% {
                clip-path: var(--clip-six);
                transform: translate(calc(var(--shimmy-distance) * -1%));
            }

            40% {
                clip-path: var(--clip-six);
                transform: translate(calc(var(--shimmy-distance) * 1%));
            }

            50% {
                clip-path: var(--clip-six);
                transform: translate(0, 0);
            }

            55% {
                clip-path: var(--clip-seven);
                transform: translate(calc(var(--shimmy-distance) * 1%), 0);
            }

            60% {
                clip-path: var(--clip-seven);
                transform: translate(0, 0);
            }

            31%,
            61%,
            100% {
                clip-path: var(--clip-four);
            }
        }
    </style>
</head>

<body>
    <div class="ele-0"></div>
</body>

</html>

很显然,就是clip-path的动画转换+一个translate移动动画。
所以

 <span aria-hidden class="cybr-btn__glitch">Cyber_</span>

这个内部按钮就只是一个附带了上述裸奔特效的按钮而已
为了看看glitch本来的样子,把不必要的部分注释掉后

<style>

/* .cybr-btn:after,
.cybr-btn:before {
...
}

.cybr-btn:before {
...
}

.cybr-btn:after {
...
} */
.cybr-btn__glitch {
  ...
  /* animation: glitch 2s infinite; */
  /* display: none; */
}
</style>
<html>
<button class="cybr-btn">
        <!-- Cyber<span aria-hidden>_</span> -->
        <span aria-hidden class="cybr-btn__glitch">Cyber_</span>
        <!-- <span aria-hidden class="cybr-btn__tag">R25</span> -->
      </button>
</html>
image.png

按钮就如上所述,请读者脑内把这个按钮和裸奔特效合成一下,是不是就是cybr按钮本来的样子了?
以上。

上一篇下一篇

猜你喜欢

热点阅读