-
[JS ํฌํธํด๋ฆฌ์ค ๋ง๋ค๊ธฐ] ์คํฌ๋กค ํ์ด์ง์ ๋ง๊ฒ ๋ฉ๋ด๋ฒํผ ์๋ ํ์ฑํ ์ํค๊ธฐMini Projects/make Portfolio 2022. 4. 1. 06:31
2022.03.24-26
๐คโ ์ด๋ป๊ฒ ์คํฌ๋กค์ ํ๋ฉด ์๋จ๋ฉ๋ด๋ฒํผ์ด ํด๋น ํ์ด์ง์ ๋ง๊ฒ ์๋์ผ๋ก ์ ํํ์ง
๊ฐ ํ์ด์ง์ ๋ฉ๋ด๋ฒํผ์ ์ฐ๊ฒฐ์์ผ ์ค ์ ์๋ ํญ๋ชฉ์ ์ฐพ์์, ํ์ด์ง์ ์์ง์์ด ๋ฐ์ํ ๋ ๋ฉ๋ด๋ฒํผ์๋ ์์ง์์ ์ฃผ๋ฉด ๋ ๊ฒ์ด๋ผ๊ณ ์๊ฐํ๋ค.
ํ์ธํด๋ณด๋ ํ์ด์ง์ ๋ฉ๋ด๋ ๋์ผํ 'id'๋ฅผ ๊ฐ๊ณ ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ ๊ฒ ํด๋ณด๋ฉด ์ด๋จ๊น.
case 1
ํ์ด์ง๊ฐ ์คํฌ๋กค ๋์ด ๋ฐ์ผ๋ก ๋ด๋ ค๊ฐ๋ฏ์ด, ์ ํ๋ ์ํ๋ ์์ผ๋ก ์คํฌ๋กค ๋๋๋ก ํ๋ฉด ๋๋ค๊ณ ์๊ฐํ๋ค.
1. ์ ํ๋ ๋ฉ๋ด๋ฒํผ์ ํด๋นํ๋ ํ์ด์ง์ ์ขํ๊ฐ์ ๊ตฌํ๋ค.
2. ํด๋น ์ขํ๊ฐ์ด ์๋์ฐ ์คํฌ๋ฆฐ ์ขํ์ ์ผ์น๋๋ฉด ์๋จ๋ฐ ๋ฒํผ์ ์ด๋์ํจ๋ค.
๊ทผ๋ฐ ํด๋ณด๋๊น ์๋๋ค. ์๋๋ฉด 'ํ์ด์ง'๊ฐ ์คํฌ๋กค ๋๋๊ฑฐ๊ธฐ ๋๋ฌธ์ด๋ค.
case2
์๋จ๋ฉ๋ด๋ฒํผ๊ณผ ํ์ด์ง์ id๊ฐ ๋์ผํ๋, ์คํฌ๋กค๋งํด์ ํ์ฌ ๋ณด์ด๋ ํ๋ฉด์ id์ ์๋จ๋ฉ๋ด id๊ฐ ๋์ผํ๋ค๋ฉด ๋ฉ๋ด๋ฒํผ์ ํ์ฑํ ์ํจ๋ค.
๊ทธ๋ฌ๋ฉด, ์คํฌ๋กค๋งํด์ ๋ณด์ด๋ ํ์ฌ ํ๋ฉด์ id๋ฅผ ์ด๋ป๊ฒ ์ฐพ์ ๊ฒ์ธ๊ฐ.
์ฌ๊ธฐ์ intersectionobserver๋ฅผ ์๊ฒ ๋๋ค.
๐โ
1) ๋ชจ๋ ์น์ ์ ์์๋ค๊ณผ ๋ฉ๋ด ์์ดํ ๋ค์ ๊ฐ์ ธ์จ๋ค.
(1) ๋ฐฐ์ด์ ์ด์ฉํด์ ๋ชจ๋ ์น์ ์ ์์๋ค์ ๊ฐ์ ธ์จ๋ค.
//1. ๋ฐฐ์ด์ ์ด์ํ์ฌ ๋ชจ๋ ์น์ ์ ์์๋ฅผ ๊ฐ์ ธ์จ๋ค. const sectionIds = ['#home', '#about', '#skills', '#work', '#testimonials','#contacts'];
(2) ์น์ id๋ฅผ ๋๋ฉด์ ์น์ ์ DOM์์๋ก ๋ง๋ ๋ค. (map์ฌ์ฉ)
//sectionIds๋ฅผ ๋๋ฉด์ queryselector๋ฅผ ํตํด id๊ฐ ์๋ section์ ๋ฐ์์ dom์์๋ก ๋ง๋ ๋ค. //map์ dom์์๋ก ๋ง๋ค์ด์ฃผ๋ ๊ธฐ๋ฅ์ ํ๋ค.(ํฐ ๊ฐ๋ ์ผ๋ก ๋ง๋ค์ด ์ฃผ๋ ์ญํ ์ธ๊ฐ.) const sections = sectionIds.map(id => document.querySelector(id)); console.log(sections); // 0: section#home // 1: section#about.section.section__container // 2: section#skills.section // 3: section#work.section // 4: section#testimonials.section // 5: section#contacts.section
์น์ Id๋ฅผ ๋๋ฉด์ DOM์์๋ก ๋ง๋ค์ด์ฃผ๋๋ฐ ์ด๋ map์ ์ด์ฉํ๋ค. ๋ญ๋๊น, ์์๊ฐ๋ ์ ํฐ ๊ฐ๋ ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ ์ญํ ์ ํ๋ ๋ฏ ํ๋ค.
(3) ์น์ id๋ฅผ ๋๋ฉด์ ์๋จ๋ฐ ์์ดํ ์ DOM์์๋ก ๋ง๋ ๋ค. (map์ฌ์ฉ)
//sectionIds๋ฅผ ๋๋ฉด์ queryselector๋ฅผ ํตํด navitem์ ๋ฐ์์จ๋ค. //sectionid์ ํด๋นํ๋ navitem์ ๋ถ๋ฌ์ค๊ธฐ ์ํด navitem ์์๋ค์ ๋ถ๋ฌ์จ๋ค. const navItems = sectionIds.map(id => document.querySelector(`[data-link="${id}"]`)); console.log(navItems); // 0: li.navbar__menu__item.active // 1: li.navbar__menu__item // 2: li.navbar__menu__item // 3: li.navbar__menu__item // 4: li.navbar__menu__item // 5: li.navbar__menu__item
2๋ฒ๊ณผ ๋๊ฐ์ด ์น์ id๋ฅผ ๋๋ฉด์ ์๋จ๋ฐ์ DOM์์๋ฅผ ๋ง๋ ๋ค.
์ด๋, ์๋จ๋ฐ์๋ id๋ก ๋ค์ด๊ฐ ์๋๊ฒ ์๋๋ผ data-link์ ๊ฐ์ด ๋ค์ด๊ฐ ์๊ธฐ ๋๋ฌธ์ `[data-link="${id}"]`๋ฅผ ์ด์ฉํ์ฌ ์์ด๋๊ฐ์ ๋ถ๋ฌ์์ฃผ๋ฉด ๋๋ค.
2) intersectionObserver๋ฅผ ์ด์ฉํด์ ๋ชจ๋ ์น์ ๋ค์ ๊ด์ฐฐํ๋ค.
(1) ์น์ ์ ๊ด์ฐฐํ observer์ ๊ธฐ๋ณธ์ธํ ์ ๋ง๋ ๋ค.
// observer์ต์ ์ค์ const observerOption = { root: null, rootMargin: '0px', threshold: 0.3, } //2) ์ด ๊ฐ์ฒด์๋ ๋ฐฐ์ด์ ๋๋ฉด์ ๋ด์ฉ์ ๋ฐํํ๋ค. const observerCallback = (entries, observer) => { entries.forEach(entry => { }; }; //1) observer๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.(๊ด์ฐฐ์๋ฅผ ๋ง๋ ๋ค.) const observer = new IntersectionObserver(observerCallback, observerOption);
(1) observer๋ผ๋ ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค. (๊ด์ฐฐ์๋ฅผ ๋ง๋ ๋ค)
(2) ์ด ๊ฐ์ฒด์๋ entries๋ผ๋ ๋ฐฐ์ด์ด ๋ค์ด์์ ๋ด์ฉ์ ๋๋ฉด์ ๊ด์ฐฐํ๊ณ ์ถ์ ๋ด์ฉ์ ๋ฐํํ๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ค ๋ด์ฉ์ ๊ด์ฐฐํ๊ณ ์ถ์๊น?
์ง๊ธ ๋ด๊ฐ ์ํ๋ ๊ฒ์ ์น์ ๊ณผ ์๋จ๋ฐ ์์ดํ ์ ์ฐ๊ฒฐ์์ผ์ฃผ๋ '๋ฌด์ธ๊ฐ'๋ฅผ ํด์ผํ๋ค.
๊ทธ๋ ๋ค๋ฉด ์น์ ์ด ์คํฌ๋กค๋ง ๋ ๋ ํด๋น ์น์ ์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ ธ์ ์ด๋ฅผ ์๋จ๋ฐ์ ์ธ๋ฑ์ค์ ์ฐ๊ฒฐ์ํค๋ฉด ๋์ง ์์๊น.
์ด๋ป๊ฒ ํ์ฌ ์์ง์ด๋ ์น์ ๊ณผ ์๋จ๋ฐ ์ธ๊ฒ๋ฅด๋ฅผ ์ฐ๊ฒฐ์ํฌ๊น.
์ด๋ฅผ ์ํด observeCallbackํจ์์ ์๋ ๋ด์ฉ์ ๋ฃ๋๋ค.
const observerCallback = (entries, observer) => { entries.forEach(entry => { if(!entry.isIntersecting && entry.intersectionRatio > 0) { //entry(target)์ ์ผ์นํ๋ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ ธ์จ๋ค. const index = sectionIds.indexOf(`#${entry.target.id}`); console.log(index, entry.target.id); //์๋กค ์คํฌ๋กค๋ง ๋ ๋ (์ฆ, ๋ฐ์ผ๋ก ๋ด๋ฆด ๋) = y์ขํ๊ฐ -์ผ ๊ฒฝ์ฐ //y์ขํ๊ฐ -์ผ ๊ฒฝ์ฐ์๋ index+1์ด ๋ navitem์์๋ฅผ ๋ณด์ฌ์ฃผ๊ณ //y์ขํ๊ฐ +์ผ ๊ฒฝ์ฐ์๋ index-1์ด ๋ navitem์์๋ฅผ ๋ณด์ฌ์ค๋ค. //์น์ ์ id์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ ธ์จ๋ค. let selectedIndex; if(entry.boundingClientRect.y < 0) { selectedIndex = index + 1; } else { selectedIndex = index - 1; } }
์์ง์ด๋ ๋ ผ๋ฆฌ๋ฅผ ์ง ๋ณด์๋ฉด,
ํ์ฌ๋ ์คํฌ๋กค์ ์๋ก ๊ตด๋ฆฌ๋ฉด์ ํ์ด์ง๊ฐ '์๋๋ก ๋ด๋ ค๊ฐ๋ ์ํ'์ธ๋ฐ,
1๋ฒ ์น์ ์ด ์๋ก ๋๊ฐ๋ฉด์ 2๋ฒ ์น์ ์ด ๋ณด์ฌ์ง๋ฉด ๋ฉ๋ด์์ดํ ์ 2๋ฒ์น์ ์ ๊ฐ๋ฆฌํค๋ฉด ๋๋ค.
์ฆ, 1๋ฒ ์น์ ์ y์ขํ๊ฐ์ด (-)๊ฐ ๋๋ฉด(์๋์ฐ๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์ ๋) 2๋ฒ ์์ดํ ์ ์ธ๋ฑ์ค๋ฅผ ๋ณด์ฌ์ฃผ๋ฉด ๋๋ค.
if(!entry.isIntersecting && entry.intersectionRatio > 0)
์ผ๋จ, ํ์ด์ง๊ฐ ์๋๋ก ๋ด๋ ค๊ฐ๋์ง, ์๋ก ์ฌ๋ผ์ค๋์ง๋ฅผ ์๊ธฐ ์ํด์ intersectionObserver์ isIntersecting์ด๋ผ๋ ๊ธฐ๋ฅ์ ์ด์ฉํ๋ค.
ํ์ด์ง๊ฐ '๋ค์ด์ค๋ ์ํ'์ด๋ฉด true๊ณ '๋๊ฐ๋ ์ํ'์ด๋ฉด false๋ฅผ ๋ฐํํ๋ค.
1๋ฒ ์น์ ์ด ๋๊ฐ๋ ์ํ์ด๋ฉด ์ํ๊ฐ false์ด๋ฏ๋ก if(!entry.isIntersecting) ๋ผ๊ณ ์ง์ ํ๋ค.
const index = sectionIds.indexOf(`#${entry.target.id}`);
ํ์ฌ ๋๊ฐ๊ณ ์๋ ์น์ ์ ํ๊ฒ์ผ๋ก ํด์ ํด๋น ์น์ ์ id์ ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ ธ์จ๋ค.
let selectedIndex; if(entry.boundingClientRect.y < 0) { selectedIndex = index + 1; } else { selectedIndex = index - 1; };
๋๊ฐ๊ณ ์๋ ์น์ ์ y์ขํ๊ฐ (-)์ด๋ฉด ํ์ฌ ์ธ๋ฑ์ค์์ 1์ ๋ํ๊ณ , (+)์ด๋ฉด 1์ ๋นผ์ค๋ค.
3) ์์์ ๊ตฌํ ์น์ ์ ์ธ๋ฑ์ค์ ์๋จ๋ฐ ์์ดํ ์ ์ธ๋ฑ์ค๋ฅผ ์ฐ๊ฒฐ์ํจ๋ค
let selectedNavItem = navItems[0]; function selectNavItem(selected) { //์น์ id์ ์ธ๋ฑ์ค์ ์ผ์นํ๋ Navitem์ ๊ฐ์ ธ์จ๋ค. //ํจ์ ๋ฐ์์ selctednavitem์ด๋ ์์๋ฅผ ๊ธฐ์ตํ๋ค๊ฐ, ์ง์์ฃผ๊ณ , ๋ค์ ํธ์ถํด์, ๋ํด์ค๋ค. selectedNavItem.classList.remove('active'); selectedNavItem = selected; selectedNavItem.classList.add('active'); };
์๋จ๋ฐ ์์ดํ ์ ์ธ๋ฑ์ค๊ฐ ์ ํ๋๋ฉด ๊ธฐ์กด์ ์กด์ฌํ๋ ์๋จ๋ฐ ์์ดํ ์์์์ active๋ฅผ ์ ๊ฑฐํ๊ณ ,
์๋ก ์ ํํ ์์ดํ ์์์ active๋ฅผ ์ถ๊ฐํด์ค๋ค.
(2) ๊ธฐ๋ณธ์ธํ ์ด ๋์๋ค๋ฉด ์ด๋ค ํญ๋ชฉ์ ๊ด์ฐฐํ ์ง ์ง์ ํด์ค๋ค.
//3) ์ด๋ค ๋ฐฐ์ด์ ๋๋ฉด์ ์ด๋ค ๋ด์ฉ์ ๋ฐํํ ์ง ์ง์ ํด์ค ๊ฒ์ด๋ค. (observer์ผ ๊ด์ฐฐํด์ค) sections.forEach(section => observer.observe(section));
(1)์์ ๋ง๋ ์น์ DOM์์๋ฅผ ๋๋ฉด์, ๊ฐ ์น์ ์ ๊ด์ฐฐํ๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด์ ์ด๋ค ๋ด์ฉ์ ๊ด์ฐฐํด์ค์ง ์๊ฐํด๋ณด์.
์ด๊ฑด ๋ค์์๊ฐ์.
eunne's github: https://github.com/eunne/Project_Portfolio.git
'Mini Projects > make Portfolio' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