“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”
- Frederick Philips Brooks
Mythical Man-Month 저자
화면에서 보이는 것처럼 마우스에 효과를 줄 수 있습니다.
이번에는 마우스 따라다니기 효과에 대해서 알아보도록 하겠습니다.
body의 main부분과 style부분 그리고 script부분을 나눠서 설명하겠습니다.
body의 main
<main id="main">
<div class="mouse__wrap">
<div class="mouse__cursor"></div>
<div class="mouse__text">
<p><span class="s1">Life</span> isn't about <span class="s2">finding</span> yourself. Life is about <span class="s3">creating</span> yourself.</p>
<p><span class="s4">삶</span>은 자신을 <span class="s5">찾아가는 것</span>이 아니라 <span class="s6">만들어 가는 것</span>이다.</p>
</div>
</div>
<div class="mouse__info">
<ul>
<li>clientX : <span class="clientX">0</span>px</li>
<li>clientY : <span class="clientY">0</span>px</li>
<li>offsetX : <span class="offsetX">0</span>px</li>
<li>offsetY : <span class="offsetY">0</span>px</li>
<li>pageX : <span class="pageX">0</span>px</li>
<li>pageY : <span class="pageY">0</span>px</li>
<li>screenX : <span class="screenX">0</span>px</li>
<li>screenY : <span class="screenY">0</span>px</li>
</ul>
</div>
</main>
<!-- main -->
body부분은 보이는 것처럼 간단합니다.
이번에는 class를 style과 함수를 적용하기 위해서 지정했습니다.
style
<style>
.mouse__wrap {
cursor: none;
}
.mouse__cursor {
position: absolute;
left: 0;
top: 0;
width: 50px;
height: 50px;
border-radius: 50%;
border: 3px solid #fff;
background-color: rgba(100, 19, 240, 0.1);
user-select: none;
pointer-events : none;
transition:
background-color 0.3s,
border-color 0.3s,
transform 0.6s,
border-radius 0.3s,
border 0.3s
;
}
.mouse__cursor.s1 {
background-color: rgba(255, 255, 255, 0.1);
border-color: rgb(240, 240, 68);
}
.mouse__cursor.s2 {
background-color: rgba(237, 224, 224, 0.877);
border-color: rgb(240, 163, 68);
transform: scale(2) rotateY(720deg);
}
.mouse__cursor.s3 {
background-color: rgba(204, 63, 63, 0.434);
border-color: rgb(197, 240, 68);
transform: scale(1.5) rotateX(545deg);
}
.mouse__cursor.s4 {
background-color: rgba(63, 204, 138, 0.434);
border-color: rgb(206, 68, 240);
transform: scale(10);
border-radius: 10px;
}
.mouse__cursor.s5 {
background-color: rgba(204, 204, 63, 0.434);
border-color: rgb(68, 120, 240);
transform: scale(5) skew(140deg) rotate(200deg);
}
.mouse__cursor.s6 {
background-color: rgba(63, 72, 204, 0.434);
border-color: rgb(102, 240, 68);
transform: scale(0.1);
}
.mouse__text {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
.mouse__text p {
font-size: 2vw;
line-height: 2;
}
.mouse__text p:last-child {
font-size: 3vw;
}
.mouse__text p span {
color: gold;
}
.mouse__info {
position: absolute;
left: 0;
bottom: 0;
padding: 20px;
font-size: 16px;
line-height: 1.6;
}
</style>
마우스 커서의 모양을 새로 만들기 위해서 cursor : none 을 설정한 후에
동그라미에 속은 다른 색으로 만들어 주기 위해서 테두리인 border-color와 속 색인 background-color를 다르게 설정했습니다.
user-select : none 은 텍스트 영역이 클릭 및 드래그로 선택되지 않게 하고,
pointer-events : none 은 HTML 요소에 정의된 클릭, 상태(hover,active등), 커서 옵션들이 비활성화합니다.
이 두 가지의 속성 값들로 인해 마우스를 글자 위에 올려두면 원형을 유지하며 클릭의 동작은 하지 않도록 했습니다.
transition 효과를 넣음으로써 마우스가 어느 곳에 도달하게 되면 변하는데, 이 때에 시간이 설정한 정도로 걸리도록 했습니다.
어느 곳에 해당되는 .mouse__cursor.s1~6는 각자 다른 색의 테두리와 색으로 정했습니다.
여기에 더한 transform 효과들에 대해서 알아보자면,
- transform:scale() - X 또는 Y축으로 확대/ 축소
scale은 해당 요소를 지정한 크기만큼 확대 또는 축소 시킬 수 있습니다. - transform:rotate() - 지정 요소 회전
rotate는 요소를 지정한 각도만큼 회전시킵니다.
회전 각도가 플러스 값일 경우 시계 방향, 마이너스 값일 경우 반시계 방향으로 회전합니다. - transform:translate() - 지정 요소 X 또는 Y축으로 이동
translate는 요소를 지정한 위치로 X 또는 Y축만큼 이동 시킵니다. - transform:skew() - 지정 요소 X 또는 Y축으로 기울이기
skew는 요소를 지정한 만큼 X 또는 Y축으로 기울입니다. - transform-origin 속성
위의 transform 속성인 scale(), rotate(), translate(), skew()들을 한번씩 연습해 보았다면, 지정 요소의 중심을 기준으로 동작한다는 것을 알 수 있을 것 입니다.
하지만 transform-origin 을 사용하면 지정 요소의 기준점을 변경할 수 있습니다.
.mouse__text 와 .mouse__info 로 글자를 정렬시키고, 꾸몄습니다.
script
<script>
window.addEventListener("mousemove", function(event){
document.querySelector(".clientX").innerHTML = event.clientX;
document.querySelector(".clientY").innerHTML = event.clientY;
document.querySelector(".offsetX").innerHTML = event.offsetX;
document.querySelector(".offsetY").innerHTML = event.offsetY;
document.querySelector(".pageX").innerHTML = event.pageX;
document.querySelector(".pageY").innerHTML = event.pageY;
document.querySelector(".screenX").innerHTML = event.screenX;
document.querySelector(".screenY").innerHTML = event.screenY;
}); //event는 마우스의 정보
//선택자
const cursor = document.querySelector(".mouse__cursor");
window.addEventListener("mousemove", function(e){
cursor.style.left = e.clientX -25 + "px";
cursor.style.top = e.clientY -25 + "px";
});
// for(let i=0; i<=7; i++){
// documnet.querySelectorAll(".mouse__info ul li span").forEach(function(el,index){
// el.innerHTML = index+1 + "00";
// });
// }
// document.querySelector(".s1").addEventListener("mouseover", function(){
// cursor.classList.add("s1");
// });
// document.querySelector(".s1").addEventListener("mouseout", function(){
// cursor.classList.remove("s1");
// });
// document.querySelector(".s2").addEventListener("mouseover", function(){
// cursor.classList.add("s2");
// });
// document.querySelector(".s2").addEventListener("mouseout", function(){
// cursor.classList.remove("s2");
// });
// document.querySelector(".s3").addEventListener("mouseover", function(){
// cursor.classList.add("s3");
// });
// document.querySelector(".s3").addEventListener("mouseout", function(){
// cursor.classList.remove("s3");
// });
// document.querySelector(".s4").addEventListener("mouseover", function(){
// cursor.classList.add("s4");
// });
// document.querySelector(".s4").addEventListener("mouseout", function(){
// cursor.classList.remove("s4");
// });
// document.querySelector(".s5").addEventListener("mouseover", function(){
// cursor.classList.add("s5");
// });
// document.querySelector(".s5").addEventListener("mouseout", function(){
// cursor.classList.remove("s5");
// });
// document.querySelector(".s6").addEventListener("mouseover", function(){
// cursor.classList.add("s6");
// });
// document.querySelector(".s6").addEventListener("mouseout", function(){
// cursor.classList.remove("s6");
// });
// for(let i=1; i<=6; i++){
// document.querySelector(".s"+i).addEventListener("mouseover", function(){
// cursor.classList.add("s"+i);
// });
// document.querySelector(".s"+i).addEventListener("mouseout", function(){
// cursor.classList.remove("s"+i);
// });
// }
document.querySelectorAll(".mouse__text span").forEach(function(el,index){
el.addEventListener("mouseover", function(){
cursor.classList.add("s"+(index+1));
});
el.addEventListener("mouseout", function(){
cursor.classList.remove("s"+(index+1));
});
});
//getAttribute(); //속성 값을 가져옴
document.querySelectorAll(".mouse__text span").forEach(function(span){
let attr = span.getAttribute("class");
//attr = s1 s2 s3 s4 s5 s6
span.addEventListener("mouseover", function(){
cursor.classList.add(attr);
});
span.addEventListener("mouseout", function(){
cursor.classList.remove(attr);
});
});
//setAttribute(); //값을 가져옴
</script>
window 객체는 브라우저라는 host 환경에서 동작하는 최상위 객체로, 브라우저 환경에서 동작하는 여러 API들의 가교 역할을 합니다.
document, history, location, setTimout, cookieStore 등 다른 브라우저 api에 접근을 제공합니다.
뿐만 아니라 브라우저 탭에 대한 접근 권한이 있기 때문에 window.open, window.close, window.location 등을 통해 브라우저 탭 레벨의 여러 제어가 가능하다.
console, alret, confirm 등의 fucntion이 window객체에 정의되어 있습니다.
document 객체는 window에 로드되는 HTML 문서 그 자체를 나타내며, 해당 문서 내부의 HTML Element, Css 등을 제어할 수 있는 여러 메서드를 제공합니다. 보편적으로 window 객체의 프로퍼티로 제공됩니다.
일반적으로 querySelector 등의 메서드로 css selector 기반의 element 쿼리를 많이 하게 됩니다.
addEventListener()는 document의 특정요소(Id,class,tag 등등..) event(ex - click하면 함수를 실행하라, 마우스를 올리면 함수를 실행하라 등등.. )를 등록할 때 사용합니다.
하나의 이벤트에서 여러 개의 이벤트 핸들러 함수를 등록하거나, 동일 객체의 동일 이벤트에 서로 다른 모듈이 이벤트 핸들러를 여러개 등록하는 데 문제가 없으려면, 다른 이벤트 핸들러 등록 방법을 사용해야 합니다.
이벤트 대상이 되는 대다수 객체에는 이런 용도로 addEventListener()라는 이벤트 리스너 등록 메서드가 있습니다.
mousemove 는 마우스가 움직일 때마다 발생합니다. 마우스 커서의 현재 위치를 계속 기록하는 것에 사용할 수 있습니다.
mouseover 는 마우스를 HTML요소 위에 올리면 발생합니다.
mouseout 는 마우스가 HTML요소 밖으로 벗어날 때 발생합니다.
여기에 함수를 적용해서 커서를 다양한 모습으로 변하게 실행시킨 것입니다.
같은 함수를 반복해서 쓰는 것을 피하기 위해서 forEach 메서드로 함수식을 실행시킨 과정을 적은 것입니다.
함수에서 요소, 인덱스,배열의 순으로 값을 찾을 수 있기 때문에, 이를 이용해서 찾고 싶은 값의 자릿수 즉, 인덱스를 문자와 함께 쓴 모습이 ( "s" + (index + 1) ) 이렇게 나온 것입니다.
classList 사용은 공백으로 구분된 문자열인 element.className 을 통해 엘리먼트의 클래스 목록에 접근하는 방식을 대체하는 간편한 방법입니다. 이를 이용해서 mouseover 일 때와 mouseout 일 때의 모습을 각 각 다르게 출력하도록 했습니다.