인프런 커뮤니티 질문&답변

LIZ.B님의 프로필 이미지

작성한 질문수

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

main.js 적용 내용

main.js 적용내용 강좌에서 에러가 나서 문의 드려요~

해결된 질문

작성

·

293

0

(() => {
    let yOffset = 0;  //window.pageyOffset
    let prevScrollHeight = 0// 현재 스크롤 위치(yOffset)보다 이전에 위치한 스크롤 섹션들의 스크롤 높이값의 합
    let currentScene = 0// 현재 활성화된(눈 앞에 보고있는) 씬(scroll-section)
    let enterNewScene = false//새로운 scene이 시작된 순간

    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: [01, { start: 0.1end: 0.2 }],
                messageB_opacity_in: [01, { start: 0.3end: 0.4 }],
                messageC_opacity_in: [01, { start: 0.5end: 0.6 }],
                messageD_opacity_in: [01, { start: 0.7end: 0.8 }],
                messageA_translateY_in: [200, { start: 0.1end: 0.2 }],
                messageB_translateY_in: [200, { start: 0.3end: 0.4 }],
                messageC_translateY_in: [200, { start: 0.5end: 0.6 }],
                messageD_translateY_in: [200, { start: 0.7end: 0.8 }],
                messageA_opacity_out: [10, { start: 0.25end: 0.3 }],
                messageB_opacity_out: [10, { start: 0.45end: 0.5 }],
                messageC_opacity_out: [10, { start: 0.65end: 0.7 }],
                messageD_opacity_out: [10, { start: 0.85end: 0.9 }],
                messageA_translateY_out: [0, -20, { start: 0.25end: 0.3 }],
                messageB_translateY_out: [0, -20, { start: 0.45end: 0.5 }],
                messageC_translateY_out: [0, -20, { start: 0.65end: 0.7 }],
                messageD_translateY_out: [0, -20, { start: 0.85end: 0.9 }]

            }

        },
        {
            // 1
            type:'normal',
            heightNum:5,//브라우저 높이의 5배로 scrollHeight 세팅
            scrollHeight :0,
            objs:{
                container:document.querySelector('#scroll-section-1')
            }

        },
        {
            // 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: [200, { start: 0.15end: 0.2 }],
                messageB_translateY_in: [300, { start: 0.6end: 0.65 }],
                messageC_translateY_in: [300, { start: 0.87end: 0.92 }],
                messageA_opacity_in: [01, { start: 0.25end: 0.3 }],
                messageB_opacity_in: [01, { start: 0.6end: 0.65 }],
                messageC_opacity_in: [01, { start: 0.87end: 0.92 }],
                messageA_translateY_out: [0, -20, { start: 0.4end: 0.45 }],
                messageB_translateY_out: [0, -20, { start: 0.68end: 0.73 }],
                messageC_translateY_out: [0, -20, { start: 0.95end: 1 }],
                messageA_opacity_out: [10, { start: 0.4end: 0.45 }],
                messageB_opacity_out: [10, { start: 0.68end: 0.73 }],
                messageC_opacity_out: [10, { start: 0.95end: 1 }],
                pinB_scaleY: [0.51, { start: 0.6end: 0.65 }],
                pinC_scaleY: [0.51, { start: 0.87end: 0.92 }]

            }

        },
        {
            // 3
            type:'sticky',
            heightNum:5,//브라우저 높이의 5배로 scrollHeight 세팅
            scrollHeight :0,
            objs:{
                container:document.querySelector('#scroll-section-3'),
                canvasCaption:document.querySelector('.canvas-caption')
            },
            valeus:{
                canvasCaption_opacity: [ 01, { start: 0end: 0 } ],
                canvasCaption_translateY: [ 200, { start: 0end: 0 } ]
            }


        },
    ]


    function setLayout(){
        //각 스크롤 섹션의 높이 세팅
        for(let i =0 ; i<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.offsetHeight;
            }
            sceneInfo[i].objs.container.style.height =`${sceneInfo[i].scrollHeight}px`;
        }
        console.log(sceneInfo);
        yOffset = window.pageYOffset;
        let totalScrollHeight =0;
        for(let i =0;i<sceneInfo.length;i++){
            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 / sceneInfo[currentScene].scrollHeight;
        if(values.length===3){
            //start
            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{
            //end
            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;

        // console.log(currentScene);
        switch (currentScene){
            case 0:
          
                if(scrollRatio <= 0.22){
                    //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.42) {
                    // in
                    objs.messageB.style.opacity = calcValues(values.messageB_opacity_incurrentYOffset);
                    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_incurrentYOffset)}%, 0)`;
                } else {
                    // out
                    objs.messageB.style.opacity = calcValues(values.messageB_opacity_outcurrentYOffset);
                    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_outcurrentYOffset)}%, 0)`;
                }
                if (scrollRatio <= 0.62) {
                    // in
                    objs.messageC.style.opacity = calcValues(values.messageC_opacity_incurrentYOffset);
                    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_incurrentYOffset)}%, 0)`;
                } else {
                    // out
                    objs.messageC.style.opacity = calcValues(values.messageC_opacity_outcurrentYOffset);
                    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_outcurrentYOffset)}%, 0)`;
                }

      
                break;
            case 1:
                // console.log('1 play');
                break;
            case 2:
                // console.log('2 play');
                break;
            case 3:
                // console.log('3 play');
                break;
                           
        }
    }



    function scrollLoop(){
        enterNewScenefalse;
        prevScrollHeight = 0;
       for(let i=0;i<currentScene;i++){
           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(enterNewScenereturn;
       playAnimation();
    }

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


0.62 scrollRatio 에서 에러가 나서 문의 드려요.
main.js:187 Uncaught TypeError: Cannot read property 'style' of null

답변 2

1

1분코딩님의 프로필 이미지
1분코딩
지식공유자

objs.messageC를 가져오지 못해서 발생하는 에러일 것 같은데요,
올려주신 스크립트를 적용해보니 문제는 없는 것 같아요~
아무래도 직접 작성하신 html에 해당 클래스가 다르게 적용되어있지 않을까 싶은데,
아래 부분처럼 되어있는지 한번 확인 부탁드릴게요~

<div class="sticky-elem main-message c">
    <p>온종일 편안한<br>맞춤형 손잡이</p>
</div>

아니면, html도 함께 올려주시면 좋을 것 같습니다^^

0

LIZ.B님의 프로필 이미지
LIZ.B
질문자

넵 수정해보도록 할께요~ 감사합니다~~~~

LIZ.B님의 프로필 이미지

작성한 질문수

질문하기