美文网首页
clip-path特效之赛博朋克按钮

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

作者: 某时橙 | 来源:发表于2020-12-18 18:13 被阅读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按钮本来的样子了?
    以上。

    相关文章

      网友评论

          本文标题:clip-path特效之赛博朋克按钮

          本文链接:https://www.haomeiwen.com/subject/hxhtnktx.html