현재 인프런에서 강의하고 계신 판다코딩님의 수업내용을 바탕으로 작성한 글입니다.
Handling Mouse는 mouse 포인터에 효과를 부여하거나, 그 값에 따라 object를 제어하는 것입니다.
이를 응용하여 3D를 활용하여 깊이감을 제어할 수 있으며 PC에서는 Mouse를, 모바일에서는 자이로센서에 응용할 수 있습니다.
이러한 제어 방법을 익히기 위해서는 JavaScript의 addEventListener함수에 대하여 알고 있어야 합니다.
addEventListener 는 웹페이지에 표시되는 특정한 요소에 event가 발생하였을 때 JavaScript 함수를 실행할 수 있도록 해줍니다. 여기서 event는 특정한 사건을 말하며, 마우스의 클릭, 마우스의 움직임 이외에 다양한 이벤트를 자바스크립트에서 지원해주고 있습니다.
Lenearing Objective
Coordinate system for screen
자바스크립트는 화면상에 좌표를 client, offset, page, screen으로 나누어 관리합니다.
client 메서드는 브라우저가 기준인 좌표입니다. 현재 보이는 브라우저 화면 상에서 어느 지점에 위치하는 지를 의미하기 때문에 스크롤 해도 값은 변하지 않습니다.
offset 메서드는 이벤트가 걸려 있는 DOM객체를 기준으로 좌표를 출력합니다. 이와 비슷한 메서드로 layer가 있습니다. 이 메서드는 현재 파이어폭스에서만 사용합니다.
page 메서드는 문서가 기준입니다. client와 비슷하지만 이 메서드는 문서 전체 크기가 기준이라 스크롤 시 값이 바뀝니다. (스크롤을 포함해서 측정합니다)
screen 메서드는 화면 출력 크기(자신의 모니터)가 기준인 절대 좌표입니다. 브라우저를 움직여도 값은 같습니다.
정리하자면
client 클라이언트(현재 보이는 브라우저 화면 기준) 영역 기준
offset 이벤트 대상을 기준
page 전체 문서를 기준
screen 모니터 화면을 기준
▶Example Code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="height: 500vh; ">
<div style=" position:fixed;">
<div class="client">
<h1>Client</h1>
<h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3>
</div>
<div class="offset">
<h1>Offset</h1>
<h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3>
</div>
<div class="page">
<h1>Page</h1>
<h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3>
</div>
<div class="screen">
<h1>Screen</h1>
<h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3>
</div>
</div>
<script>
window.onload = function(){
window.addEventListener("mousemove", (e) => {
//console.log(e);
document.querySelector('.client .xPoint').innerHTML = e.clientX;
document.querySelector('.client .yPoint').innerHTML = e.clientY;
document.querySelector('.offset .xPoint').innerHTML = e.offsetX;
document.querySelector('.offset .yPoint').innerHTML = e.offsetY;
document.querySelector('.page .xPoint').innerHTML = e.pageX;
document.querySelector('.page .yPoint').innerHTML = e.pageY;
document.querySelector('.screen .xPoint').innerHTML = e.screenX;
document.querySelector('.screen .yPoint').innerHTML = e.screenY;
}, false);
}
</script>
</body>
</html>
Mouse Move
addEventListener에 mousemove값으로 마우스의 좌표를 계산할 수 있습니다. 이 때 인자로 넘겨주는 'e'의 값을 콘솔로 확인해보면 clientX와 clientY에 우리가 사용할 브라우저 화면 상에서 마우스 좌표 X값과 Y값이 출력되는 것을 확인할 수 있습니다.
//JavaScript
window.addEventListener("mousemove", mouseFunc, false);
function mouseFunc(e){
console.log(e);
}
//JavaScript ES6+
window.addEventListener("mousemove", (e) => {
console.log(e);
}, false);
Object Handling
css 속성 중 transform을 이용하면 알아낸 좌표값을 바탕으로 object를 제어할 수 있습니다.
transform 속성은 요소에 회전, 기울기, 크기 이동, 위치 이동 등의 효과를 적용할 수 있는 데 저희가 사용할 값은 translate로 translate는 요소의 위치를 이동하여 좌표 공간을 변경할 수 있습니다.
position
- static : default
- relative : top / right / bottom / left 속성의 영향을 받음
- absolute : static 속성을 가지고 있지 않은 부모를 기준
- fixed : 특정 위치에 고정
transform
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
height: 100vh;
background-color: lightslategray;
margin: 0px;
/*
cursor: none;
*/
}
.object{
position: absolute;
width: 100px;
height: 100px;
background-color: red;
/*
top: -50px;
left: -50px;
*/
}
</style>
</head>
<body>
<div class="object"></div>
<script>
window.onload = function(){
let object = document.querySelector('.object');
window.addEventListener("mousemove", (e) => {
object.style.transform = "translate(" + e.clientX+"px," + e.clientY + "px)";
}, false);
}
</script>
</body>
</html>
이 코드에서는 커서가 박스의 좌상단에 위치하게 됩니다.
만약 커서를 박스의 중간에 놓고 싶다면 object의 css의 주석을 지우면 됩니다.
만약 커서를 없애고 싶다면 body의 주석을 지우면 됩니다.
requestAnimationFrame
위의 코드를 실행하면 박스의 움직임이 딱딱한것을 알수 있습니다. 이는 요소를(마우스를) 움직일 때 마우스의 좌표값이 변경되는 시간과 이미지가 화면에 다시 그려지는 시간(렌더링 시간)에 대한 차이때문입니다.
requsetAnimationFrame함수를 재귀적으로 호출하여 이를 해결할 수 있습니다.
requsetAnimationFrame은 브라우저에게 수행하기를 원하는 애니메이션을 알리고 다음 리페인트가 진행되기 전에 해당 애니메이션을 업데이트하는 함수를 호출하게 합니다. 따라서 디스플레이의 주사율에 근접한 속도로 object를 렌더링할 수 있게 해줍니다. 또 단순히 요소의 좌표값에 마우스의 좌표값을 부여하는 것이 아니라, speed와 같은 값을 곱하여 부여해준다면 요소와 마우스의 거리가 멀 때는 빠르게 움직이고, 요소와 마우스의 거리가 가까울 때는 천천히 움직이는 등의 역동적인 효과를 부여할 수 있습니다.
참고: https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame
function loop(){
//console.log();
window.requestAnimationFrame(loop);
}
이 코드를 추가하면 똑같은 속도로 전보다는 더 부드럽게 박스가 이동하는것을 알 수 있습니다.
<script>
let x = 0;
let y = 0;
let object = document.querySelector('.object');
let mx = 0;
let my = 0;
let speed = 0.1;
window.onload = function(){
window.addEventListener("mousemove", (e) => {
x = e.clientX;
y = e.clientY;
}, false);
loop();
}
function loop(){
//console.log();
mx += (x - mx) * speed;
my += (y - my) * speed;
object.style.transform = "translate(" + mx +"px," + my + "px)";
window.requestAnimationFrame(loop);
}
</script>
이 코드를 통해 요소와 마우스의 거리가 멀 때는 빠르게 움직이고, 요소와 마우스의 거리가 가까울 때는 천천히 움직이는 등의 역동적인 효과를 알수 있습니다.
easing
지금까지는 javascript를 이용하여 요소를 부드럽게 움직여보았습니다. 이번에는 javascript가 아니라 css로 요소를 부드럽게 움직여 보겠습니다.
css는 transition 속성을 통해서 요소의 css 변화가 일어날 때 생기는 애니메이션에 대한 속성을 제어할 수 있습니다. 이 transition을 javascript로 동적으로 만든 것이 여러분들이 잘 아는 :hover 나 :active와 같은 속성들입니다. transition 속성은 값으로 (요소의 변화 / 변화의 시간 / 변화 속성) 을 부여할 수 있는데, 변화 속성에 대해서 조금 더 깊게 이야기해보겠습니다.
transition-timing-function 속성
transition-timing-function 속성은 전환(transition) 효과의 시간당 속도를 설정할 수 있습니다.
이 속도를 모델링하기 위하여 css는 cubic bezier curve를 사용합니다.
https://cubic-bezier.com 사이트에서 bezier curve의 control point를 직접 움직여 보시면서 커브의 변화율을 느껴보세요. curve에서 그려지는 y축의 값이 속도입니다. 저희가 이 때까지 만든 코드에서 mousemove대신 click으로 event의 조건을 달리한 이후 요소가 움직이는 속도를 제어해봅시다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
height: 100vh;
background-color: lightslategray;
margin: 0px;
cursor: none;
}
.object{
position: absolute;
width: 100px;
height: 100px;
background-color: red;
top: -50px;
left: -50px;
transition: all 1s ease-in;
/*
transition: all 1s cubic-bezier(.17,.67,.83,.67);
*/
}
</style>
</head>
<body>
<div class="object"></div>
<script>
let x = 0;
let y = 0;
let object = document.querySelector('.object');
window.onload = function(){
window.addEventListener("click", (e) => {
x = e.clientX;
y = e.clientY;
object.style.transform = "translate(" + x +"px," + y + "px)";
}, false);
}
</script>
</body>
</html>
현재 인프런에서 강의하고 계신 판다코딩님의 수업내용을 바탕으로 작성한 글입니다.
Handling Mouse는 mouse 포인터에 효과를 부여하거나, 그 값에 따라 object를 제어하는 것입니다.
이를 응용하여 3D를 활용하여 깊이감을 제어할 수 있으며 PC에서는 Mouse를, 모바일에서는 자이로센서에 응용할 수 있습니다.
이러한 제어 방법을 익히기 위해서는 JavaScript의 addEventListener함수에 대하여 알고 있어야 합니다.
addEventListener 는 웹페이지에 표시되는 특정한 요소에 event가 발생하였을 때 JavaScript 함수를 실행할 수 있도록 해줍니다. 여기서 event는 특정한 사건을 말하며, 마우스의 클릭, 마우스의 움직임 이외에 다양한 이벤트를 자바스크립트에서 지원해주고 있습니다.
Lenearing Objective
Coordinate system for screen
자바스크립트는 화면상에 좌표를 client, offset, page, screen으로 나누어 관리합니다.
client 메서드는 브라우저가 기준인 좌표입니다. 현재 보이는 브라우저 화면 상에서 어느 지점에 위치하는 지를 의미하기 때문에 스크롤 해도 값은 변하지 않습니다.
offset 메서드는 이벤트가 걸려 있는 DOM객체를 기준으로 좌표를 출력합니다. 이와 비슷한 메서드로 layer가 있습니다. 이 메서드는 현재 파이어폭스에서만 사용합니다.
page 메서드는 문서가 기준입니다. client와 비슷하지만 이 메서드는 문서 전체 크기가 기준이라 스크롤 시 값이 바뀝니다. (스크롤을 포함해서 측정합니다)
screen 메서드는 화면 출력 크기(자신의 모니터)가 기준인 절대 좌표입니다. 브라우저를 움직여도 값은 같습니다.
정리하자면
client 클라이언트(현재 보이는 브라우저 화면 기준) 영역 기준
offset 이벤트 대상을 기준
page 전체 문서를 기준
screen 모니터 화면을 기준
▶Example Code
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body style="height: 500vh; "> <div style=" position:fixed;"> <div class="client"> <h1>Client</h1> <h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3> </div> <div class="offset"> <h1>Offset</h1> <h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3> </div> <div class="page"> <h1>Page</h1> <h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3> </div> <div class="screen"> <h1>Screen</h1> <h3>X : <span class="xPoint"></span> Y : <span class="yPoint"></span></h3> </div> </div> <script> window.onload = function(){ window.addEventListener("mousemove", (e) => { //console.log(e); document.querySelector('.client .xPoint').innerHTML = e.clientX; document.querySelector('.client .yPoint').innerHTML = e.clientY; document.querySelector('.offset .xPoint').innerHTML = e.offsetX; document.querySelector('.offset .yPoint').innerHTML = e.offsetY; document.querySelector('.page .xPoint').innerHTML = e.pageX; document.querySelector('.page .yPoint').innerHTML = e.pageY; document.querySelector('.screen .xPoint').innerHTML = e.screenX; document.querySelector('.screen .yPoint').innerHTML = e.screenY; }, false); } </script> </body> </html>
Mouse Move
addEventListener에 mousemove값으로 마우스의 좌표를 계산할 수 있습니다. 이 때 인자로 넘겨주는 'e'의 값을 콘솔로 확인해보면 clientX와 clientY에 우리가 사용할 브라우저 화면 상에서 마우스 좌표 X값과 Y값이 출력되는 것을 확인할 수 있습니다.
//JavaScript window.addEventListener("mousemove", mouseFunc, false); function mouseFunc(e){ console.log(e); } //JavaScript ES6+ window.addEventListener("mousemove", (e) => { console.log(e); }, false);
Object Handling
css 속성 중 transform을 이용하면 알아낸 좌표값을 바탕으로 object를 제어할 수 있습니다.
transform 속성은 요소에 회전, 기울기, 크기 이동, 위치 이동 등의 효과를 적용할 수 있는 데 저희가 사용할 값은 translate로 translate는 요소의 위치를 이동하여 좌표 공간을 변경할 수 있습니다.
position
- static : default
- relative : top / right / bottom / left 속성의 영향을 받음
- absolute : static 속성을 가지고 있지 않은 부모를 기준
- fixed : 특정 위치에 고정
transform
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body{ height: 100vh; background-color: lightslategray; margin: 0px; /* cursor: none; */ } .object{ position: absolute; width: 100px; height: 100px; background-color: red; /* top: -50px; left: -50px; */ } </style> </head> <body> <div class="object"></div> <script> window.onload = function(){ let object = document.querySelector('.object'); window.addEventListener("mousemove", (e) => { object.style.transform = "translate(" + e.clientX+"px," + e.clientY + "px)"; }, false); } </script> </body> </html>
이 코드에서는 커서가 박스의 좌상단에 위치하게 됩니다.
만약 커서를 박스의 중간에 놓고 싶다면 object의 css의 주석을 지우면 됩니다.
만약 커서를 없애고 싶다면 body의 주석을 지우면 됩니다.
requestAnimationFrame
위의 코드를 실행하면 박스의 움직임이 딱딱한것을 알수 있습니다. 이는 요소를(마우스를) 움직일 때 마우스의 좌표값이 변경되는 시간과 이미지가 화면에 다시 그려지는 시간(렌더링 시간)에 대한 차이때문입니다.
requsetAnimationFrame함수를 재귀적으로 호출하여 이를 해결할 수 있습니다.
requsetAnimationFrame은 브라우저에게 수행하기를 원하는 애니메이션을 알리고 다음 리페인트가 진행되기 전에 해당 애니메이션을 업데이트하는 함수를 호출하게 합니다. 따라서 디스플레이의 주사율에 근접한 속도로 object를 렌더링할 수 있게 해줍니다. 또 단순히 요소의 좌표값에 마우스의 좌표값을 부여하는 것이 아니라, speed와 같은 값을 곱하여 부여해준다면 요소와 마우스의 거리가 멀 때는 빠르게 움직이고, 요소와 마우스의 거리가 가까울 때는 천천히 움직이는 등의 역동적인 효과를 부여할 수 있습니다.
참고: https://developer.mozilla.org/ko/docs/Web/API/Window/requestAnimationFrame
function loop(){ //console.log(); window.requestAnimationFrame(loop); }
이 코드를 추가하면 똑같은 속도로 전보다는 더 부드럽게 박스가 이동하는것을 알 수 있습니다.
<script> let x = 0; let y = 0; let object = document.querySelector('.object'); let mx = 0; let my = 0; let speed = 0.1; window.onload = function(){ window.addEventListener("mousemove", (e) => { x = e.clientX; y = e.clientY; }, false); loop(); } function loop(){ //console.log(); mx += (x - mx) * speed; my += (y - my) * speed; object.style.transform = "translate(" + mx +"px," + my + "px)"; window.requestAnimationFrame(loop); } </script>
이 코드를 통해 요소와 마우스의 거리가 멀 때는 빠르게 움직이고, 요소와 마우스의 거리가 가까울 때는 천천히 움직이는 등의 역동적인 효과를 알수 있습니다.
easing
지금까지는 javascript를 이용하여 요소를 부드럽게 움직여보았습니다. 이번에는 javascript가 아니라 css로 요소를 부드럽게 움직여 보겠습니다.
css는 transition 속성을 통해서 요소의 css 변화가 일어날 때 생기는 애니메이션에 대한 속성을 제어할 수 있습니다. 이 transition을 javascript로 동적으로 만든 것이 여러분들이 잘 아는 :hover 나 :active와 같은 속성들입니다. transition 속성은 값으로 (요소의 변화 / 변화의 시간 / 변화 속성) 을 부여할 수 있는데, 변화 속성에 대해서 조금 더 깊게 이야기해보겠습니다.
transition-timing-function 속성
transition-timing-function 속성은 전환(transition) 효과의 시간당 속도를 설정할 수 있습니다.
이 속도를 모델링하기 위하여 css는 cubic bezier curve를 사용합니다.
https://cubic-bezier.com 사이트에서 bezier curve의 control point를 직접 움직여 보시면서 커브의 변화율을 느껴보세요. curve에서 그려지는 y축의 값이 속도입니다. 저희가 이 때까지 만든 코드에서 mousemove대신 click으로 event의 조건을 달리한 이후 요소가 움직이는 속도를 제어해봅시다.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body{ height: 100vh; background-color: lightslategray; margin: 0px; cursor: none; } .object{ position: absolute; width: 100px; height: 100px; background-color: red; top: -50px; left: -50px; transition: all 1s ease-in; /* transition: all 1s cubic-bezier(.17,.67,.83,.67); */ } </style> </head> <body> <div class="object"></div> <script> let x = 0; let y = 0; let object = document.querySelector('.object'); window.onload = function(){ window.addEventListener("click", (e) => { x = e.clientX; y = e.clientY; object.style.transform = "translate(" + x +"px," + y + "px)"; }, false); } </script> </body> </html>