JS를 이용한 애니메이션 (Ripple Effect)

Rock Kyun·2023년 10월 20일
0
post-thumbnail
post-custom-banner

오늘 했던 것

  • 알고리즘 문제 풀기
  • CSS, JS를 이용한 고급 효과 만들기 (Ripple Effect, 3d card)

오늘 학습한 것

  • getBoundingClientRect() : 직사각형 요소의 정보를 가져온다 (width, height, padding, ....)
  • CSS로 요소에 효과를 더하는 방법

오늘은 결과물

  • 대단한 버튼👏
    대다나다
  • 귀여운 와플곰 카드👍
    와플곰

과정 요약

  1. 먼저 HTMl에 button 요소를 만든다.
  2. CSS에서 button의 스타일링을 한다.
  3. button::after로 버튼 위에 띄워질 원을 만든다.
  4. JS에서 button을 선택하여 가져오고
    getBoundingClientRect()를 사용하여 x, y, width, height 값을 가져온다.
  5. 원의 중심이 사용자가 클릭한 위치가 되게 한다.
  6. 원의 반지름이 요소의 대각선 길이가 되도록해준다.
  7. 클릭 시 클릭한 곳을 중심으로 반지름이 점차 커지고 사라지도록 한다.

기술적인 부분

  1. getBoundingClientRect()
  • 이 브라우저 내장 함수를 사용하면 선택한 직사각형 요소의 정보를 객체로 반환해준다.
// 선택한 요소에서 브라우저 내장 함수 호출
console.log(rippleBtn).getBoundingClientRect();

// 결과
DOMRect {x: 299.5, y: 424, width: 200, height: 65, top: 424,}
  • 이것을 활용하여 아래와 같이 원의 반지름을 구해
    style.setProperty() 속성으로 원의 width, height에 적용해준다.
<.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. 클릭 시 클릭한 곳이 원의 중심이 되도록 설정

  • event가 일어난 요소를 클릭 시 마우스의 위치를 받아온다.
  • 위와 마찬가지로 setProperty() 속성으로
    원의 left, top 값을 할당해준다.
  • 클릭 한 곳을 찾는 방식은 이곳을 참고하는 것을 추천한다.
    마우스 클릭 지점과 원의 중심을 맞추는 방법
<.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')
  }) // 초를 지정하지 않아 즉시 실행

오늘 느낀 점

  • CSS를 다루는 API들도 많구나.
  • JS를 활용하여 애니메이션을 만들면 가능한 것이 더 많아 지는구나.
  • 알아두면 좋을 API들은 아직도 많이 있다.
post-custom-banner

0개의 댓글