개발 기술/css 애니메이션 (with js)

버튼 커서 애니메이션 (with. js)

by GicoMomg (Lux) 2021. 10. 20.

이번 시간에는 버튼 hover시 커서를 따라 그라데이션이 나타나도록 해보았다.

1. 미리보기

See the Pen button-gradient by KumJungMin (@kumjungmin) on CodePen.



2. 코드 보기

1) html

<button class="btn-gradient">
  <span class="title">Button</span>
</button>
  • html 구조는 간단한다!
  • 버튼(btn-gradient)을 추가하고, span(title)을 이용해 글자를 넣는다.



2) scss (1)

(1) 글자에 스타일 설정하기

  • (a) 구글 폰트에서 원하는 폰트를 import하고 title에 적용한다.
  • (b) pointer-events: none을 설정하여, 글자에 pointer 이벤트를 비활성화시킨다.
@import url('https://fonts.googleapis.com/css2?family=Palette+Mosaic&display=swap');

.title {
  position: relative;    
  font-family: 'Palette Mosaic', cursive; /*(a)*/
  pointer-events: none;                   /*(b)*/
}

(2) 버튼 스타일 지정하기

  • 버튼에 기본적인 디자인을 설정한다. (너비, 높이, 글자색, 배경색 등)

.btn-gradient {
  width: 8rem;    
  height: 3rem;
  font-size: 1.2rem;
  color: #fff;
  font-weight: 500;
  overflow: hidden;
  background: #B980F0;
  cursor: pointer;
  border: 0;
  border-radius: 0.3rem;
}

(3) 버튼에 그라데이션 원 추가하기

버튼에 hover시, 그라데이션 원이 나타나게 할 것이다.
원의 경우 before(가상 클래스)를 이용하여 만든다.

.btn-gradient {
  position: relative;   /*(a)*/
  &:before {
    position: absolute; /*(a)*/
    width: 10rem;      
    height: 10rem;
    content: '';
    transition: 0.2s;   /*(b)*/
    transform: translate(-50%, -50%); 
    background: radial-gradient(circle closest-side, #FE9898, transparent); /*(c)*/
  }
}
  • (a) before가 버튼 기준 절대 위치하도록, 버튼에는 relative, before에는 absolute를 지정한다.
  • (b) transition: 0.2s를 하여 애니메이션 속도를 0.2초로 설정한다.
  • (c) 배경색의 경우 radial-gradientcircle을 지정해서 원형으로 만든다.

(4) hover 이벤트시 그라데이션 원이 나타나게 하기

.btn-gradient {  
  &:before {
    transform: translate(-50%, -50%) scale(0); /*기본*/
  }
}
.btn-gradient:hover::before {
  transform: translate(-50%, -50%) scale(1);  /*hover시*/
}
  • scale은 해당 요소의 크기를 조절한다.
  • 기본으로 scale(0)을 하여 크기를 0으로 만든다.
  • hoverscale(1)을 해서 요소가 나타나게 한다.



3) js

(1) mousemove 이벤트를 사용하자

const btn = document.querySelector('.btn-gradient'); //(a)
btn.addEventListener("mousemove", e => {            //(b)
  ...
})
  • (a) document.querySelector를 사용하여 버튼 요소를 가져온다.
  • (b) 버튼에 mousemove이벤트시 실행한 동작을 정의한다.

(2) 버튼 기준, 커서의 위치를 알려면...

버튼 기준, 커서의 위치를 알려면 아래 두 속성에 대해 알아야 한다!

  • getBoundingClientRect : body 기준 해당 요소의 좌표값을 가져온다.
  • clientX, clientY : mousemove 이벤트시 이 값을 불러오면, body 기준 커서의 x, y값을 가져온다.

(3) 버튼 기준 커서값 구하기

btn.addEventListener("mousemove", e => {  
  const rect = e.target.getBoundingClientRect();    //(c)
  const x = e.clientX - rect.left;         //(d)
  const y = e.clientY - rect.top;          //(d)
})
  • (c) getBoundingClientRect로 해당 요소의 좌표값을 가져온다.
  • (d) clientX, clientY에서 getBoundingClientRect를 빼서, 버튼 내부에서 마우스 위치를 얻는다.

(4) 커서값을 css용 변수로 만들자!

btn.addEventListener("mousemove", e => {  
  ...
  btn.style.setProperty('--x', x + 'px');  //(e)
  btn.style.setProperty('--y', y + 'px');  //(e)
})
  • (e) setProperty(—변수명, 값)을 사용해 css에서 사용할 변수를 만들 수 있다!
  • (e) x, y에 버튼 기준, 마우스의 위치값을 각각 저장한다. (다음은 scss(2)에서 진행)



4) scss (2)

.btn-gradient {
  ...
  &:before {
    top: var(--y);   /*(a)*/
    left: var(--x);  /*(a)*/
  } 
}
  • (a) js에서 만들었던 변수를 css에서 var(—변수명)형태로 사용할 수 있다.
  • (a) 그라데이션 원의 top, left에 각각 —y, —x를 넣어준다.
    (그러면 마우스를 따라 이동하게 됨)





출처

아래 링크로 가서 더 알아보자~!

반응형

댓글