본문 바로가기

자바스크립트

[js] 간단한 마우스 커서 애니메이션? 만들기

반응형

 간단하게 만들어볼 결과물

See the Pen Untitled by youngwan2 (@youngwan2) on CodePen.

 

 html  작업

div 박스에 mouse 클래스 속성값을 추가하고, 자식 요소로 span 태그를 두 개 생성한다.

    <div class="mouse">
        <span></span>
        <span></span>
    </div>

 

CSS 작업

만들어진 커서 이외의 기본 커서는 보이지 않도록 cursor : none 을 전역으로 설정한다. 부모 태그인 div 가 절대위치인 absolute 여야 left, top 등의 position 속성이 적용되므로 주의한다.


*{
    margin: 0;
    box-sizing: border-box;
    cursor: none;
}

body{
    background-color: black;
    color:white;
    height: 100vh;
    width: 100%;
  
}

/* 포지션이 절대적 위치여야 left, top 과 같은 포지션 속성을 적용할 수 있다. */
.mouse{
    background-color: transparent;
    width: 50px;
    height: 50px;
    border-radius: 50px;
    position: absolute;
}

/* 각 스판 요소를 크로스로 교차하기 위해 ntn-of-type 을 사용하여 교차축을 그린다. */

.mouse span:nth-of-type(1){
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%,-50%);
    width: 100%;
    height: 2%;
    border: 1px solid rgb(255, 9, 9);
    background-color: white;
}

.mouse span:nth-of-type(2){
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%,-50%);
    width: 2%;
    height: 100%;
    border: 1px solid rgb(252, 18, 18);
    background-color: rgb(244, 14, 14);
}

/* 부모 태그 자체에 애니메이션을 적용해야 그 안의 자식요소가 동시에 회전한다. */
.mouse {
    animation: loop 1000s linear infinite alternate;
}

/*  여기서는 rotate3d(가로기준, 세로기준, 중앙기준) 속성 
이 되므로 z 축(중앙기준)에 값을 부여하고, 4번째 인자로 오랫동안 회전할 수 있도록
각도를 부여한다. 사실 z 축은 앞뒤 거리를 말하는데, perspective가 적용되지 않는다면 중앙이 기준이 된다.
*/

@keyframes loop {
    from {transform: rotate3d(0,0,1,10000deg); }
}

 

 JS 작업

getBoundingClientRect() 메서드는 마침표 연산자(.) 로 접근한 객체의 크기, 높이 등의 정보를 담고 있는 메서드이다. 이 메서드를 사용하면 객체의 형태가 css로 변동되어도 영향을 받지 않는다.

 

clientx, y 속성만 적용한다면 객체의 정중앙으로  커서가 위치하지 않는다. 따라서 해당 객체의 넓이의 중간, 높이의 중간값을 각 x,y 값에서 빼줌으로써 중앙정렬한다.(이 부분이 이해가 안 될 때는 위의 코드팬의 js 부분을 건드려 보면 된다. 이 때 css에 전역으로 설정한 커서 none 속성을 제거하고 보는게 좋다.)

 

참고로 left 나 right 와 같은 위치에 직접 접근해서 사용하는 것은 생각보다 브라우저 렌더링 성능에 좋지 못하다고 한다. 복잡한 애플리케이션에 사용한다면 , cqu 가속을 사용하는 translate3d 속성을 활용해 보는 것도 좋아 보인다.

(() => {
    // div 태그를 선택해온다.
    const mouse = document.querySelector('.mouse');

     //mousemove 시 실행되는 함수
    const mouseMove=(x,y)=>{
        mouse.style.left = `${x-mouse.getBoundingClientRect().width/2}px`
        mouse.style.top = `${y-mouse.getBoundingClientRect().height/2}px`
    }

    //전역에 이벤트리스너를 적용하여 mousemove 시 사용자가
     // 바라보는 브라우저 창의 x축과 y축 정보를 지속적으로 추적하여
     // mouseMove 함수의 매개변수로 값을 전달한다.
    window.addEventListener('mousemove',(e)=>{
        mouseMove(e.clientX, e.clientY)
       
    })


})();

 

 JS 추가

state 변화에 따라 포커스 효과를 추가해 보았다. 변화된 내용은 아래 코드를 위 코드팬에 붙여넣어서 확인해보자

(() => {
  const mouse = document.querySelector(".mouse");

// state 상태를 저장한 객체
  const actionObj = {
    state: false,
  };

// mouse 객체를 클릭하는 순간 
// state 값이 true가 되면서 포커스효과 적용
  mouse.addEventListener("click", () => {
    actionObj.state = !actionObj.state;
    actionObj.state === true
      ? (mouse.style.background = "white")
      : (mouse.style.background = "transparent");
  });

// 마우스무브 시 효과를 적용하는 함수
  const mouseMove = (x, y) => {
    mouse.style.left = `${x - mouse.getBoundingClientRect().width / 2}px`;
    mouse.style.top = `${y - mouse.getBoundingClientRect().height / 2}px`;
  };

// 마우스무브 이벤트를 실행시키며, mouseMove() 함수에 clientX,Y 값 전달
  window.addEventListener("mousemove", (e) => {
    mouseMove(e.clientX, e.clientY);
  });
})();

 

 최종 결과물 이미지

반응형