button
요소를 만든다.button
의 스타일링을 한다.button::after
로 버튼 위에 띄워질 원을 만든다.button
을 선택하여 가져오고// 선택한 요소에서 브라우저 내장 함수 호출
console.log(rippleBtn).getBoundingClientRect();
// 결과
DOMRect {x: 299.5, y: 424, width: 200, height: 65, top: 424, …}
<.js>
const { x, y, width, height } = rippleBtn.getBoundingClientRect();
const radius = Math.sqrt(width * width, height * height);
rippleBtn.style.setProperty('--circleSize', radius * 2 + 'px')
<.css>
.ripple_button::after {
content: '';
position: absolute;
width: var(--circleSize); // JS에서 동적으로 할당 받는 값
height: var(--circleSize); // JS에서 동적으로 할당 받는 값
}
2. 클릭 시 클릭한 곳이 원의 중심이 되도록 설정
<.js>
const { clientX, clientY } = e;
const left = (clientX - x - radius) / width * 100 + '%'
const top = (clientY - y - radius) / height * 100 + '%'
rippleBtn.style.setProperty('--left', left)
rippleBtn.style.setProperty('--top', top)
<.css>
.ripple_button::after {
content: '';
position: absolute;
width: var(--circleSize);
height: var(--circleSize);
top: var(--top); // 클릭 위치가 원의 중심이 되도록하는 top 값
left: var(--left); // 클릭 위치가 원의 중심이 되도록하는 left 값
3. 클릭마다 애니메이션이 시작되도록 setTimeOut()으로 애니메이션 적용
<.css>
.ripple_button::after {
content: '';
position: absolute;
width: var(--circleSize);
height: var(--circleSize);
top: var(--top);
left: var(--left);
background-color: aliceblue;
border-radius: 50%;
opacity: 0;
animation: var(--ani); // JS에서 할당 (ripple-effect 500ms linear)
transform: scale(0);
}
@keyframes ripple-effect {
0% {
transform: scale(0);
opacity: 0.3;
}
100% {
transform: scale(1);
opacity: 0;
}
}
<.js>
rippleBtn.style.setProperty('--ani', '')
setTimeout(() => {
// --ani에 ripple-effect 500ms linear 설정
rippleBtn.style.setProperty('--ani', 'ripple-effect 500ms linear')
}) // 초를 지정하지 않아 즉시 실행