前端切图学习-仿 Material Design 按键

Button Ripple Effect

Posted by R1NG on August 26, 2021 Viewed Times

仿 Material Design 按键 Button-Ripple-Effect

1. 概述

项目本体模拟了 Material Design 按键的按动效果.

本项目中涉及的知识点:

  1. 了解 JavaScript 事件对象的属性
  2. 使用 setTimeout() 在指定的时间后调用函数或计算表达式
  3. 使用 letter-spacing 属性控制字符间距
  4. 使用 translate(-50%, -50%) 将元素置于其定位点的中心位置
  5. 使用 scale() 对元素大小进行缩放
  6. 使用 @keyframes 规则创建补间动画

效果:

20210827115820


2. 结构和切图

网页的基本结构如下:

1
2
3
<body>
    <button class="ripple">Click Me</button>    
</body>


3. 编写 CSS 样式

首先定义排版模式, 并设定水平垂直居中:

1
2
3
4
5
6
7
8
9
10
11
body {
    background-color: #660099;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100vh;
    flex-direction: column;
    margin: 0;
    overflow: hidden;
}

其次设定按钮样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
button {
    background-color: #FFCC33;
    color: #fff;
    border: 1px #999999 solid;
    font-size: 14px;
    border-radius: 2px;
    text-transform: uppercase;
    letter-spacing: 2px;
    padding: 20px 30px;
    margin: 10p 0x;
    position: relative;
    overflow: hidden;
}
button:focus {
    outline: none;
}

再调整构成水波纹动效的圆形波纹遮罩的初始样式. 注意遮罩样式初始值为一个圆心在其定位框体 border-box 左上角的白色圆, 大小被缩放为 $0$, 结合 animation 语句可以实现从小到大的波纹扩散效果.

1
2
3
4
5
6
7
8
9
button .circle {
    position: absolute;
    background-color: #fff;
    width: 100px;
    height: 100px;
    border-radius: 50%;
    transform: translate(-50%, -50%) scale(0);
    animation: scale .5s ease-out;
}

最后定义水波纹扩散效果的结束关键帧, 并令浏览器自行计算其间的补间动画.

1
2
3
4
5
6
@keyframes scale {
    to {
        transform: translate(-50%, -50%) scale(3);
        opacity: 0;
    }
}

完整的 CSS 样式表如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
* {
   box-sizing: border-box;
}
body {
   background-color: #660099;
   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
   display: flex;
   align-items: center;
   justify-content: center;
   height: 100vh;
   flex-direction: column;
   margin: 0;
   overflow: hidden;
}
button {
   background-color: #FFCC33;
   color: #fff;
   border: 1px #999999 solid;
   font-size: 14px;
   border-radius: 2px;
   text-transform: uppercase;
   letter-spacing: 2px;
   padding: 20px 30px;
   margin: 10p 0x;
   position: relative;
   overflow: hidden;
}
button:focus {
   outline: none;
}

button .circle {
   position: absolute;
   background-color: #fff;
   width: 100px;
   height: 100px;
   border-radius: 50%;
   transform: translate(-50%, -50%) scale(0);
   animation: scale .5s ease-out;
}

@keyframes scale {
   to {
       transform: translate(-50%, -50%) scale(3);
       opacity: 0;
   }
}


4. JavaScript

最后编写 JavaScript 函数.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const buttons = document.querySelectorAll('.ripple');

buttons.forEach(button => {
    button.addEventListener('click', function (e) {
        const x = e.clientX;
        const y = e.clientY;

        const buttonTop = e.target.offsetTop;
        const buttonLeft = e.target.offsetLeft;

        const xInside = x - buttonLeft;
        const yInside = y - buttonTop;

        const circle = document.createElement('span');
        circle.classList.add('circle');
        circle.style.top = yInside + 'px';
        circle.style.left = xInside + 'px';

        // this ==> button
        this.appendChild(circle);

        setTimeout(() => circle.remove(), 500);
    })
})

在此处我们注意: 一般地, 事件对象 e 具备以下属性:

Property Function
timeStamp 返回事件生成的日期和时间
button 返回事件触发时所点击的鼠标按钮
pageX 返回光标相对网页的水平位置
pageY 返回光标相对网页的垂直位置
screenX 返回光标相对屏幕的水平位置
screenY 返回光标相对屏幕的垂直位置
target 返回该事件被传送到的对象
type 返回事件类型
clientX 返回光标相对当前可见区域的水平位置
clientY 返回光标相对当前可见区域的垂直位置

最后, 完整的网页演示可见 此处