Javascript_30_26

Derek·2021년 1월 21일
0

javascript_30

목록 보기
27/31
post-thumbnail

안녕하세요!

Derek 입니다 😁

시리즈 5개 게시물만 남았네요! 어서 마무리짓고 싶은 마음뿐..!

이번 게시물은 Day 26 project를 다뤄볼거에요! 오늘은 눈에 보이는 멋진 게시물 관련 기능을 정리해보려고합니다.




26. Stripe follow along nav

목표

상단 그림처럼 메뉴 네비게이션 바에 목록 표시를 dynamic하게 구현한다.

24번 프로젝트와 같이 홈페이지나 포트폴리오를 만들때 유용할 것 같은 기능입니다. 이제까지 배운 속성들을 조금씩 활용해서 완성 할 수 있을것 같습니다.


Wes Bos 와 Derek 구현코드

const triggers = document.querySelectorAll(".cool > li");
const background = document.querySelector(".dropdownBackground");
const nav = document.querySelector(".top");

function handleEnter() {
  this.classList.add("trigger-enter");
  setTimeout( () => this.classList.contains("trigger-enter") && this.classList.add("trigger-enter-active"), 150);
  background.classList.add("open");

  const dropdown = this.querySelector(".dropdown");

  const dropdownCoords = dropdown.getBoundingClientRect();
  const navCoords = nav.getBoundingClientRect();

  const coords = {
    height: dropdownCoords.height,
    width: dropdownCoords.width,
    top: dropdownCoords.top - navCoords.top,
    left: dropdownCoords.left - navCoords.left
  }

  background.style.setProperty("width", `${coords.width}px`);
  background.style.setProperty("height", `${coords.height}px`);
  background.style.setProperty("transform", `translate(${coords.left}px, ${coords.top}px`);
}

function handleLeave() {
  this.classList.remove("trigger-enter", "trigger-enter-active");
  background.classList.remove("open");
}

triggers.forEach(trigger => trigger.addEventListener("mouseenter", handleEnter));
triggers.forEach(trigger => trigger.addEventListener("mouseleave", handleLeave));

약간 복잡합니다! 그래도 큰 덩어리로 묶자면, mouseenter 이벤트 하나와, mouseleave 이벤트 이렇게 2개의 함수로 구성되어 있어요.

이번 프로젝트는 HTML 파일도 필요할 것 같네요.

HTML 파일

<nav class="top">
    <div class="dropdownBackground">
      <span class="arrow"></span>
    </div>

    <ul class="cool">
      <li>
        <a href="#">About Me</a>
        <div class="dropdown dropdown1">
          <div class="bio">
            <img src="https://logo.clearbit.com/wesbos.com">
            <p>Wes Bos sure does love web development. He teaches things like JavaScript, CSS and BBQ. Wait. BBQ isn't part of web development. It should be though!</p>
          </div>
        </div>
      </li>
      <li>
        <a href="#">Courses</a>
        <ul class="dropdown courses">
          <li>
            <span class="code">RFB</span>
            <a href="https://ReactForBeginners.com">React For Beginners</a>
          </li>
          <li>
            <span class="code">ES6</span>
            <a href="https://ES6.io">ES6 For Everyone</a>
          </li>
          ...
        </ul>
      </li>
      <li>
        <a href="#">Other Links</a>
        <ul class="dropdown dropdown3">
          <li><a class="button" href="http://twitter.com/wesbos">Twitter</a></li>
          <li><a class="button" href="http://facebook.com/wesbos.developer">Facebook</a></li>
          <li><a class="button" href="http://wesbos.com">Blog</a></li>
          <li><a class="button" href="http://wesbos.com/courses">Course Catalog</a></li>
        </ul>
      </li>
    </ul>
  </nav>

element들에 대해서 뭐가 뭔지 설명드리려고 합니다.

  • top class (nav 태그) : 전체를 감싸는 태그
  • dropdownBackground class : 메뉴 리스트들 사이를 왔다갔다 하는 하얀색 배경
  • cool class : 이곳에 있는 li 가 크게 목록을 만드는 태그입니다.

기능별로 정리해보겠습니다.


1. element 추출

const triggers = document.querySelectorAll(".cool > li");
const background = document.querySelector(".dropdownBackground");
const nav = document.querySelector(".top");

