Ripple Effect
使用 Vue 自定義指令實現類似 Material Design Button 的 Ripple Effect。
實作
1. 指令
1
2
3
4
5
6
7
8
9
10
|
const EVENT = 'mousedown';
const ripple = {
mounted(el) {
el.addEventListener(EVENT, createRipple);
},
unmounted(el) {
el.removeEventListener(EVENT, createRipple);
},
};
|
2. createRipple
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
function createRipple(event) {
const target = event.currentTarget;
const { top, left } = target.getBoundingClientRect();
const { clientWidth, clientHeight } = target;
const diameter = Math.sqrt(clientWidth ** 2 + clientHeight ** 2);
const radius = diameter / 2;
const localX = event.clientX - left;
const localY = event.clientY - top;
const ripple = document.createElement('span');
ripple.setAttribute('class', 'v-ripple');
ripple.setAttribute(
'style',
`
width: ${diameter}px;
height: ${diameter}px;
left: ${localX - radius}px;
top: ${localY - radius}px;
`,
);
ripple.addEventListener('animationend', removeRipple);
target.appendChild(ripple);
}
|
3. removeRipple
1
2
3
4
5
|
function removeRipple(event) {
const ripple = this;
ripple.remove();
ripple.addEventListener('animationend', removeRipple);
}
|
4. CSS animation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
.v-ripple {
position: absolute;
background-color: currentColor;
border-radius: 50%;
opacity: 0.2;
transform: scale(0);
animation: v-ripple-animation 0.6s linear;
}
@keyframes v-ripple-animation {
to {
opacity: 0;
transform: scale(4);
}
}
|
CodePen