像 Google 一样制作按钮动画(涟漪效果)
Make Button Animation like in Google (Ripple Effect)
我在网站上找到了一个按钮,该按钮具有 google 按钮的动画效果。
你如何制作这样一个按钮,无论你点击哪里,它都会制作动画?
这是我到目前为止所做的代码:
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>
这种效应被称为 Material 涟漪效应(或者至少是大多数人的说法)。
有两种方法可以实现这种效果 - 一种使用 JS 和 CSS,以获得成熟的效果,这意味着波纹从鼠标所在的位置产生,另一种使用纯 CSS,没有 JS - 无论鼠标在按钮内的哪个位置,都会导致按钮出现波纹。
有些人更喜欢 CSS-only 版本,因为它更干净,但大多数人更喜欢完整版本,因为它考虑了鼠标位置,因此提供了更好的体验...
不管怎样,这两种效果我都做了,你喜欢哪个就选哪个吧:)。
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)
我在网站上找到了一个按钮,该按钮具有 google 按钮的动画效果。
你如何制作这样一个按钮,无论你点击哪里,它都会制作动画?
这是我到目前为止所做的代码:
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>
这种效应被称为 Material 涟漪效应(或者至少是大多数人的说法)。
有两种方法可以实现这种效果 - 一种使用 JS 和 CSS,以获得成熟的效果,这意味着波纹从鼠标所在的位置产生,另一种使用纯 CSS,没有 JS - 无论鼠标在按钮内的哪个位置,都会导致按钮出现波纹。
有些人更喜欢 CSS-only 版本,因为它更干净,但大多数人更喜欢完整版本,因为它考虑了鼠标位置,因此提供了更好的体验...
不管怎样,这两种效果我都做了,你喜欢哪个就选哪个吧:)。
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)