DOM API를 활용하여 Y축 좌표 따오는 방법

Nanotube·2021년 7월 24일
3

React

목록 보기
5/7
post-thumbnail

혼자서 진행하는 프로젝트를 진행하면서 중첩된 Navbar를 작성해주는 중 어떻게 작성해야할지 막막하여 구글링과 다양한 시도를 하게되었다. 우선 처음 Navbar는 최상단에 위치하여야 하며, 두번째 Navbarcss의 속성 position 의 옵션중 하나인 fixed로 스크롤을 내릴때마다 따라오게 해주는 방향으로 잡았었다.

문제는 이제부터였다. 우선 두가지 Navbar를 작성하고, 각각의 스크롤 효과를 주기위해 window.scrollY를 사용하여 주었는데, 두번째 Navbar가 빌어먹게도 엉뚱한 위치에 가있거나 사라져 버리는 등 골치를 꽤나 썩였다. 자세한 원인을 파악하기 위해 구글링 중 컴포넌트가 한페이지에 여러개 붙어있기 때문에 두번째 Navbarwindow.scrollY로 기준을 잡았기 때문에 발생하는 문제였었다. 그렇게 postionabsolute,sticktop:0등 다양한 옵션을 수정하고 바꿔도 될리가 없었다. 어떻게든 찾은 구글링을 통해 DOM API를 활용하는 해답을 얻게되었다.

위치 시작점에 따른 좌표 따오기

보통 웹페이지 개발을 할 경우 x축의 좌표보다는 y축 좌표를 주로 사용한다. 내 개인 프로젝트도 마찬가지고.. 스크롤을 내리면서 효과를 구현한다거나 Child요소의 y좌표를 구할 경우를 가정해보자.

  width: 100%;
  height: 200VH;

width:100%, height: 200vh 의 사이즈의 페이지안에 각각의 크기의 두 요소가 존재하는데 DOM API가 제공하는 명령어를 통해 좌표를 알아볼 생각이다.

두가지 DOM API

element.getBoundingClientRect() : 뷰포트(Viewport)를 이루는 가장자리와 요소(element)와의 거리 정보를 가지고 있는 객체를 리턴하는 메소드이다. 반환하는 객체로는 top, bottom, left, right 프로퍼티가 존재하며 뷰포트와의 방향별 거리를 의미한다.

window.pageYOffset: 수직 방향으로 얼마나 스크롤했는지 픽셀 단위로 알려주는 window객체의 속성으로, window.scrollY와 같은 값을 가진다.

실제 예시

이 예제는 Reactstyled-components로 작성되어있어서 useRef()useEffect()를 활용하여 작성해봤다.

import React, { useEffect, useState } from "react";
import { Redirect } from "react-router-dom";
import { useRef } from "react";
import { Target, TargetBox, Test } from "./styles/styeldGames";

export default function Games() {
  const parentElement = useRef(null);
  const childElement = useRef(null);

  const distancePeFromTop = () => {
    let peTop = parentElement.current.getBoundingClientRect().top;
    console.log("HTML시작점으로부터의 거리(부모요소의 TOP):", peTop);
  };

  const distancePeFromBottom = () => {
    let peBTM = parentElement.current.getBoundingClientRect().bottom;
    console.log("HTML시작점으로부터의 거리(부모요소의  Bottom):", peBTM);
  };

  const distanceChildFromTop = () => {
    let chTop = childElement.current.getBoundingClientRect().top;
    let peTop = parentElement.current.getBoundingClientRect().top;
    console.log("부모요소와의 거리(각 요소의  TOP),", chTop - peTop);
  };

  const distanceChildFromBottom = () => {
    let chBTM = childElement.current.getBoundingClientRect().bottom;
    let peBTM = parentElement.current.getBoundingClientRect().bottom;
    console.log("부모요소와의 거리(각 요소의  Bottom),", chBTM - peBTM);
  };

  const distanceFromHTML = () => {
    let chTop =
      childElement.current.getBoundingClientRect().top + window.pageYOffset;
    console.log("뷰포트 시작점으로부터의 거리:", chTop);
  };

  useEffect(() => {
    window.addEventListener("scroll", distancePeFromTop);
    window.addEventListener("scroll", distancePeFromBottom);
    window.addEventListener("scroll", distanceChildFromTop);
    window.addEventListener("scroll", distanceChildFromBottom);
    window.addEventListener("scroll", distanceFromHTML);
  }, []);

  return (
    <Test>
      <TargetBox ref={parentElement}>
        나는 네모의 부모요소
        <Target ref={childElement}>나는 네모</Target>
      </TargetBox>
    </Test>
  );
}

이제 대충 작성은 되었으니 스크롤을 내릴 경우 console.log()로 아래의 이미지와 같이 출력된다.

스크롤을 내림에 따라 뷰포트, 부모요소와의 거리를 픽셀단위로 콘솔에 찍히는 모습을 볼 수 있다.

결과적으로 보면 이렇게 된다.

ref:maxkim-j블로그

profile
나노튜브

0개의 댓글