이야기 정리

[자바스크립트] 엘리먼트의 위치 값 구하기 - getBoundingClientRect(), offsetTop 본문

개발공부/JavaScrit

[자바스크립트] 엘리먼트의 위치 값 구하기 - getBoundingClientRect(), offsetTop

jinhistory 2023. 3. 28. 15:52

getBoundingClientRect()란?

  • element의 크기, 위치 정보를 담은 DOMRect 객체를 반환한다.
  • y, x, top, right, bottom, left, width, height 등의 속성을 가지고 있다.
  • width, height 는 element의 가로 세로 값을 나타낸다.
  • y와 top 값은 같지만, bottom의 경우 height값을 포함한 값이다.
  • x와 left 값은 같지만, right의 경우 width 값을 포함한 값이다.

 

글보다는 그림을 보면 한번에 이해하기 쉽다!

사진 출처 : https://developer.mozilla.org/ko/docs/Web/API/Element/getBoundingClientRect

 

예제 : getBoundingClientRect()을 활용한 스크롤 애니메이션

See the Pen 스크롤이벤트 by beren-105 (@beren-105) on CodePen.

위 예제를 보면 스크롤을 내리면 아래 있던 문단들이 천천히 모습을 드러낸다. 

먼저 자바스크립트 코드를 살피며 어떤 방식인지 살펴보자.

 

const els = document.querySelectorAll('.el')
window.addEventListener('scroll', (e) => {

// 1. veiwport의 높이 값을 구한다.
const veiwPortHeigth = window.innerHeight;

// 2. 반복문을 통해 현재 거리가 veiwport의 높이보다 작아지면 나타나게 만든다.
for (var i=0; i<els.length; i++) {
    const y = els[i].getBoundingClientRect().y;

    if (y <veiwPortHeigth - 100) {
        els[i].classList.add('opactiy-100');
    } else {
        els[i].classList.remove('opactiy-100');
    }
    }
})

.getBoundingClientRect().y의 값은 els 엘리먼트와 가까워질수록 값이 작아진다.

왜냐면 .getBoundingClientRect()는 엘리먼트와 viewport에서 얼마만큼 떨어져 있는지 나타내기 때문이다.

이 값이 viewport의 높이값보다 작아지면 els 엘리먼트가 나타나게 코드를 작성했다.

 

여기서 veiwPortHeigth 값에 -100을 준 이유는 엘리먼트가 나타나자마자 바로 애니메이션이 실행되는 것보다는, 어느정도 위로 올라온 뒤에 실행되는 것이 자연스럽기 때문이다.

 

getBoundingClientRect 메서드를 사용해 스크롤 애니메이션을 구현하면 문제점이 존재한다.

위 방법처럼 고정값으로 애니메이션 효과를 주면 반응형 웹처럼 사이즈가 변경될 시 똑같이 작동하지 않을 수 있다는 점이다! 이 문제를 해결하기 위한 방법은 추후 리액트를 활용해 자세히 다루려한다.

 


.getBoundingClientRect()가 viewport에서의 위치값을 반환했다면, 부모 엘리먼트와의 거리를 잴 수 있는 방법도 있다.

 

Element.offsetTop

  • 부모 엘리먼트와의 거리를 반환한다.
  • viewport에서 얼마만큼 떨어졌는지보다, 부모 element와의 거리가 필요할 때 적절하다.

 

예제 : offsetTop 프로퍼티를 이용한 클릭 이벤트

See the Pen offsetTop 이벤트 by beren-105 (@beren-105) on CodePen.

버튼을 클릭할 시 박스가 아래로 내려가되, 박스 밖으로 나가지 않는 이벤트다.

이번에도 먼저 코드부터 살펴보자.

 

const btn = document.querySelector('button');

btn.addEventListener('click', () => {
    const box = document.querySelector('.box');

    // 1. offsetTop으로 현재의 위치를 구한다.
    const positio = box.offsetTop;
    // 2. clientHeight로 최대 높이를 구한다.
    const maxHeight = document.querySelector('.section').clientHeight;
    let currentPosition = positio;

    // 3. if문을 사용해 현재 위치가 최대 높이보다 커지지 않게한다.
    if (currentPosition + box.clientHeight < maxHeight) {
        currentPosition += 50;
        box.style.top = `${currentPosition}px`
    }
})

만약 첫번째 코드처럼 getBoundingClientRect 메서드를 사용했다면 박스 안에만 위치 시킬 수 없었다. 하지만 부모 엘리먼트와의 위치를 구하는 offsetTop 프로퍼티를 사용해 처음 위치를 구하면 가능하다.

 

viewport의 높이를 알고 싶다면 window.innerHeight / 엘리먼트의 높이를 알고 싶다면 Element.clientHeight을 사용한다고 기억해두면 다른 코드를 짤 때 유용하게 써먹을 수 있다.

 

 

 

 

 

참조

https://developer.mozilla.org/ko/docs/Web/API/Element/getBoundingClientRect

https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop

Comments