MouseEvent.button
값 | 내용
:--|:--
0 | 마우스 왼쪽 버튼
1 | 마우스 휠
2 | 마우스 오른쪽 버튼
3 | X1 (일반적으로 브라우저 뒤로 가기 버튼)
4 | X2 (일반적으로 브라우저 앞으로 가기 버튼)
MouseEvent.type
값 | 내용
:--|:--
mousedown | 마우스 버튼을 누르는 순간
mouseup | 마우스 버튼을 눌렀다 떼는 순간
click | 왼쪽 버튼을 클릭한 순간
dblclick | 왼쪽 버튼을 빠르게 두 번 클릭한 순간
contextmenu | 오른쪽 버튼을 클릭한 순간
mousemove | 마우스를 움직이는 순간
mouseover | 마우스 포인터가 요소 위로 올라온 순간
mouseout | 마우스 포인터가 요소에서 벗어나는 순간
mouseenter | 마우스 포인터가 요소 위로 올라온 순간 (버블링이 일어나지 않음)
mouseleave | 마우스 포인터가 요소에서 벗어나는 순간 (버블링이 일어나지 않음)
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<title>JS with Codeit</title>
</head>
<body>
<div id="mouse">
<div id="btns">
<div id="btn0" class="btn"></div>
<div id="btn1" class="btn"></div>
<div id="btn2" class="btn"></div>
</div>
</div>
<script src="index.js"></script>
<script src="mouse-event.js"></script>
</body>
</html>
#mouse {
width: 240px;
height: 390px;
border: 1px solid #333333;
border-radius: 150px;
overflow: hidden;
}
#btns {
display: flex;
position: relative;
width: 100%;
height: 150px;
border-bottom: 1px solid #333333;
}
#btn0 {
width: calc(50% - 1px);
height: 100%;
border-right: 1px solid #333333;
}
#btn1 {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #FFFFFF;
width: 40px;
height: 90px;
border: 1px solid #333333;
border-radius: 20px;
}
#btn2 {
width: 50%;
height: 100%;
}
.btn {
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
font-weight: 900;
}
.clicked-0 #btn0 {
background-color: #EB2F2F;
}
.clicked-1 #btn1 {
background-color: #FFB62E;
}
.clicked-2 #btn2 {
background-color: #FFFF58;
}
.dblclick #btn0 {
background-color: #0CB30C;
}
let timer = 0;
function printEventType(e) {
const EVENT_DURATION = 800;
const eventTime = new Date();
if (timer === 0) {
timer = new Date();
}
if (eventTime - timer > EVENT_DURATION) {
console.log('--------------------------');
}
if (e.target.id !== 'mouse') {
e.preventDefault();
}
const btns = document.querySelector(`#btns`);
const btn = document.querySelector(`#btn${e.button}`);
btns.classList.add(`clicked-${e.button}`);
btn.textContent = e.button;
console.log(`${e.type} 이벤트가 발생했습니다.`);
if (e.type === 'dblclick') {
btns.className = 'dblclick';
}
function styleInit() {
btns.className = '';
btn.textContent = '';
}
setTimeout(styleInit, EVENT_DURATION);
timer = eventTime;
}
document.addEventListener('click', printEventType);
document.addEventListener('contextmenu', printEventType);
document.addEventListener('dblclick', printEventType);
document.addEventListener('mouseup', printEventType);
document.addEventListener('mousedown', printEventType);
마우스에서 어떤 event가 발생했는지 console에서 확인할 수 있는 코드
MouseEvent.type
mousemove: 마우스 포인터가 이동할 때
mouseover: 마우스 포인터가 요소 밖에서 안으로 이동할 때
mouseout: 마우스 포인터가 요소 안에서 밖으로 이동할 때
MouseEvent.target
이벤트가 발생한 요소
MouseEvent.relatedTarget
이벤트가 발생하기 직전(또는 직후)에 마우스가 위치해 있던 요소
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
<title>JS with Codeit</title>
</head>
<body>
<div id="box1" class="box">
mousemove
</div>
<div id="box2" class="box">
<b class="title">mouseover / mouseout</b>
<div id="cell-1" class="cell">cell-1</div>
<div id="cell-2" class="cell">cell-2</div>
<div id="cell-3" class="cell">cell-3</div>
<div id="cell-4" class="cell">cell-4</div>
</div>
<script src="index.js"></script>
</body>
</html>
* {
box-sizing: border-box;
}
body {
padding: 50px;
}
.box {
display: flex;
width: 250px;
height: 250px;
}
#box1 {
justify-content: center;
align-items: center;
margin-bottom: 40px;
font-size: 35px;
background-color: #acfffc;
}
#box2 {
flex-flow: row wrap;
position: relative;
padding: 35px;
background-color: #b6ffaa;
}
#box2 .title {
position: absolute;
top: 8px;
left: 0;
width: 100%;
font-size: 18px;
font-weight: 500;
text-align: center;
}
.cell {
width: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
font-weight: 900;
opacity: .1;
}
.on {
opacity: 1;
}
#cell-1,
#cell-4 {
color: #FFFFFF;
background-color: #000000;
}
#cell-2,
#cell-3 {
color: #000000;
background-color: #FFFFFF;
}
const box2 = document.querySelector('#box2');
function printEventData(e) {
console.log('event:', e.type);
console.log('target:', e.target);
console.log('relatedTarget:', e.relatedTarget);
console.log('------------------------------------');
if (e.target.classList.contains('cell')) {
e.target.classList.toggle('on');
}
}
box2.addEventListener('mouseover', printEventData);
box2.addEventListener('mouseout', printEventData);
이동했을 때 어떤 event가 실행되고 target과 relatedTarget이 어떤 요소인지 확인할 수 있는 방법
mouseenter
와 mouseleave
는 버블링이 일어나지 않습니다.
위 코드 결과에서 mouseover
타입으로 이벤트 핸들러가 등록된 div#box1
요소(왼쪽)에서 마우스를 움직여 보세요.
당연히 해당 요소 바깥에서 안쪽으로 마우스 커서가 이동할 때도 이벤트가 발생하지만, 버블링과 이벤트 위임의 원리로 자식요소인 b.title
부분으로 마우스 커서가 이동할 때도 이벤트가 발생합니다.
하지만 mouseenter
타입으로 이벤트 핸들러가 등록된 div#box2
요소(오른쪽)에서는 해당 요소 바깥에서 안쪽으로 마우스 커서가 이동할 때만 이벤트 핸들러가 동작하는 모습을 확인할 수 있습니다.
mouseenter
와 mouseleave
는 자식 요소의 영역을 계산하지 않습니다.
다시 mouseover
타입으로 이벤트 핸들러가 등록된 div#box1
요소(왼쪽)에서 마우스를 움직여 봅시다.
버블링에 의해 자식 요소로 마우스 커서가 이동할 때도 이벤트 핸들러가 동작하지만, 자식 요소에서 다시 div#box1
요소로 마우스 커서가 이동할 때도 이벤트 핸들러가 동작하죠? mouseover
는 자식 요소의 영역을 구분하기 때문입니다.
반면, mouseenter
는 자식 요소의 영역을 구분하지 않기 때문에 mouseenter
타입으로 이벤트 핸들러가 등록된 div#box2
요소(오른쪽)에서는 자식 요소에서 이벤트 핸들러가 동작하지 않는 것뿐만 아니라 자식 요소의 영역에 들어갔다 나올 때도 이벤트 핸들러가 동작하지 않는 모습을 볼 수 있습니다.
mouseover
/mouseout
과 비교하면서 mouseenter
/mouseleave
에 대해 살펴봤는데요.
간단하게 정리하면, 이벤트가 자식 요소에 영향끼치는지가 둘의 가장 큰 차이라고 할 수 있습니다.
그래서 이벤트 핸들러가 자식 요소에까지 영향을 끼치게 하고싶은 경우에는 mouseover
/mouseout
을, 자식 요소에는 영향을 끼치지 않고 해당 요소에만 이벤트 핸들러를 다루고자 한다면 mouseenter
/mouseleave
를 활용하면 좋을 것 같습니다.
프로퍼티 | 내용 |
---|---|
clientX, clientY | 마우스 포인터의 브라우저 표시 영역에서의 위치 |
pageX, pageY | 마우스 커서의 문서 영역에서의 위치 |
offsetX, offsetY | 마우스 포인터의 이벤트 발생한 요소에서의 위치 |
screenX, screenY | 마우스 포인터의 모니터 화면 영역에서의 위치 |
MouseEvent.clientX, clientY
화면에 표시되는 창 기준 마우스 포인터 위치
client
프로퍼티는 말 그대로 클라이언트 영역 내에서 마우스의 좌표 정보를 담고있는데요. 클라이언트 영역이란 이벤트가 발생한 순간에 브라우저가 콘텐츠를 표시할 수 있는 영역을 뜻합니다.
clientX : 브라우저가 표시하는 화면 내에서 마우스의 X좌표 위치를 담고 있습니다.
clientY : 브라우저가 표시하는 화면 내에서 마우스의 Y좌표 위치를 담고 있습니다.
client
값은 그 순간 보여지는 화면을 기준으로 계산하기 때문에 스크롤 위치와는 무관하게 항상 보여지는 화면의 좌측 상단의 모서리 위치를 (0, 0)으로 계산합니다.
MouseEvent.pageX, pageY
웹 문서 전체 기준 마우스 포인터 위치
offset
프로퍼티는 이벤트가 발생한 target이 기준이 됩니다.
offsetX : 이벤트가 발생한 target
내에서 마우스의 X좌표 위치를 담고 있습니다.
offsetY : 이벤트가 발생한 target
내에서 마우스의 Y좌표 위치를 담고 있습니다.
offset
값도 이벤트가 발생한 대상을 기준으로 계산하기 때문에 스크롤 위치와는 무관하게 항상 대상의 좌측 상단의 모서리 위치를 (0, 0)으로 계산합니다.
MouseEvent.offsetX, offsetY
이벤트가 발생한 요소 기준 마우스 포인터 위치
page 프로퍼티는 전체 문서를 기준으로 마우스 좌표 정보를 담고 있습니다. 그렇기 때문에 스크롤로 인해서 보이지 않게된 화면의 영역까지 포함해서 측정한다는 점이 앞의 두 프로퍼티와의 차이점 입니다.
pageX : 전체 문서 내에서 마우스의 X좌표 위치를 담고 있습니다.
pageY : 전체 문서 내에서 마우스의 Y좌표 위치를 담고 있습니다.
자칫 client
값과 혼동하기 쉬우니 잘 구분해 두시는 것이 좋습니다.