간단하게 만들어볼 결과물
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);
});
})();
최종 결과물 이미지
'자바스크립트' 카테고리의 다른 글
[js] 대상 객체에 마우스 호버 시 적용되는 애니메이션 만들어보기 (0) | 2023.02.23 |
---|---|
[js] 브라우저 화면의 중간값을 구하기(중심축을 이용한 애니메이션) (0) | 2023.02.22 |
[간단정리js] 자바스크립트 타입검사 시 == 연산자 대신 === 사용하기 (0) | 2023.02.21 |
[js] typeof 에서 null은 object 다. (0) | 2023.02.21 |
[js] 브라우저 렌더링 과정(2) - HTML 파싱 및 DOM 생성 (0) | 2023.02.13 |