-
[JS ํฌํธํด๋ฆฌ์ค ๋ง๋ค๊ธฐ] ์ ํํ ํญ๋ชฉ๋ง ํํฐ๋งํ๊ธฐ (์ ๋๋ฉ์ด์ ํจ๊ณผ ์ ์ฉ)Mini Projects/make Portfolio 2022. 3. 22. 07:46
2022.03.22
๐คโ ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋นํ๋ ์ ๋ณด๊ฐ ํํฐ๋ง ๋์ด ์กฐํ๋๋ค.
์ค๋๋ถํฐ๋ JS๋ฅผ ์ ํ ์กฐ๊ธ ๋ ํ์ด์ง๋ฅผ ๋์ ์ผ๋ก ๋ง๋๋ ค ํ๋ค.
๐โ์ด๋ ๊ฒ ํด๋ณด์
1) ๊ฐ ํํฐ๋ฒํผ์ ๊ฒฐ๊ณผ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
(1) data- ๋ฅผ ์ด์ฉํ์
<div class="section__container"> <div class="work__categories"> <button class="category__btn active" data-filter="*">All<span class="category__count active">5</span></button> <button class="category__btn" data-filter="js">Javascript<span class="category__count">3</span></button> <button class="category__btn" data-filter="react">React<span class="category__count">2</span></button> </div> <div class="work__projects"> <!-- href: git url --> <a href="#" class="project" target="blank" data-filter="js"> ... </section>
๋ฒํผ์ ํด๋นํ๋ work__catergories์ ๊ฐ ๋ฒํผ ํด๋์ค์ data-filter๋ฅผ ์ถ๊ฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ํด๋น ๋ฒํผ์ ๋๋ฅด๋ฉด ํํฐ๋ง๋๋ ์ ๋ณด์ธ work__projects์ ๊ฐ ํ๋ก์ ํธ์๋ data-filter๋ฅผ ์ถ๊ฐํ๋ค.
๋ฒํผ๊ณผ ๊ฐ ํ๋ก์ ํธ์ ์ถ๊ฐํ data-filter์ ๊ฐ์ด ๊ฐ์ ํญ๋ชฉ๋ผ๋ฆฌ ๋ฒํผ์ ๋๋ฅด๋ฉด ํํฐ๋ง๋์ด ๋์ค๋๋ก ๋ง๋ค๊ฑฐ๋ค.//project filtering const workCategories = document.querySelector('.work__categories'); const workProjects = document.querySelector('.work__projects'); const projects = document.querySelectorAll('.project'); workCategories.addEventListener('click', (event) => { const filter = event.target.dataset.filter console.log(filter); })
console.log๋ก ํ์ธํด๋ณด๋ฉด event.target ์ผ๋ก ์์์ ์ค์ ํ data-filter์ ๊ฐ์ ์ ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
ํ์ง๋ง, ํ๋ก์ ํธ ๊ฐ์๋ฅผ ๋ํ๋๋ ๋๊ทธ๋ผ๋ฏธ ์์ ๋ค์ด๊ฐ ๋ฒํผ์ ๋๋ฅด๋ฉด undefined๊ฐ ๋ฐ์ํ๋ค.
์๋ง๋ ๋ฒํผ ์์ spanํํ๋ก ์ ์๋์ด์ ํด๋น ๋ฒํผ์๋ ๊ฐ์ด ์ ์ฉ์ด ์๋ ๋ฏ ํ๋ค. (event๊ฐ ๋ฐ์ํ๋ target์ ํน์ ํ๊ธฐ ๋๋ฌธ์ ์์๋ ธ๋๊น์ง๋ ์ด๋ฒคํธ๊ฐ ์ ์ฉ์ด ์๋๋๊ฑธ๊น?)(2) ๋ถ๋ชจ๋ ธ๋์ ๊ฐ์ ๊ฐ์ ธ์๋ณด์
์ด๋ฐ ๊ฒฝ์ฐ์๋ ํฌ๋กฌ ๊ฐ๋ฐ์๋ชจ๋์ ๋ค์ด๊ฐ์ undefined๊ฐ ๋ฐ์ํ๋ ๋ถ๋ถ์ breakpoint๋ฅผ ๊ฑธ์ด๋๊ณ local ๋ฑ์์ ์ด๋ค ํญ๋ชฉ๋ค์ด ์ ์ฉ๋์ด ์๋์ง ํ์ธํด๋ณธ๋ค. ์ฌ๊ธฐ์๋ ํ์ฌ event.target์ด ๋ฐ์ํ ๋ฒํผ(category__count.active)์ ๋ถ๋ชจ๋ ธ๋(button.category__btn.active)์ ์์์ filter๋ฅผ ์ค์ ํด๋์๋ ํด๋์ค๊ฐ ๋ค์ด์๊ธฐ ๋๋ฌธ์ ํด๋น ๋ฒํผ์ ๋๋ ์ ๋์๋ ๋ถ๋ชจ๋ ธ๋๋ก ์ฌ๋ผ๊ฐ์ data๋ฅผ ๊ฐ์ ธ์ค๋๋ก ์ค์ ํ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
workCategories.addEventListener('click', (event) => { const filter = event.target.dataset.filter || event.target.parentNode.dataset.filter console.log(filter); })
undefined๋ ์กฐ๊ฑด๋ฌธ์์ false๊ฐ์ ๊ฐ์ง๋ 'or'์ ํํ๋ก ๋ฌธ๋ฒ์ ๋ง๋ค๋ฉด ๋๋ค. ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ ์ ๋์จ๋ค.
2) ํํฐ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋น๊ฐ๊ณผ ์ผ์นํ๋ ํ๋ก์ ํธ๋ง ์กฐํ๋๋๋ก ๋ง๋ ๋ค.
(1) ํํฐ๋ฒํผ๊ฐ๊ณผ ๋น๊ตํ ํ๋ก์ ํธ์ ๊ฐ์ ๊ตฌํ๊ธฐ ์ํด forEach๋ฌธ์ ์ฌ์ฉํ์ฌ ์กฐ๊ฑด์ ์ํํ๋ค.
//project filtering //๋ชจ๋ ํ๋ก์ ํธ๋ฅผ ๋ฐฐ์ด๋ก ๊ฐ์ ธ์ค๊ธฐ ์ํด queryselectorall์ ์ฌ์ฉํ๋ค. const projects = document.querySelectorAll('.project'); workCategories.addEventListener('click', (event) => { const filter = event.target.dataset.filter || event.target.parentNode.dataset.filter; if (filter == null) { return; } projects.forEach((project) => { console.log(project); }); });
๋ฒํผ์ ๋๋ฅด๋ฉด target์ผ๋ก ์ง์ ํ ๊ฐ๋ง ๊ฐ์ ธ์ค๊ธฐ ์ํด, ๋ชจ๋ ์กฐ๊ฑด๋ค์ ์กฐํํด์ ์ผ์นํ๋ ๊ฐ์ด ์๋์ง ํ์ธํด์ผ ํ๋ค.
๊ทธ๋ฌ๋ฌ๋ฉด ์ํ๋ฅผ ํด์ผํ๋๋ฐ for๋ฌธ์ ์ฌ์ฉํ ์๋ ์์ผ๋ forEach๋ผ๋ ๋ ๊ฐ๋จํ ์กฐ๊ฑด๋ฌธ์ด ์์ผ๋ ์ด๋ฅผ ์ฌ์ฉํ๋๋ก ํ๋ค.
์ถ๋ ฅํด๋ณด๋ ์ ๋์จ๋ค.... if (filter == null) { return; } projects.forEach((project) => { console.log(project.dataset.filter); project.dataset.filter == 'js' ? console.log('true') : console.log('false'); });
๋ฐ๋ณต๋ฌธ๋ค ๋๋ฉฐ ๋์ค๋ ๊ฐ๊ณผ, ํด๋น ๋ฒํผ์ ์ค์ ๋ ์๋ ๊ฐ์ด ๋์ผํ๋ฉด true๊ฐ ๋์์ผ ํ๋, ํ ์คํธ๋ฅผ ํด๋ณธ๋ค.
๊ทธ๋ฅ project๋ง ์ ์ผ๋ฉด ์์๊ฐ์ด project์ ํด๋นํ๋ ๋ชจ๋ ์ ๋ณด๊ฐ ๋์ค๊ธฐ ๋๋ฌธ์ ํด๋์ค๋ฅผ ํน์ ํด์ค์ผํ ๊ฒ ๊ฐ๋ค.
๊ทธ๋์ dataset.filter๋ผ๊ณ ๊ตฌ์ฒด์ ์ผ๋ก ๊ฐ์ ์ง์ ํด์ฃผ์๋ค.
์ฌ๊ธฐ์ ๋๋ ์๋ฌธ์, ๋น๊ต๋์์ด ๋๋ '์์๊ฐ(์์์๋ 'js')'์ด ๊ณ ์ ์ธ๋ฐ, ๋ง์ฝ ๊ทธ ๋น๊ต๋์์ด ๋ ๋ง์์ง๋ฉด ์ค์ฒฉ for๋ฌธ์ ์จ์ผํ๋๊ฑธ๊น?
์๋๋ค.
๋ด๊ฐ ๋ญ ์๋ชป์๊ฐํ๊ณ ์์๋ค.
(1)์์ ๊ตฌํ๋ ๊ฒ์ด ํํฐ๋ฒํผ์ ๋๋ ์ ๋ ๋์ค๋ '์์๊ฐ'์ด๊ณ
(2)์์๋ ์กฐํ๋์์ด ๋๋ ํ๋ก์ ํธ๋ค์ ๋ฐ๋ณต๋ฌธ์ผ๋ก ๋๋ฉด์ (1)์์์ ๊ฐ๊ณผ ๋น๊ตํ๋๋ก ๋ง๋ค๋ฉด ๋๋ค.[js] workCategories.addEventListener('click', (event) => { //ํํฐ์ ์์๊ฐ ๊ตฌํ๊ธฐ const filter = event.target.dataset.filter || event.target.parentNode.dataset.filter; //ํํฐ๋ฒํผ์ ๋ค๋ฅธ ๊ณณ์ ๋๋ ์ ๋ undefiend๊ฐ ๋์ค๋ฏ๋ก ํด๋น ํด๋ฆญ์ ๋ํ ์ด๋ฒคํธ๋ฅผ ์์ ์ค๋ค. if (filter == null) { return; } //๊ฐ ํ๋ก์ ํธ์ ๊ฐ์ ์กฐํํ๊ธฐ projects.forEach((project) => { // ํํฐ๊ฐ์ด *์ด๊ฑฐ๋, ํ๋ก์ ํธ ๊ฐ๊ณผ ๋์ผํ๋ค๋ฉด ํญ๋ชฉ์ด ๋ชจ๋๋ค ๋ณด์ด๋๋ก ๋ง๋ค์ if (filter === '*' || filter === project.dataset.filter) { project.classList.remove('invisible') } else { project.classList.add('invisible') } }); });
[css] .project.invisible { display: none; }
ํํฐ๋ฒํผ์ ๋๋ ์ ๋, ํํฐ๋ฒํผ๊ฐ์ด *์ด๊ฑฐ๋ ํด๋น ๊ฐ๊ณผ ํ๋ก์ ํธ๋ค์ ๊ฐ์ ๋น๊ตํด์ ์ผ์นํ๋ฉด ๋ณด์ด๋๋ก ๋ง๋ค์ด์ผ ํ๋ค.
ํ์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ๋ชจ๋ ํ๋ก์ ํธ๋ค์ด '๋ณด์ฌ์ง'์ํ์ด๋, ์ผ์นํ์ง ์๋ ํญ๋ชฉ๋ค์๋ง invisible ํด๋์ค๋ฅผ ๋ฃ์ด์ ์๋ณด์ด๋๋ก ๋ง๋ค๋ฉด ๋๋ค.3) ์ ๋๋ฉ์ด์ ์ ์ค ๋ณด์
๊ฐ ํ๋ก์ ํธ ํญ๋ชฉ์ด ํํฐ๋ง ๋ ๋, ์ ๋๋ฉ์ด์ ์ ์ค๋ณด๋๋ก ํ์.
[js] workCategories.addEventListener('click', (event) => { ... //์ ๋๋ฉ์ด์ ์ ๊ฐ ํ๋ก์ ํธ๋ฅผ ๋ด๊ณ ์๋ ์์์๋ค๊ฐ ์ค workProjects.classList.add('anime-out'); ... });
๊ฐ ํ๋ก์ ํธ์ ์ฃผ๋ฉด ๋๋ ํ๋๋ฐ, ํ๋ก์ ํธ๋ฅผ ๋ด๊ณ ์๋ ์์์๋ค๊ฐ ์ฃผ๋ฉด ํ๋ฒ์ ์ ๋๋ฉ์ด์ ์ด ์ผ์ด๋จ์ผ๋ก ํ๋ก์ ํธ๋ฅผ ๋ด๊ณ ์๋ ์์์๋ค๊ฐ ์ ๋๋ฉ์ด์ ์ ์ฃผ๋๋ก ํ๋ค.
[css] .work__projects { display: flex; flex-wrap: wrap; justify-content: center; padding: var(--padding-20); opacity: 1; transition: all var(--animation-duration) ease-out; } .work__projects.anime-out { opacity: 0; transform: scale(0.96, 0.96) translateY(40px); }
transition์ด ์ผ์ด๋๋ ๊ฑด ๋ฉ์ธ ํด๋์ค(.work__projects)์ ์ ์ํด์ผ ํด๋น ๋ฐ์ค์ ์๋ก์ด ํด๋์ค(.anime-out)๊ฐ ์ถ๊ฐ๋๋ฉฐ ๋ณํ๋ ๋ ์ ๋๋ฉ์ด์ ์ด ์ผ์ด๋๊ฒ ๋๋ค.
์ ๋๋ฉ์ด์ ์ ์ฌ๋ผ์ง๋ฉด์ ์์๊ฐ ์๋๋ก ์์์ง๋๋ก ๋ง๋ค์๋ค.(1) ์ ๋๋ฉ์ด์ ์ ์ ์ฉํ๋๋ ์์๊ฐ ์ฌ๋ผ์ ธ๋ฒ๋ ธ๋ค?
๊ทธ๋ฐ๋ฐ ์ ์ ๋๋ฉ์ด์ ์ ์ ์ฉํด๋ณด๋ฉด ์์๊ฐ ์ฌ๋ผ์ง์ํ๋ก ๊ณ์ ์กด์ฌํ๋ค.
์๋ํ๋ฉด opacity๊ฐ 0์ธ ์ํ๋ก ๊ณ์ ์ ์ฉ๋์ด์๋ ์ํ์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ์ ๋๋ฉ์ด์ ์ด ๋ฐ์ํ๊ณ ์ผ์ ์๊ฐ ๋ค์ ํด๋น ์ ๋๋ฉ์ด์ ์ ์ข ๋ฃํด์ฃผ๋ ๋ช ๋ น์ ํด์ค์ผ ํ๋ค.(2) setTimeout()
workCategories.addEventListener('click', (event) => { ... setTimeout(() => { workProjects.classList.remove('anime-out'); }, 300); ... });
300ms ํ์ workprojects ์์ anime-outํด๋์ค๋ฅผ ์ ๊ฑฐํด์ค.๋ผ๋ ๋ช ๋ น์ด๋ค.
์ด๋ ๊ฒ ์ ์ฉํ๊ฒ ๋๋ฉด ๋ณด์ด๋ ๊ฒ์ฒ๋ผ ์ ๋๋ฉ์ด์ ์ด ์ ์ฉ๋ ํ์ ๋ค์ ์์๋ค์ด ๋ณด์ด๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
ํ์ง๋ง, ์ ๋๋ฉ์ด์ ์ ๋ณด๋ฉด ์ด๋ฏธ 'ํํฐ๋ง์ด ๋ ํ์ ์ ๋๋ฉ์ด์ ์ด ์ ์ฉ'๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ ๋๋ฉ์ด์ ์ด ์๋ฏธ๊ฐ ์์ผ๋ ค๋ฉด ์ ๋๋ฉ์ด์ ์ด ์ ์ฉ ๋๋ฉด์ ํํฐ๋ง์ด ๋์ด์ผ ํ๊ธฐ์ ๋ฐฉ๋ฒ์ ๋ค์ ๋ฐ๊ฟ๋ณธ๋ค.
(์ฆ, ์ง๊ธ์ ํํฐ๋ง์ด ๋๊ณ -> ์๋๋ก ์ฌ๋ผ์ง๋ฉด์ ๋ค์ ์ฌ๋ผ์ค๋ ์ ๋๋ฉ์ด์ ์ด ์ ์ฉ๋์ด์์ง๋ง
์๋๋ก ์ฌ๋ผ์ง๋ฉด์ ๋ค์ ์ฌ๋ผ์ฌ ๋ -> ํํฐ๋ง์ด ๋๋๋ก ์ ๋๋ฉ์ด์ ์ ๋ฐ๊พธ๊ฒ ๋ค๋ ๊ฒ์ด๋ค.)
ํ์ฌ ์ด๋ฐ ํ์์ด ๋ฐ์ํ๋ ์ด์ ๋ฅผ ์ดํด๋ณด์.
์์ฑํ ์ฝ๋๋ฅผ ์ดํด๋ณด๋ฉด
1. ์ ๋๋ฉ์ด์ ์ด ์ ์ฉ๋๋ค.
2. ์ ํํ ํญ๋ชฉ์ด ํํฐ๋ง์ด ๋๋ค.
3. ์ ๋๋ฉ์ด์ ์ 300ms ํ์ ์ ๊ฑฐํ๋ค.
ํ์ฌ js๋ deferํ๊ฒ ์๋ํ๋๋ก ์ค์ ํ๊ธฐ๋๋ฌธ์, ๋ชจ๋ ์์๋ค์ด ๋๊ธฐ์ ์ผ๋ก ๋ฐ์ํ์ฌ ๋ธ๋ผ์ฐ์ ์ ์ ๋ฐ์ดํธ ๋๋ค.
์ฆ, 1,2,3๋ฒ ์ฝ๋๊ฐ ์คํ ํ ์ค๋น๋ฅผ ๋์์ ํ ํ์, ๋๊ธฐ๋ฅผ ํ๋ค๊ฐ ๋ธ๋ผ์ฐ์ ์์ ์ ๋ณด๋ฅผ ์ฝ์ด์ค๋ ์ผ์ด ๋ชจ๋ ๋๋๋ฉด ๊ทธ ๋ ์คํ๋๋ค.
๋จ์ง 1,2๋ฒ์ ๋์์ ์คํ๋๊ณ 3๋ฒ์ 300msํ์ ์คํ๋๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ 1๋ฒ์ด ๋จผ์ ์ ์ฉ๋๊ณ 2,3๋ฒ์ด ๋์ค์ ์คํ๋๊ฒ ํ๊ธฐ ์ํด์๋ 2๋ฒ๊ณผ 3๋ฒ์ ํ๋๋ก ๋ฌถ์ด์ฃผ๋ฉด ๋๋ค.
(1๋ฒ์ด ๋จผ์ ์ ์ฉ๋์ด์ผ ํ๋ ์ด์ ๋ '์๋๋ก ์ฌ๋ผ์ง๋ ํจ๊ณผ'๋ฅผ ์ ์ฉ ํ ํ์ -> 'ํด๋น ํจ๊ณผ๋ฅผ ์์ ๋ฉด์ ํํฐ๋ง ํญ๋ชฉ์ ๋ณด์ฌ์ฃผ๊ณ ์ถ๊ธฐ ๋๋ฌธ'์ด๋ค.)
ํ๋๋ก ๋ฌถ์ด์ฃผ๊ธฐ ์ํด์ 3๋ฒ settimeout ํจ์ ์์ 2๋ฒ ์ฝ๋๋ธ๋ญ์ ๋ฃ์ผ๋ฉด ๋๋ค.workCategories.addEventListener('click', (event) => { ... //์ ๋๋ฉ์ด์ ์ ๊ฐ ํ๋ก์ ํธ๋ฅผ ๋ด๊ณ ์๋ ์์์๋ค๊ฐ ์ค workProjects.classList.add('anime-out'); setTimeout(() => { //ํ๋ก์ ํธ ํํฐ๋ง ์ฝ๋๋ฅผ settimeoutํจ์ ์์ ๋ฃ์๋ค. projects.forEach((project) => { if (filter === '*' || filter === project.dataset.filter) { project.classList.remove('invisible') } else { project.classList.add('invisible') } workProjects.classList.remove('anime-out'); }); }, 300); });
๊ทธ๋ฌ๋ฉด ์ด๋ ๊ฒ ์์๊ฐ ์๋๋ก ์ฌ๋ผ์ง๊ณ '์ฌ๋ผ์ค๋ฉด์ ํํฐ๋ง ๋๋' ์ ๋๋ฉ์ด์ ์ด ํ์ํ๋ค.
์ค๋์ ๋ญ๊ฐ js์ ๋๊ธฐ์ ์ฒ๋ฆฌ์ ๋ํ ๊ฐ๋ ์ ์ค์ ๋ก ์ฝ๋๋ฅผ ํตํด ํ์ธํด๋ณธ ๊ฒ ๊ฐ์์ ์ดํด๊ฐ ๋ ์ ๋ ๊ฒ ๊ฐ๋ค.
์ ์ ์๋ก์ด ํจ์๋ค์ด ๋์์ ์ฌ๋ฐ๋ค.
eunne's github: https://github.com/eunne/Project_Portfolio.git
'Mini Projects > make Portfolio' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