inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

애플 웹사이트 인터랙션 클론!

main.js 적용 내용

선생님 안녕하세요 코드 적용 후 에러가 발생하고 있습니다 ㅠㅠ

236

radbenet

작성한 질문수 2

0

벌써 두시간 째 원인 파악 하고 있는데

도저히 찾을 수가 없네요 

선생님 도와 주세요

breakpoint 찍어봐도 

제가 실력이 부족해서

지금까지 잘 해 왔는데 갑자기 이러니까 너무 슬프네요

살려주세요!

코드 첨부해드리겠습니다.

(() => {

  let yOffset = 0// window.pageYOffset 대신 쓸 수 있음
  let prevScrollHeight = 0// 현재 스크롤 위치 yOffset 보다 이전에 위차한 스크롤 섹션들의 스크롤 높이값의 합
  let currentScene = 0// 현재 활성화된 씬
  let enterNewScene = false// 새로운 Scene이 시작되는 순간 true
  
  const sceneInfo = [
    {
      // 0
      type: 'sticky',
      heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅
      scrollHeight: 0,
      objs: {
        container: document.querySelector('#scroll-section-0'),
        messageA: document.querySelector('#scroll-section-0 .main-message.a'),
        messageB: document.querySelector('#scroll-section-0 .main-message.b'),
        messageC: document.querySelector('#scroll-section-0 .main-message.c'),
        messageD: document.querySelector('#scroll-section-0 .main-message.d')
      },
      values: {
        messageA_opacity_in: [0, 1, { start: 0.1, end: 0.2 }],
        // messageB_opacity_in: [0, 1, { start: 0.3, end: 0.4 }],
        // messageC_opacity_in: [0, 1, { start: 0.5, end: 0.6 }],
        // messageD_opacity_in: [0, 1, { start: 0.7, end: 0.8 }],
        messageA_translateY_in: [20, 0, { start: 0.1, end: 0.2 }],
        // messageB_translateY_in: [20, 0, { start: 0.3, end: 0.4 }],
        // messageC_translateY_in: [20, 0, { start: 0.5, end: 0.6 }],
        // messageD_translateY_in: [20, 0, { start: 0.7, end: 0.8 }],
        messageA_opacity_out: [1, 0, { start: 0.25, end: 0.3 }],
        // messageB_opacity_out: [1, 0, { start: 0.45, end: 0.5 }],
        // messageC_opacity_out: [1, 0, { start: 0.65, end: 0.7 }],
        // messageD_opacity_out: [1, 0, { start: 0.85, end: 0.9 }],
        messageA_translateY_out: [0, -20, { start: 0.25, end: 0.3 }],
        // messageB_translateY_out: [0, -20, { start: 0.45, end: 0.5 }],
        // messageC_translateY_out: [0, -20, { start: 0.65, end: 0.7 }],
        // messageD_translateY_out: [0, -20, { start: 0.85, end: 0.9 }]
    
      }
    },
    {
      // 1
      type: 'normal',
      //heightNum: 5, // 노멀에서는  필요 없음
      scrollHeight: 0,
      objs: {
        container: document.querySelector('#scroll-section-1'),
        content: document.querySelector('#scroll-section-1 .description')
      }
    },
    {
      // 2
      type: 'sticky',
      heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅
      scrollHeight: 0,
      objs: {
        container: document.querySelector('#scroll-section-2'),
        messageA: document.querySelector('#scroll-section-2 .a'),
        messageB: document.querySelector('#scroll-section-2 .b'),
        messageC: document.querySelector('#scroll-section-2 .c'),
        pinB: document.querySelector('#scroll-section-2 .b .pin'),
        pinC: document.querySelector('#scroll-section-2 .c .pin')
      },
      values: {
        // messageA_translateY_in: [20, 0, { start: 0.15, end: 0.2 }],
        // messageB_translateY_in: [30, 0, { start: 0.6, end: 0.65 }],
        // messageC_translateY_in: [30, 0, { start: 0.87, end: 0.92 }],
        // messageA_opacity_in: [0, 1, { start: 0.25, end: 0.3 }],
        // messageB_opacity_in: [0, 1, { start: 0.6, end: 0.65 }],
        // messageC_opacity_in: [0, 1, { start: 0.87, end: 0.92 }],
        // messageA_translateY_out: [0, -20, { start: 0.4, end: 0.45 }],
        // messageB_translateY_out: [0, -20, { start: 0.68, end: 0.73 }],
        // messageC_translateY_out: [0, -20, { start: 0.95, end: 1 }],
        // messageA_opacity_out: [1, 0, { start: 0.4, end: 0.45 }],
        // messageB_opacity_out: [1, 0, { start: 0.68, end: 0.73 }],
        // messageC_opacity_out: [1, 0, { start: 0.95, end: 1 }],
        // pinB_scaleY: [0.5, 1, { start: 0.6, end: 0.65 }],
        // pinC_scaleY: [0.5, 1, { start: 0.87, end: 0.92 }]
    }
  
    },
    {
      // 3
      type: 'sticky',
      heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅
      scrollHeight: 0,
      objs: {
        container: document.querySelector('#scroll-section-3'),
        canvasCaption: document.querySelector('.canvas-caption')

      },
      values: {
        
      }
    }
  ];  

  function setLayout() {
    // 각 스크롤 섹션의 높이 세팅  
    for (let i = 0i < sceneInfo.lengthi++) {
      if (sceneInfo[i].type === 'sticky') {
        sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight;
      } else if (sceneInfo[i].type === 'normal') {
        sceneInfo[i].scrollHeight = sceneInfo[i].objs.container.offsetHeigh;
      }
        sceneInfo[i].objs.container.style.height = `${sceneInfo[i].scrollHeight}px`;
    }
    YOffset = window.pageYOffset;
    
    let totalScrollHeight = 0;
    for (let i = 0i < sceneInfo.lengthi++) {
        totalScrollHeight += sceneInfo[i].scrollHeight;
      if (totalScrollHeight >= YOffset) {
        currentScene = i
        break;
      }
    }
    document.body.setAttribute('id',`show-scene-${currentScene}`);
  }


  function calcValues(valuescurrentYOffset) {
    let rv;
    // 현재 씬(스크롤섹션)에서 스크롤된 범위를 비율로 구하기
    const scrollHeight = sceneInfo[currentScene].scrollHeight;
    const scrollRatio = currentYOffset / scrollHeight;

    if (values.length === 3) {
      // start ~ end 사이에 애니메이션 실행
      const partScrollStart = values[2].start * scrollHeight;
      const partScrollEnd = values[2].end * scrollHeight;
      const partScrollHeight = partScrollEnd - partScrollStart;

      if (currentYOffset >= partScrollStart && currentYOffset <= partScrollEnd) {
        rv = (currentYOffset - partScrollStart/ partScrollHeight * (values[1- values[0]) + values[0];
      } else if (currentYOffset < partScrollStart) {
        rv = values[0];
      } else if (currentYOffset > partScrollEnd) {
        rv = values[1];
      }
    } else {
      rv = scrollRatio * (values[1- values[0]) + values[0];
    }

    return rv;
  }

  function playAnimation() {
    const objs = sceneInfo[currentScene].objs;
    const values = sceneInfo[currentScene].values;
    const currentYOffset = yOffset - prevScrollHeight;
    const scrollHeight = sceneInfo[currentScene].scrollHeight;
    const scrollRatio =  currentYOffset / scrollHeight;
    switch (currentScene) { 
      case 0:
        if (scrollRatio <= 0.22) {
          //in
          objs.messageA.style.opacity = calcValues(values.messageA_opacity_in, currentYOffset);
          objs.messageA.style.transform = `translate3d(${calcValues(values.messageA_tranlateY_in, currentYOffset)}%)`;
        } else {
          //out
          objs.messageA.style.opacity = calcValues(values.messageA_opacity_out, currentYOffset);
          objs.messageA.style.transform = `translate3d(${calcValues(values.messageA_tranlateY_out, currentYOffset)}%)`;
        }
        //  if (scrollRatio <= 0.42) {
        //    // in
        //    objs.messageB.style.opacity = calcValues(values.messageB_opacity_in, currentYOffset);
        //    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_in, currentYOffset)}%, 0)`;
        // } else {
        //    // out
        //    objs.messageB.style.opacity = calcValues(values.messageB_opacity_out, currentYOffset);
        //    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_out, currentYOffset)}%, 0)`;
        // }

        // if (scrollRatio <= 0.62) {
        //    // in
        //    objs.messageC.style.opacity = calcValues(values.messageC_opacity_in, currentYOffset);
        //    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_in, currentYOffset)}%, 0)`;
        // } else {
        //    // out
        //    objs.messageC.style.opacity = calcValues(values.messageC_opacity_out, currentYOffset);
        //    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_out, currentYOffset)}%, 0)`;
        // }

        // if (scrollRatio <= 0.82) {
        //    // in
        //    objs.messageD.style.opacity = calcValues(values.messageD_opacity_in, currentYOffset);
        //    objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_in, currentYOffset)}%, 0)`;
        // } else {
        //    // out
        //    objs.messageD.style.opacity = calcValues(values.messageD_opacity_out, currentYOffset);
        //    objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_out, currentYOffset)}%, 0)`;
        // }
        
        break;
      case 1:
        // console.log('1 play');
        break;
      case 2:
      //  // console.log('2 play');
      //  if (scrollRatio <= 0.32) {
      //    // in
      //    objs.messageA.style.opacity = calcValues(values.messageA_opacity_in, currentYOffset);
      //    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_in, currentYOffset)}%, 0)`;
      // } else {
      //    // out
      //    objs.messageA.style.opacity = calcValues(values.messageA_opacity_out, currentYOffset);
      //    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_out, currentYOffset)}%, 0)`;
      // }

      // if (scrollRatio <= 0.67) {
      //    // in
      //    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_in, currentYOffset)}%, 0)`;
      //    objs.messageB.style.opacity = calcValues(values.messageB_opacity_in, currentYOffset);
      //    objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleY, currentYOffset)})`;
      // } else {
      //    // out
      //    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_out, currentYOffset)}%, 0)`;
      //    objs.messageB.style.opacity = calcValues(values.messageB_opacity_out, currentYOffset);
      //    objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleY, currentYOffset)})`;
      // }

      // if (scrollRatio <= 0.93) {
      //    // in
      //    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_in, currentYOffset)}%, 0)`;
      //    objs.messageC.style.opacity = calcValues(values.messageC_opacity_in, currentYOffset);
      //    objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleY, currentYOffset)})`;
      // } else {
      //    // out
      //    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_out, currentYOffset)}%, 0)`;
      //    objs.messageC.style.opacity = calcValues(values.messageC_opacity_out, currentYOffset);
      //    objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleY, currentYOffset)})`;
      // }

        break;
      case 3:
        //  // console.log('3 play');
        break;
    }
  }
  
  
  function scrollLoop() {
    enterNewScene = false;
    prevScrollHeight = 0;
    for (let i = 0i < currentScenei++) {
      prevScrollHeight += sceneInfo[i].scrollHeight;
    }
    if (yOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) {
      enterNewScene = true;
      currentScene++;
      document.body.setAttribute('id',`show-scene-${currentScene}`);
    }
    if (yOffset < prevScrollHeight) { 
      enterNewScene = true;
      if (currentScene === 0return// 브라우저 바온스 효과로 인해 마이너스가  되는 것을 방지(모바일)
      currentScene--;
      document.body.setAttribute('id',`show-scene-${currentScene}`);
    }
    if (currentScenereturn;
    playAnimation();
  }

  window.addEventListener('scroll'() => {
    yOffset = window.pageYOffset;
    scrollLoop();
  });
  window.addEventListener('load'setLayout);
  window.addEventListener('resize'setLayout);

})();
// HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>AirMug Pro</title>
  <!-- RESET CSS / STYLE CSS -->
  <link rel="stylesheet" href="css/default.css">
  <link rel="stylesheet" href="css/blank.css"> 
  <!-- 구글 폰트 -->
  <link rel="preconnect" href="https://fonts.gstatic.com">
  <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;900&display=swap" rel="stylesheet">
</head>
<body>
  <div class="container">
    <nav class="global-nav">
      <div class="global-nav-links">
        <a href="#none" class="global-nav-item">Rooms</a>
        <a href="#none" class="global-nav-item">Ideas</a>
        <a href="#none" class="global-nav-item">Stores</a>
        <a href="#none" class="global-nav-item">Contact</a>
      </div>
    </nav>
    <nav class="local-nav">
      <div class="local-nav-links">
        <a href="#none" class="product-name">AirMug Pro</a>
        <a href="#none">개요</a>
        <a href="#none">제품사양</a>
        <a href="#none">구입하기</a>
      </div>
    </nav>
    <section class="scroll-section" id="scroll-section-0">
      <h1>AirMugPro</h1>
      <div class="sticky-elem main-message a">
        <p>온전히 빠져들게 하는<br>최고급 세라믹</p>
      </div>
      <div class="sticky-elem main-message b">
        <p>주변 맛을 느끼게 해주는<br> 주면 맛 허용 모드</p>
      </div>
      <div class="sticky-elem main-message c">
        <p>온종일 편안한<br>맞춤형 손잡이</p>
      </div>
      <div class="sticky-elem main-message d">
        <p>새롭게 입가를<br>찾아온 매혹</p>
      </div>
    </section>

    <section class="scroll-section" id="scroll-section-1">
      <p class="description">
        <strong>보통 스크롤 영역</strong>
        Lorem ipsum dolor, sit amet consectetur adipisicing elit. Necessitatibus expedita, aliquam odio iste quasi fugit doloribus vero ab quaerat sunt, corrupti voluptatum officiis vitae nemo? Nostrum, doloremque eveniet. Vero, dicta facere optio sapiente assumenda ad cupiditate magnam repellendus sunt itaque nostrum beatae saepe esse ab sed ipsam ipsum consequatur, modi nam, veniam aliquid voluptas. Corporis ipsum praesentium non commodi veritatis, ad nobis? Recusandae sunt neque, ad odio illo non tempore impedit, tenetur itaque ipsum voluptatem! Asperiores deleniti fuga laboriosam quasi beatae nisi mollitia, quos modi incidunt temporibus assumenda in earum fugit et cumque sunt explicabo sit dignissimos quam ex ea aliquid qui alias veniam. Expedita repudiandae exercitationem eum. Eius distinctio aut quisquam expedita consequuntur eligendi quos excepturi maxime veritatis esse, porro, aliquam quod officiis natus vitae autem accusantium in perferendis? Sequi, odit doloremque fugiat repellat temporibus animi facere inventore dolorum, iusto pariatur similique consequatur culpa neque eligendi ab sapiente, facilis eum nostrum hic aperiam ad accusantium. Porro a non minima accusantium fugit mollitia ipsum dolorem molestias quod repellendus qui quibusdam deleniti quia officia ea, vero deserunt accusamus tempore, iure molestiae animi praesentium consequuntur totam rerum? Ex quod optio impedit. Unde quis eligendi optio voluptates ipsam est pariatur obcaecati debitis maxime!
      </p>
    </section>

    <section class="scroll-section" id="scroll-section-2">
      <div class="sticky-elem main-message a">
        <p>
          <small>편안한 촉감</small>
        입과 하나 되다
        </p>
      </div>
      <div class="sticky-elem desc-message b">
        <p>
        편안한 목넘김을 완성하는 디테일한 여러 구성 요소들, 우리는 이를 하나하나 새롭게 살피고 재구성하는 과정을 거쳐 새로운 수준의 머그, AirMug Pro를 만들었습니다. 입에 뭔가 댔다는 감각은 어느새 사라지고 오롯이 당신과 음료만 남게 되죠
        </p>
        <div class="pin"></div>
      </div>
        <div class="sticky-elem desc-message c">
        <p>
        디자인 앤 퀄리티 오브 스웨덴,<br>메이드 인 차이나
        </p>
        <div class="pin"></div>
      </div>
    </section>

    <section class="scroll-section" id="scroll-section-3">
      <p class="mid-message">
        <strong>Retina 머그</strong><br>
        아이디어를 광활하게 펼칠<br>
        아름답고 부드러운 음료 공간.      
      </p>
      <div class="canvas-caption">
        <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum provident aspernatur veniam sed assumenda, repellendus, necessitatibus et ipsa laudantium dignissimos blanditiis expedita id debitis, pariatur rerum iure nisi magni repellat quaerat totam explicabo veritatis similique praesentium. Dignissimos dolores expedita totam pariatur quis quae similique labore voluptates delectus ipsa veniam facere, officiis repellendus ipsam ab molestiae voluptas modi facilis eaque excepturi voluptatem fugit sed sapiente. Unde esse nostrum eos. Laboriosam eligendi repellat commodi ad, dolore accusantium similique eum beatae aspernatur. Nihil ex officia, quae ullam magnam quasi ea saepe corporis molestias magni maxime ab repudiandae praesentium, numquam amet porro minima eveniet, asperiores voluptates quam nemo hic deserunt. Ipsa praesentium, omnis similique fugiat voluptates animi explicabo illum mollitia sed magni? Quisquam aperiam laborum nostrum consequuntur dolor quidem minima amet pariatur repellendus aut eius, modi accusamus quasi. Quaerat nisi dolores maiores, animi optio quidem obcaecati quisquam, rerum maxime corrupti natus vitae voluptatibus totam! Provident suscipit, adipisci sed nisi illum minus non eius. Nisi perferendis vitae accusamus ipsa voluptatum sint necessitatibus asperiores quae fuga exercitationem? Quos odio saepe optio labore, officia modi perferendis doloribus provident nisi ratione repellat architecto atque aliquam neque consequatur eaque cupiditate? Rerum beatae obcaecati necessitatibus ipsa accusamus dolor nobis saepe.
      </p>
    </div>
    </section>
    <footer>
      <div class="footer">
      2021 김기운
    </div>
    </footer>
  </div>
  <script src="js/blank.js"></script>
</body>
</html>



svg 인터랙티브-웹 웹 디자인 javascript HTML/CSS 클론코딩

답변 2

1

1분코딩

js에서, messageA_tranlateY_inmessageA_tranlateY_out이라고 오타가 있는 부분이 있네요^^
Ctrl + F로 tranlate 라고 쓰신 부분을 찾아서, translate로 바꾸어주세요~ (s가 빠졌습니다)

0

radbenet

네 너무 감사합니다!

열심히 공부해서 마무리 짓겠습니다.

감사합니다!

이미지 배경 문의

0

65

1

[크로스브라우징] safari에서 동영상 영역 미노출

0

106

1

항상 궁금했는데 크림슨 컬러 선택하셨을때 활용했던 사이트 좀 알려주세요~

0

109

2

vue강의는안하시나요?!

0

100

1

스크롤 속도에 따른 messageA_opacity_out

0

115

1

drawImage(objs.videoImages[sequence], 0, 0); error

0

88

1

선생님 캔버스 width 크기는 이미지 크기에맞게 해줘야하나요?

0

126

0

선생님 안녕하세요. 혹시 메인개발(?)분야가 뭔지 궁금합니다.

0

206

1

React에서 load 상태를 어떻게 감지할 수 있을까요?

0

678

1

[섹션7-3: 버그수정 2] tempYOffset 오류

0

194

1

스크롤할 때 캔버스로 하신 이유가 있으신가요? 그냥 성능 떄문에 캔버스로 하신건가요?

0

312

2

게속 오류떠서 글 작성해봐요....

0

505

2

Vanilla JavaScript로 SPA 만드는 자료 혹은 선택 기준을 추천해주실 수 있으신가요?

1

488

1

특정 타이밍 스크롤 애니메이션 적용하기 섹션 수강중입니다.

0

455

2

[#svg, #이미지프레임과 텍스트 싱크] 스크롤 값에 움직이는 svg path, 이미지프레임과 텍스트 싱크 맞추는 것, 2가지 질문이 있습니다.

0

451

2

페이지가 처음 로딩 되었을 때 애니메이션 처리가 되지 않는 느낌입니다

0

430

1

섹션2 번째, opacity=0 되지 않고 잔상이 남습니다.

0

533

1

원래 쿼리셀렉터에서는 띄워쓰기 하면안되나요?

0

593

2

라이브러리 질문

1

412

2

translateY대신 애플에서 사용한 것 처럼 matrix로 scale의 크기를 주려고 하는데

0

409

1

[스크롤 높이 세팅] scrollHeight값이 3990아닌 4645로만 나오는데 뭐가 문제일까요? ㅠㅠ

0

597

2

scrollLoop 함수 질문

0

475

2

도메인 웹호스팅시 이미지가 안 뜨는데 누가 좀 알려주세요ㅠㅜ

0

1234

2

load 이벤트시 첫 비디오 이미지가 뜨네요.

0

504

2