【问题标题】:Make Button Animation like in Google (Ripple Effect)制作 Google 中的按钮动画(波纹效果)
【发布时间】:2021-06-21 04:36:20
【问题描述】:

我在一个网站上发现了一个带有 google Button 动画的按钮。

如何制作这样一个按钮,无论你点击哪里,它都会产生动画?

这是我到目前为止所做的代码:

button {
  text-transform: uppercase;
  padding: 0.8em;
  width: 100px;
  background: #0053d9;
  color: #fff;
  border: none;
  border-radius: 5px;
  transition: all 0.2s;
  font-size: 15px;
  font-weight: 500;
}

button:hover {
  filter: brightness(80%);
  cursor: pointer;
}

button:active {
  transform: scale(0.92)
}
<button>Login</button>

【问题讨论】:

  • 您将不得不使用 JS 和 CSS 来使“波纹”从鼠标所在的位置出现,但是如果您希望波纹从按钮的中间出现,那就是可以使用纯 CSS。你想要这两个选项中的哪一个?
  • 正如@AlphaHowl 所说,如果您希望波纹从鼠标所在的位置出现,则需要使用 Javascript。可以参考这个例子创建类似的按钮codepen.io/BretCameron/pen/mdPMVaW
  • @AlphaHowl 老实说,我想要 JS 版本,但 CSS 版本也不错
  • 好的,等等……
  • @PR7 哦,那也很酷!谢谢!

标签: html css animation button


【解决方案1】:

这种效果被称为物质涟漪效应(或者至少这是大多数人所说的)。

有两种方法可以实现这种效果 - 一种使用 JS 和 CSS 来获得完整的效果,这意味着波纹来自鼠标所在的位置,另一种使用纯 CSS,不使用 JS - 这会导致无论鼠标在按钮内的哪个位置,按钮都会发出波纹。

有些人更喜欢纯 CSS 版本,因为它更干净,但大多数人更喜欢完整版本,因为它考虑了鼠标位置,因此提供了更好的体验...

不管怎样,我已经创建了这两个效果,选择你喜欢的任何一个:)。

PS:这里是您看到的任何完整版本的规则:

  • 必须在鼠标按下按钮时创建波纹 - 不是在单击鼠标时,因为这在移动设备上需要额外的一百毫秒(因为移动浏览器延迟将点击事件传递给能够检查它是单击还是双击)。因此,在显示涟漪之前存在这种延迟,用户体验会急剧下降,因为您的网站会显得缓慢和滞后,即使它可能不是。
  • 波纹必须停留在按钮上并覆盖其背景,直到鼠标抬起或按钮失去焦点 - 以先到者为准。

废话不多说,代码如下……

window.addEventListener("mousedown", e => {
    const target = e.target;

    if(target.nodeName == "BUTTON" && !target.classList.contains("css-only-ripple")) {
      show_ripple(target);
    }
  });
  function show_ripple(button) {
    const style = getComputedStyle(button);
    let ripple_elmnt = document.createElement("span");
    let diameter = Math.max(parseInt(style.height), parseInt(style.width)) * 1.5;
    let radius = diameter / 2;

    ripple_elmnt.className = "ripple";
    ripple_elmnt.style.height = ripple_elmnt.style.width = diameter + "px";
    ripple_elmnt.style.position = "absolute";
    ripple_elmnt.style.borderRadius = "1000px";
    ripple_elmnt.style.pointerEvents = "none";
    
    ripple_elmnt.style.left = event.clientX - button.offsetLeft - radius + "px";
    ripple_elmnt.style.top = event.clientY - button.offsetTop - radius + "px";

    ripple_elmnt.style.transform = "scale(0)";
    ripple_elmnt.style.transition = "transform 500ms ease, opacity 400ms ease";
    ripple_elmnt.style.background = "rgba(255,255,255,0.5)";
    button.appendChild(ripple_elmnt);

    setTimeout(() => {
      ripple_elmnt.style.transform = "scale(1)";
    }, 10);

    button.addEventListener("mouseup", e => {
      ripple_elmnt.style.opacity = 0;
      setTimeout(() => {
        try {
          button.removeChild(ripple_elmnt);
        } catch(er) {}
      }, 400);
    }, {once: true});
    button.addEventListener("blur", e => {
      ripple_elmnt.style.opacity = 0;
      setTimeout(() => {
        try {
          button.removeChild(ripple_elmnt);
        } catch(er) {}
      }, 450);
    }, {once: true});
  }
button {
      text-transform: uppercase;
      padding: 0.8em;
      width: 100px;
      background: #0053d9;
      color: #fff;
      border: none;
      border-radius: 5px;
      transition: all 0.2s;
      font-size: 15px;
      font-weight: 500;
      position: relative;
      overflow: hidden;
    }

    button:hover {
      filter: brightness(80%);
      cursor: pointer;
    }

    button:active {
      transform: scale(0.92)
    }

    .css-only-ripple::after {
      content: "";
      position: absolute;
      top: 50%;
      left: 50%;
      width: 150%;
      aspect-ratio: 1 / 1;
      transform: translate(-50%, -50%) scale(0);
      pointer-events: none;
      border-radius: 999px;
      background: rgba(255, 255, 255, .5);
    }

    .css-only-ripple:focus::after {
      animation: scale_up 1000ms forwards;
    }

    @keyframes scale_up {
      0% {
        transform: translate(-50%, -50%) scale(0);
        opacity: 1;
      }
      100% {
        transform: translate(-50%, -50%) scale(1);
        opacity: 0;
      }
    }
<button>Login</button>
<button class="css-only-ripple">Login</button>

<br>
The first button is the CSS and JS version, and the second is the CSS-only version. For the CSS-only button, you have to unfocus it before you click it again or the ripple will not show (it only gets created on focus)

【讨论】:

  • 我的荣幸:)
猜你喜欢
  • 2020-09-13
  • 1970-01-01
  • 2021-06-26
  • 2015-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-16
  • 1970-01-01
相关资源
最近更新 更多