스크롤 이벤트 다루기
스크롤 이벤트는 브라우저에서 스크롤을 줄 때 오브젝트에 어떠한 변화를 주는 것을 말하는 데, 이때 재밌는 효과들을 넣어줄 수 있다.
보통의 경우 웹페이지 인터랙션을 깊게 파지 않는 경우에는 jQeury같은 라이브러리를 쓰는 데, Javascript의 자체 내장되어 있는 속성과 메소드 등의 라이브러리로만으로도 충분히 구현가능하기 때문에, 라이브러리에 너무 의존하지 않는 것이 좋다.
▼아래 페이지에서 스크롤 예시를 확인해볼 수 있다.
https://www.lundqvistdallyn.studio/
스크롤은 페이지 마지막 부근에 도달했을 때 작동하는 것이 아닌 움직일 때마다 작동하는데, 가장 기본적인 사용 방법은 이렇게 document 또는 window 객체에 addEventListener로 스크롤 이벤트를 호출할 수 있다.
document.addEventListener('scroll', function() {
});
코딩으로 구현해보자
아래 예제 그림에서 왼쪽 상단에 보이는 .output의 반투명 박스는 포지션이 고정이며 스크롤의 값을 보여준다. 스크롤이 아래로 내려갔을 때 일분이가 커지는 것을 알 수 있다.
전체 코드를 살펴보자.
먼저 상단바의 스크롤에 따라 변하는 픽셀값을 표현하기 위해 content의 height를 1000vh(Viewport Height)를 주었다. 100vh가 브라우저의 높이이기 때문에 1000vh라면 기본 브라우저 높이의 10배이다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Interactive Web</title>
<link rel="stylesheet" href="css/reset.css">
<style>
img {
max-width: 100%;
}
.content {
/* viewport height */
height: 1000vh;
padding: 20%;
background: yellowgreen;
}
.output {
position: fixed;
left: 0;
top: 0;
width: 100%;
font-size: 2rem;
font-weight: 200;
color: #fff;
background: rgba(0, 0, 0, 0.4);
}
.ilbuni {
width: 100px;
margin: 20px auto;
transition: 1s;
}
.ilbuni.zoom {
transform: scale(2);
}
</style>
</head>
<body>
<div class="output">output</div>
<div class="content">
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo culpa id ratione alias illum aliquam accusamus deleniti dolores dignissimos, temporibus iste perspiciatis voluptatem repudiandae debitis similique fugiat dolor, doloremque quos mollitia repellendus iure exercitationem molestiae ab! Veritatis harum voluptate enim ducimus amet vitae veniam dignissimos possimus facilis eaque minus similique, vel commodi sed? Sequi distinctio debitis numquam, necessitatibus officiis quam, sed rerum id culpa totam provident repellendus iste, laborum maiores, consequuntur fugiat voluptatibus? Ad, architecto. Ipsam minus quis, ea quas, ex impedit quia distinctio commodi expedita laudantium dolores cum? Quisquam, odit, laboriosam consequuntur expedita optio laudantium. Optio laboriosam, repellendus laborum.
</p>
<figure class="ilbuni">
<img src="images/ilbuni_0.png" alt="일분이">
</figure>
</div>
<script>
(function() {
const outputElem = document.querySelector('.output');
const ilbuniElem = document.querySelector('.ilbuni');
let num = 0;
function showValue() {
// outputElem.innerHTML = window.pageYOffset;
// outputElem.innerHTML = ilbuniElem.offsetTop;
let posY = ilbuniElem.getBoundingClientRect().top;
outputElem.innerHTML = posY;
if (posY < window.innerHeight * 0.2) {
ilbuniElem.classList.add('zoom');
} else {
ilbuniElem.classList.remove('zoom');
}
}
window.addEventListener('scroll', function() {
showValue();
});
showValue();
})();
</script>
</body>
</html>
코드 살펴보기
<script>안의 익명함수
(function() {
window.addEventListener('scroll', function() {
});
})();
여기서 (function() { window.addEventListner('scroll', function() { }, );은 전역변수를 최대한 제외하기 위하기 위해 스스로 실행시키는 익명함수이다.
이 익명함수 안에서 .output 클래스를 가져와 변수에 넣어준 뒤, window 객체의 pageYOffset 속성을 실행시켜준다.
pageYOffset 스크롤을 얼마나 했는지 나타내주는 속성이다.
스크롤에 따라 일분이의 크기를 조작하려면
먼저 일분이의 위치를 알 수 있어야 한다. 이때 이용하는 메소드는 getBoundingClientRect()인데, 이 메소드를 이용하여 브라우저에서 객체의 top, bottom, left, right 또는 X, Y축(IE에서는 지원안됨)을 알 수 있다. top과 Y축의 값은 같다.
이 중 우리는 스크롤 이벤트를 주었을 때 일분이로부터 세로축(Y의 값)을 가져오고 싶기 때문에, getBoundingClientRect().top을 찍어주면 400.77..을 값을 알 수 있다.
다음으로 일분이가 브라우저의 4분의 1 위치로 내려왔을 때, 2배로 커지도록 해보자.
미리 만들어둔 CSS
.ilbuni.zoom {
transform: scale(2);
}
이때 강사님이 말씀해주신 팁은 함수는 최대한 단순하게 만들어서 조합해서 쓰는 방식이 좋다.
실무에서도 Manage.js라는 파일안에 단순동작하는 함수를 미리 선언을 해주고 필요할 때마다 Manage.mng.alert()처럼 호출해서 쓰고 있다.
(function() {
const outputElem = document.querySelector('.output');
const ilbuniElem = document.querySelector('.ilbuni');
let num = 0;
function showValue() {
// outputElem.innerHTML = window.pageYOffset;
// outputElem.innerHTML = ilbuniElem.offsetTop;
let posY = ilbuniElem.getBoundingClientRect().top;
outputElem.innerHTML = posY;
if (posY < window.innerHeight * 0.2) {
ilbuniElem.classList.add('zoom');
} else {
ilbuniElem.classList.remove('zoom');
}
}
window.addEventListener('scroll', function() {
showValue();
});
showValue();
})();
변수 posY에는 getBoundingClientRect().top의 값을 넣어주고, 브라우저의 5분의 1 사이즈를 가져온 뒤 그 값보다 posY 값이 작았을 때, 일분이가 커지게 해준다.
- 브라우저의 5분의 1값은 window.innerHeight로 알 수 있는데, (이 값의 * 0.2)가 5분의 1이다.
- if문으로 posY의 값이 1의 값보다 작을 때, 일분이에게 'zoom'이라는 클래스를 붙혀준다. ilbuniElem.classList.add('zoom');
- else문으로 반대의 경우 'zoom'의 클래스를 remove한다.
이렇게 스크롤 이벤트를 구현해보았다.
스크롤 이벤트의 문제점
스크롤 이벤트는 비주얼적으로 훌륭한 효과를 줄 수 있지만, 매번 반응한다면 자원을 낭비하는 경우가 생기기 때문에 많은 리소스를 활용해야 하는 상황이라면 아래 블로그글을 참고해 최적화를 해주는 게 좋다.
'Front End' 카테고리의 다른 글
사파리os 에서 window.open(url, '_blank')시 페이지 중복 오픈현상 버그수정 (0) | 2022.02.14 |
---|---|
인터랙티브 웹 개발 제대로 시작하기-Transition이벤트 (0) | 2022.02.10 |
인터랙티브 웹 개발 제대로 시작하기-객체(Object) (0) | 2022.01.26 |
인터랙티브 웹 개발 제대로 시작하기-자바스크립트 이벤트 다루기 (0) | 2022.01.07 |
인터랙티브 웹 개발 제대로 시작하기-인터랙티브 웹 개발을 위한 자바스크립트 시작하기 (0) | 2021.12.26 |