WEB-DEVELOPMENT

Editing
  • account_tree
  • bug_report

화면 스크롤시 getBoundingClientRect() 메소드 사용

화면을 특정 위치로 스크롤하기 위해서는 해당 위치의 문서 상단으로 부터 떨어진 거리를 구해야 한다. 주로 offsetTop 속성을 사용하지만 getBoundingClientRect() 메소드를 사용하는 경우도 있을 수 있다. 주의할 점은 거리 측정 기준이 다르다는 것이다.

getBoundingClientRect() 메소드가 offsetTop 프로퍼티와 다른점

getBoundingClientRect() 메소드는 뷰포트 상단(또는 하단)으로 부터의 거리를 top(또는 bottom) 키 값으로 조회가 가능하다. 반면에 offsetTop 프로퍼티는 상대적 기준이 되는 가장 가까운 상위 요소로 부터의 수직상의 거리를 나타낸다.

왜 getBoundingClientRect() 메소드를 사용할 필요가 있을까?

offseTop 프로퍼티는 상대적 기준(relative)이 되는 상위 요소가 존재한다면 스크롤 값을 구하기는 매우 어려워질 수 있다. 차라리 뷰포트가 기준이 되어 뷰포트 상단으로 맞추는게 더 편하고 유리할 수 있다. 하지만 처음에 스크롤 동작은 매우 훌륭하지만 연달아 동일 메뉴를 선택하는 경우에는 스크롤 전과 스크롤 후의 뷰포트 상단으로 부터의 거리가 달라지므로 오동작이 발생한다.

오동작이란?

다음 코드를 실행하여 동일 메뉴를 연달아 클릭해 보라.

해결 방법은?

몇가지 해결 방법이 존재할 것이다. 중요한 것은 연달아 클릭할 경우 스크롤 동작을 차단하는 것이다. 다음 아래의 코드는 메뉴 선택시 인덱스를 저장한 변수를 활용하여 연달아 클릭할 경우 스크롤 동작을 차단한다.

또 다른 문제는?

사실 위 코드는 매우 중대한 문제를 가지고 있다. 전적으로 뷰포트 상단으로부터 떨어진 거리 값을 이용해서 뷰포트 상단에 맞추어 스크롤시키는데 만약에 특정 메뉴를 눌러 화면을 스크롤하면 나머지 스크롤 위치를 결정짓는 요소들이 뷰포트 상단으로부터의 거리가 변경되게 된다. 다른 메뉴에게 이 값을 반영하면 원하는 위치로 스크롤할 수 없게 된다.

따라서 페이지 로드 후에 위치값이 사용되어지는 요소들의 getBoundingClientRect().top 값을 미리 계산해 배열에 담아두는게 좋다. 이 내용은 다음의 링크를 참고하기 바란다. 

내용 참고하기

만약에 사전에 준비한 뷰포트 상단으로부터의 거리 값을 이용한다면 위 마지막 코드에서 적용한 curIdx 변수와 관련 코드는 의미가 없게 된다.

다음의 코드가 최종 버전이다.