각각 어떤 인자인지 설명하면,

  • triggers : cool class에 있는 li 들 (즉 메뉴바를 이루는 3개의 항목)
  • background : 마우스를 따라다니는 하얀색 배경 (메뉴바 목록이 펼쳐지면 깔아주는 배결)
  • nav : 전체를 감싸는 element.

2. mouseenter 이벤트

사용자가 마우스를 메뉴바에 올릴때 일어나는 이벤트 정리입니다.

function handleEnter() {
  this.classList.add("trigger-enter");
  setTimeout( () => this.classList.contains("trigger-enter") && this.classList.add("trigger-enter-active"), 150);
  background.classList.add("open");

  const dropdown = this.querySelector(".dropdown");

  const dropdownCoords = dropdown.getBoundingClientRect();
  const navCoords = nav.getBoundingClientRect();

  const coords = {
    height: dropdownCoords.height,
    width: dropdownCoords.width,
    top: dropdownCoords.top - navCoords.top,
    left: dropdownCoords.left - navCoords.left
  }

  background.style.setProperty("width", `${coords.width}px`);
  background.style.setProperty("height", `${coords.height}px`);
  background.style.setProperty("transform", `translate(${coords.left}px, ${coords.top}px`);
}

triggers.forEach(trigger => trigger.addEventListener("mouseenter", handleEnter));

전체 함수는 위와 같습니다! 여기서도 크게 2가지로 나눌수 있어요.

2-1) class 추가 기능

마우스가 메뉴바에 들어감에 따라 클래스를 추가해줘야합니다.

this.classList.add("trigger-enter");
setTimeout( () => this.classList.contains("trigger-enter") 
           && this.classList.add("trigger-enter-active"), 150);
background.classList.add("open");

마우스가 메뉴바 위에 위치하게 되면 li 태그에 2가지 클래스를 추가합니다.

trigger-enter 함수를 추가하고, 그 다음 trigger-enter-active 를 추가해줍니다.

이를 setTimeout 함수를 통해 구현했어요.

여기서 눈에 띄는점은, setTimeout 함수 내에 익명함수입니다.

setTimeout( () => this.classList.contains("trigger-enter") 
           && this.classList.add("trigger-enter-active"), 150);

this.classList.contains("trigger-enter") this.classList.add("trigger-enter-active")&& 연산자를 통해 전자가 맞다면 후자를 실행하도록 설계했어요.

아주 유용하게 쓰일것 같아서 강조해보았습니다!

2-2) getBoundingClientRect() 함수

const dropdown = this.querySelector(".dropdown");
const dropdownCoords = dropdown.getBoundingClientRect();
const navCoords = nav.getBoundingClientRect();

const coords = {
  height: dropdownCoords.height,
  width: dropdownCoords.width,
  top: dropdownCoords.top - navCoords.top,
  left: dropdownCoords.left - navCoords.left
}

background.style.setProperty("width", `${coords.width}px`);
background.style.setProperty("height", `${coords.height}px`);
background.style.setProperty("transform", `translate(${coords.left}px, ${coords.top}px`);
}

getBoundginCleintRect() 함수에 대한 설명은 22번째 프로젝트 게시물에서 확인할 수 있습니다!

간략하게 요약하자면 호출된 객체의 위치에 대한 정보를 가지고 있어요.

background.style.setProperty("width", `${coords.width}px`);
background.style.setProperty("height", `${coords.height}px`);
background.style.setProperty("transform", `translate(${coords.left}px, ${coords.top}px`);

이렇게 설정한다면 마우스를 따라 메뉴 목록의 뒷배경이 되어주는 background의 위치르 mouseenter 이벤트가 발생할때마다 조정해줄수 있겠죠!

3. mouseleave 함수 구현

마우스가 메뉴를 벗어나면 실행되는 함수는 간단합니다.

function handleLeave() {
  this.classList.remove("trigger-enter", "trigger-enter-active");
  background.classList.remove("open");
}

triggers.forEach(trigger => trigger.addEventListener("mouseleave", handleLeave));

그저 추가했던 클래스들을 지우고
하얀색 배경인 background 를 없애주면 됩니다!




이렇게 css 를 제외하고 해당 기능에 대해서 정리해보았습니다.

getBoundingClientRect() 함수는 여러모로 블로그를 만들때 꼭 필요한 함수인것 같네요 :)
틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!

감사합니다!🤗

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글