大数跨境
0
0

一个花里胡哨的确认按钮

一个花里胡哨的确认按钮 码途钥匙
2025-08-14
0
· 点击蓝字,关注我们

































效果图

图片


一、HTML

这个按钮的 “骨架” 很清晰:外层是一个容器,里面分两部分 —— 左侧的图标区和右侧的 “Confirm” 文字。图标区是重点,包含类似 “小炮筒” 的图形和一组 “彩屑” 元素。“小炮筒” 由几个部分组合,能展现立体感;“彩屑” 是不同形状的小色块,平时藏着,只在特定时候出现。这些元素像积木一样有序组合,为后续设计打基础。

二、CSS
CSS 给按钮穿上了 “花衣服”,让它从结构变成视觉焦点。配色上,深色按钮配浅色文字,对比鲜明;“小炮筒” 用渐变色彩,加了细微阴影,更有立体感。按钮还有 “3D 效果”,鼠标移动时会轻微 “倾斜”,有了空间感。“彩屑” 设计多样,形状、颜色不同,平时隐藏。按钮边缘是圆润弧度,尺寸比例合适,兼顾美观与实用性。

三、JavaScript

JavaScript 让按钮 “活” 了起来,有了生动的交互。

鼠标在按钮上滑动,它会轻微 “跟随”,有即时反馈。点击时,“小炮筒” 有 “后坐力”,“彩屑” 像烟花般炸开,轨迹、速度、旋转角度各有不同,颜色也随机变化,最后慢慢消失。整个过程节奏得当,让简单的确认操作充满乐趣。



代码

