背景介绍
我感觉他挺好看的!
我第一次发现 Material Design 是几年前玩 Android(当时还不会开发 Android 应用程序)时候看到的些贴文。那时候我就超级喜欢它的按钮组件。它有着波纹效果,以简单,优雅的方式为用户提供反馈,Q 弹爆汁儿~
那时候的我也只会使用固定的 :hover
:focus
样式,效果固定而死板,那是我这种一班人用的,Google 那群二班的真的太强了!!!
你看看这圆润的外框,这活泼的颜色 ♂︎,这似乎汁水四溢的效果,是不是像极了你们欠我的那个赞 :)
我们可以完全做到一样的效果!
需求一览
- Ripple 效果
- 自动为所有元素加效果
- 监听新元素的插入
该咋办?
我打算用 JavaScript 监听点击事件,向按钮添加子元素(Ripple 动效元素),并向按钮添加 .ripple
类,并监听 DOM 树中的变化,如果有 .ripple
元素的加入,就为其绑定 Ripple 效果。
stateDiagram-v2
[*] --> 按钮事件
按钮事件 --> 未绑定
按钮事件 --> 已绑定
未绑定 --> 绑定按钮
绑定按钮 --> 动效
已绑定 --> 动效
动效 --> 添加 ripple
添加 ripple --> 添加子元素
添加子元素 --> [*]
HTML
<button>一个简简单单的按钮</button>
CSS
对于 Ripple 效果,我们会等下直接用 JavaScript 去动态设置,而样式的定义,就在如下的一些代码中解决:
button {
position: relative;
overflow: hidden;
}
使用 position: relative
允许我们等下构造的子元素针对按钮本体能够使用 position: absolute
。同时,overflow: hidden
可以帮助我们防止 Ripple 效果超出按钮的轮廓。然后再装饰一下:
/* 用上 Material 的默认字体 */
@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
button {
position: relative; /* 下文中会用到的相对绝对位置 */
overflow: hidden;
transition: background 400ms ease-in-out; /* 设置切换 */
color: #fff;
background-color: #662D91;
padding: 1rem 2rem;
font-family: 'Roboto', sans-serif;
outline: 0;
border: 0;
border-radius: 0.25rem;
box-shadow: 0 0 0.5rem rgba(0, 0, 0, 0.2);
cursor: pointer;
}
现在它是这样的:
Ripple
Ripple 效果实际上就是一个半径不断扩展的标准圆,而被沿着按钮外框裁切掉。因此我们先来绘制一个标准圆:
span.ripple {
position: absolute; /* 上文中我们提到过的相对绝对位置 */
border-radius: 50%;
transform: scale(0);
animation: ripple 600ms linear;
background-color: rgba(255, 255, 255, 0.2);
}
为了使波纹变圆,我们设置 border-radius
为 50%
。而为了确保动画开始时候没有效果,我们设置了默认缩放比例 0
。现在,我们将无法看到任何东西,因为我们还没有设置 top
、left
、width
以及 height
,也没有修改默认缩放比例 transform: scale(0)
。不用着急,马上我们就会用 JavaScript 设置这些属性!
现在我们还需要给 Ripple 效果添加动画切换,就让它缩放到 4 倍大小吧:
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
JavaScript
现在我们需要使用 JavaScript 来动态设置 Ripple 起始圆心的位置和 Ripple 大小。这个大小应基于按钮的大小,而位置应基于按钮和光标的位置。
事件绑定
先来绑定 click
事件:
[...document.querySelectorAll(".ripple")].forEach(btn => {
btn.addEventListener("click", showRipple);
});
然后我们可以使用 event.currentTarget
获取到当前元素:
const btn = event.currentTarget;
获取到了被点击的按钮,现在我们来构建一个子元素,并计算按钮的半径大小:
const circle = document.createElement("span");
const diameter = Math.max(button.clientWidth, button.clientHeight);
const radius = diameter / 2;
现在,我们可以定义我们需要为我们的涟漪其余属性:left
、top
、width
和 height
。
数据计算
我们知道,top 应该等于点击事件的 (x, y)
减去按钮的中心点的 (x, y)
:
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!