ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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

Designed by Tistory.