<!DOCTYPE html><html lang="zh">  <head>    <meta charset="UTF-8" />    <title>一个花里胡哨的确认按钮</title>    <style>      .button {        --background#1e2235;        --color#f6f8ff;        --shadowrgba(09610.24);        --cannon-dark#a6accd;        --cannon-light#f6f8ff;        --cannon-shadowrgba(1315240.9);        --confetti-1#892ab8;        --confetti-2#ea4c89;        --confetti-3#ffff04;        --confetti-4#4af2fd;        --z-before: -6;        display: block;        outline: none;        cursor: pointer;        position: relative;        border0;        background: none;        padding9px 22px 9px 16px;        line-height26px;        font-family: inherit;        font-weight600;        font-size14px;        colorvar(--color);        -webkit-appearance: none;        -webkit-tap-highlight-color: transparent;        transition: transform var(--transform-duration, 0.4s);        will-change: transform;        transform-style: preserve-3d;        transformperspective(440pxrotateX(calc(var(--rx, 0) * 1deg))          rotateY(calc(var(--ry, 0) * 1deg)) translateZ(0);      }      .button:hover {        --transform-duration0.16s;      }      .button.success {        --confetti-scale0;        --stroke-dashoffset15;      }      .button:before {        content"";        position: absolute;        left0;        top0;        right0;        bottom0;        border-radius12px;        transformtranslateZ(calc(var(--z-before) * 1px));        backgroundvar(--background);        box-shadow0 4px 8px var(--shadow);      }      .button .icon,      .button span {        display: inline-block;        vertical-align: top;        position: relative;        z-index1;      }      .button .icon {        --z2px;        width24px;        height14px;        margin8px 16px 0 0;        transformtranslate(            calc(var(--icon-x, 0) * 1px),            calc(var(--icon-y, 0) * 1px)          )          translateZ(2px);      }      .button .icon .confetti {        position: absolute;        left17px;        bottom9px;      }      .button .icon .confetti svg {        width18px;        height16px;        display: block;        stroke-width1px;        fill: none;        stroke-linejoin: round;        stroke-linecap: round;      }      .button .icon .confetti svg * {        transition: stroke-dashoffset 0.2s;        stroke-dasharray: 15 20;        stroke-dashoffset: var(--stroke-dashoffset, 0);        stroke: var(--stroke-all, var(--stroke, var(--confetti-2)));      }      .button .icon .confetti svg *:nth-child(2) {        --strokevar(--confetti-3);      }      .button .icon .confetti svg *:nth-child(3) {        --strokevar(--confetti-1);      }      .button .icon .confetti .emitter {        position: absolute;        left4px;        bottom4px;        pointer-events: none;      }      .button .icon .confetti .emitter div {        width4px;        height4px;        margin: -2px 0 0 -2px;        border-radius1px;        position: absolute;        left0;        top0;        transform-style: preserve-3d;        backgroundvar(--confetti-all, var(--b, none));      }      .button .icon .confetti i {        width4px;        height4px;        display: block;        transformscale(var(--confetti-scale, 0.5));        position: absolute;        transition: transform 0.25s;        leftvar(--left, -1px);        topvar(--top, 3px);        border-radiusvar(--border-radius, 1px);        backgroundvar(--confetti-background, var(--confetti-3));      }      .button .icon .confetti i:nth-child(2) {        --left9px;        --top: -1px;        --border-radius2px;        --confetti-backgroundvar(--confetti-4);      }      .button .icon .confetti i:nth-child(3) {        --left5px;        --top3px;        --confetti-backgroundvar(--confetti-1);      }      .button .icon .confetti i:nth-child(4) {        --left10px;        --top14px;        --confetti-backgroundvar(--confetti-2);      }      .button .icon .confetti i:nth-child(5) {        --left9px;        --top7px;        --confetti-backgroundvar(--confetti-4);      }      .button .icon .confetti i:nth-child(6) {        --left6px;        --top8px;        --border-radius2px;        --confetti-backgroundvar(--confetti-2);      }      .button .icon .cannon {        position: relative;        width24px;        height14px;        transformtranslate(03pxrotate(-45deg);        filterdrop-shadow(-2px 2px 2px var(--cannon-shadow));      }      .button .icon .cannon:before,      .button .icon .cannon:after {        content"";        display: block;        height14px;      }      .button .icon .cannon:before {        backgroundlinear-gradient(          var(--cannon-dark),          var(--cannon-light) 50%,          var(--cannon-dark)        );        width100%;        -webkit-clip-pathpolygon(25px -1px0 52%25px 15px);        clip-pathpolygon(25px -1px0 52%25px 15px);      }      .button .icon .cannon:after {        width6px;        position: absolute;        right: -3px;        top0;        border-radius50%;        box-shadow: inset 0 0 0 0.5px var(--cannon-light);        backgroundlinear-gradient(          90deg,          var(--cannon-dark),          var(--cannon-light)        );      }      .button.white {        --background#fff;        --color#1e2235;        --border#e1e6f9;        --shadow: none;        --cannon-dark#103fc5;        --cannon-light#275efe;        --cannon-shadowrgba(09610.2);      }      .button.white:before {        box-shadow: inset 0 0 0 1px var(--border);      }      .button.grey {        --background#404660;        --cannon-shadowrgba(1315240.2);        --cannon-dark#d1d6ee;        --cannon-light#ffffff;      }      html {        box-sizing: border-box;        -webkit-font-smoothing: antialiased;      }      * {        box-sizing: inherit;      }      *:before,      *:after {        box-sizing: inherit;      }      body {        min-height100vh;        display: flex;        font-family"Inter", Arial;        justify-content: center;        align-items: center;        background#f6f8ff;      }      body .button {        margin0 12px;      }      body .dribbble {        position: fixed;        display: block;        right20px;        bottom20px;      }      body .dribbble img {        display: block;        height28px;      }      body .twitter {        position: fixed;        display: block;        right64px;        bottom14px;      }      body .twitter svg {        width32px;        height32px;        fill: #1da1f2;      }    </style>  </head>  <body>    <!-- partial:index.partial.html -->    <button class="button">      <div class="icon">        <div class="cannon"></div>        <div class="confetti">          <svg viewBox="0 0 18 16">            <polyline points="1 10 4 7 4 5 6 1" />            <path              d="M4,13 C5.33333333,9 7,7 9,7 C11,7 12.3340042,6 13.0020125,4"            />            <path              d="M6,15 C7.83362334,13.6666667 9.83362334,12.6666667 12,12 C14.1663767,11.3333333 15.8330433,9.66666667 17,7"            />          </svg>          <i></i><i></i><i></i><i></i><i></i><i></i>          <div class="emitter"></div>        </div>      </div>      <span>Confirm</span>    </button>    <!-- partial -->    <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>    <script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/Physics2DPlugin.min.js"></script>    <script>      document.querySelectorAll(".button").forEach((button) => {        const bounding = button.getBoundingClientRect();        button.addEventListener("mousemove"(e) => {          let dy = (e.clientY - bounding.top - bounding.height / 2) / -1;          let dx = (e.clientX - bounding.left - bounding.width / 2) / 10;          dy = dy > 10 ? 10 : dy < -10 ? -10 : dy;          dx = dx > 4 ? 4 : dx < -4 ? -4 : dx;          button.style.setProperty("--rx", dy);          button.style.setProperty("--ry", dx);        });        button.addEventListener("mouseleave"(e) => {          button.style.setProperty("--rx"0);          button.style.setProperty("--ry"0);        });        button.addEventListener("click"(e) => {          button.classList.add("success");          gsap.to(button, {            "--icon-x": -3,            "--icon-y"3,            "--z-before"0,            duration0.2,            onComplete() {              particles(button.querySelector(".emitter"), 100, -46, -80, -50);              gsap.to(button, {                "--icon-x"0,                "--icon-y"0,                "--z-before": -6,                duration1,                ease"elastic.out(1, .5)",                onComplete() {                  button.classList.remove("success");                },              });            },          });        });      });      function particles(parent, quantity, x, y, minAngle, maxAngle) {        let colors = ["#FFFF04""#EA4C89""#892AB8""#4AF2FD"];        for (let i = quantity - 1; i >= 0; i--) {          let angle = gsap.utils.random(minAngle, maxAngle),            velocity = gsap.utils.random(70140),            dot = document.createElement("div");          dot.style.setProperty(            "--b",            colors[Math.floor(gsap.utils.random(04))]          );          parent.appendChild(dot);          gsap.set(dot, {            opacity0,            x: x,            y: y,            scale: gsap.utils.random(0.40.7),          });          gsap            .timeline({              onComplete() {                dot.remove();              },            })            .to(              dot,              {                duration0.05,                opacity1,              },              0            )            .to(              dot,              {                duration1.8,                rotationX`-=${gsap.utils.random(7201440)}`,                rotationZ`+=${gsap.utils.random(7201440)}`,                physics2D: {                  angle: angle,                  velocity: velocity,                  gravity120,                },              },              0            )            .to(              dot,              {                duration1,                opacity0,              },              0.8            );        }      }    </script>  </body></html>




点分享
点收藏
点在看
点点赞

【声明】内容源于网络
0
0
码途钥匙
欢迎来到 Python 学习乐园!这里充满活力,分享前沿实用知识技术。新手或开发者,都能找到价值。一起在这个平台,以 Python 为引,开启成长之旅,探索代码世界,共同进步。携手 Python,共赴精彩未来,快来加入我们吧!
内容 992
粉丝 0
码途钥匙 欢迎来到 Python 学习乐园!这里充满活力,分享前沿实用知识技术。新手或开发者,都能找到价值。一起在这个平台,以 Python 为引,开启成长之旅,探索代码世界,共同进步。携手 Python,共赴精彩未来,快来加入我们吧!
总阅读43
粉丝0
内容992