시리즈 5개 게시물만 남았네요! 어서 마무리짓고 싶은 마음뿐..!
이번 게시물은 Day 26 project를 다뤄볼거에요! 오늘은 눈에 보이는 멋진 게시물 관련 기능을 정리해보려고합니다.
상단 그림처럼 메뉴 네비게이션 바에 목록 표시를 dynamic하게 구현한다.
24번 프로젝트와 같이 홈페이지나 포트폴리오를 만들때 유용할 것 같은 기능입니다. 이제까지 배운 속성들을 조금씩 활용해서 완성 할 수 있을것 같습니다.
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
가 크게 목록을 만드는 태그입니다.기능별로 정리해보겠습니다.
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.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가지로 나눌수 있어요.
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")
를&&
연산자를 통해 전자가 맞다면 후자를 실행하도록 설계했어요.
아주 유용하게 쓰일것 같아서 강조해보았습니다!
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
이벤트가 발생할때마다 조정해줄수 있겠죠!
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()
함수는 여러모로 블로그를 만들때 꼭 필요한 함수인것 같네요 :)
틀린내용이나 수정할 내용이 있다면 언제든지 피드백 부탁드립니다!
감사합니다!🤗