Window.scrollTo()

seul_velog·2022년 1월 11일
0

JS note

목록 보기
5/9
post-thumbnail
post-custom-banner

웹사이트의 탭 메뉴를 클릭하면 특정 위치로 스크롤 바가 이동되면서 화면에 보여지는 작업

  • window 객체의 scrollTo 메서드는 문서를 지정된 좌표로 스크롤해주는 기능을 한다. (window는 생략 가능)


✍️ 원하는 요소로 스크롤 하는 동작을 이해한 과정대로 기록한 내용이다.


  • 먼저 네비게이션 바의 메뉴 컨테이너를 가져온다.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  console.log(e);
});


  • html에 data-* 사용자 지정 데이터 특성을 이용, 데이터를 가져온다.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  console.log(e.target);
});


const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  console.log(e.target.dataset);
});


  • 지정한 key를 통해 값을 확인한다.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  console.log(e.target.dataset.link);
});


  • 원하는 위치로 이동 + 부드러운 스크롤 처리를 한다.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  const link = e.target.dataset.link;
  const scrollTo = document.querySelector(link);
  scrollTo.scrollIntoView({ behavior: "smooth" });
});

  • 비어있는 공간을 클릭하면 에러가 뜬다.


  • 원하지 않는 데이터는 if문을 활용해서, 빠르게 리턴
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  const link = e.target.dataset.link;
  if (link == null) {
    return;
  }
  const scrollTo = document.querySelector(link);
  scrollTo.scrollIntoView({ behavior: "smooth" });
});

  • 그냥 링크를 출력할 때
  • 쿼리셀렉트로 링크를 선택자로 넣어서 가져왔을 때의 출력 비교
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  const link = e.target.dataset.link;
  console.log(link);
  if (link == null) {
    return;
  }
  const scrollTo = document.querySelector(link);
  scrollTo.scrollIntoView({ behavior: "smooth" });
  console.log(scrollTo);
});


  • 네비게이션 아이템(버튼)과 이벤트리스너를 활용해서 스크롤 작동
const contactBtn = document.querySelector(".home__contact");
contactBtn.addEventListener("click", () => {
  // console.log(e.target);
  // contactBtnDataset = contactBtn.target;
  const scrollTo = document.querySelector("#contact");
  scrollTo.scrollIntoView({ behavior: "smooth", block: "start" });
});

  • 함수를 활용해서 중복되는 요소를 제거한다.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  const link = e.target.dataset.link;
  if (link == null) {
    return;
  }
  scrollIntoView(link);
});


const contactBtn = document.querySelector(".home__contact");
contactBtn.addEventListener("click", () => {
  scrollIntoView("#contact");
});

function scrollIntoView(selector) {
  const scrollTo = document.querySelector(selector);
  scrollTo.scrollIntoView({ behavior: "smooth" });
}

❗️ 문제점
작동은 잘 되지만, 네브바가 섹션의 컨테이너를 침범해서 각 섹션 요소의 상단과 맞지 않는다.🤔






▼ 넷바 메뉴가 콘텐츠 상단에서 넷바 메뉴 높이만큼 가려지는 문제 해결하기

📌 아래를 활용해서 해결해 보자

  • scrollY
  • HTMLElement.offsetRop
  • window.scrollTo + ({top:scroll})

✍️ 문제점 파악 및 계획하기
1. window.scrollTo(지정위치로 스크롤) 을 사용해야 하는데 여기서 지정위치y값은 {top: ?? }로 줄 것이다.
2. ??를 정의해야 한다. 그냥 정의하면 위와 같은 문제가 반복될 것이다. 나는 계산된 값으로 정의하고 싶다.
2-1. HTMLElement.offsetTop로 계산할 수 있겠다.


  • offsetTop으로 해당 요소의 top 위치(마진 값까지 포함한다고 한다)를 가져온다.

  • 쿼리셀렉터 를 통해서 원하는 dataset 명을 담는다. (단순히 이름을 넣은 dataset) 쿼리셀렉터로 인해서 선택된 html 요소들을 활용해서 offsetTop을 출력해본다.

const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {

  const link = e.target.dataset.link;
  if (link == null) {
    return;
  }
  const LinkName = document.querySelector(link);
  const myScrollY = LinkName.offsetTop;
  console.log(myScrollY);
  // window.scrollTo({top: myScrollY})

});


  • 네비게이션 바의 높이만큼 빼주면 되지 않을까?
const LinkName = document.querySelector(link);
  const myScrollY = LinkName.offsetTop - navbarHeight;
  console.log(myScrollY);

  • window.scrollTo

  • MDN 한국번역 페이지에는 이렇게만 설명되어 있어서 값을 적어 넣는데 이해가 되지 않았다.

  • 그리고 같은 API 영문 사이트에는 이렇게 두가지를 제시한다.

  • 아래 사용예를 보고 작성해본다. 계산된 식을 넣은 변수를 top값으로 지정했는데, 실행이 되는 걸로 보아서 변수가 들어가는 것도 실행된 다는 것을 알 수 있었다. 🧐


❓결과는

  • 이렇게 하고 나니 섹션의 위치와 네브바하단이 정확히 일치 하지 않는다. 어떤 마진이나 다른 속성값 때문인 것 같다.

  • CSS에서 navbar 속성의 패딩이나 마진값을 확인 해 보았지만 달리 맞아 보이는 값이 안보여서 직접 맞는 값을 찾아 넣었다.

  const LinkName = document.querySelector(link);
  const myScrollY = LinkName.offsetTop - (navbarHeight - 16);
  console.log(myScrollY);


  • 버튼도 같은 방식으로 넣어주었다.
const contactBtn = document.querySelector(".home__contact");
contactBtn.addEventListener("click", () => {
  const LinkName = document.querySelector("#contact");
  const myScrollY = LinkName.offsetTop - (navbarHeight - 16);
  window.scrollTo({ top: myScrollY, behavior: "smooth" });
});
  • 작동이 잘 되는 것을 확인 할 수 있다!
  • 마찬가지로 scrollToFunc 함수를 정의, 중복을 제거하자.
const navbarMenu = document.querySelector(".navbar__menu");
navbarMenu.addEventListener("click", (e) => {
  
  const link = e.target.dataset.link;
  if (link == null) {
    return;
  }
  scrollToFunc(link);
});


const contactBtn = document.querySelector(".home__contact");
contactBtn.addEventListener("click", () => {
  scrollToFunc("#contact");
});

function scrollToFunc(selector) {
  const LinkName = document.querySelector(selector);
  const myScrollY = LinkName.offsetTop - (navbarHeight - 16);
  window.scrollTo({ top: myScrollY, behavior: "smooth" });
}

첫 번째 방법과는 다르게 정확히 섹션의 상단과 맞도록 스크롤이 되었다. 😀




reference
MDN - Window.scrollY
MDN - Window.scrollTo()
MDN - HTMLElement.offsetTop
MDN - data-*
dream-coding

profile
기억보단 기록을 ✨
post-custom-banner

0개의 댓글