inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

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

두 가지 에러들 해결방법을 모르겠습니다 ㅜ

198

대림대

작성한 질문수 1

0

안녕하세요. 강의 잘 듣고있습니다 !

그런데 콘솔창에 아래 이미지 처럼 에러가 떠서 질문 드립니다.

스크롤을 내릴때는 뜨지 않다가 전부 다 내리고 다시 올려보면 저렇게 에러가 뜹니다. 작동은 됩니다.. (스크롤 비디오 처리 부분)

혹시 빼먹은게 있나 강의도 여러번 다시 보았는데 해결이 나지 않아서 질문 드립니다 ..ㅜㅜ

-----

그리고 또 한가지가 있는데,  show scene1 에서 show scene2로 넘어갈때 아래 이미지가 잠깐 뜨고 사라집니다.

 

강의에서는 저와 다른 텍스트만 잠깐 뜨고 사라져서 css에서 수정하는것을 보았는데 저의 경우에는 위의 이미지처럼 저 텍스트와 이미지가 잠깐 떴다가 사라져서 이것도 해결책을 잘 모르겠습니다ㅠ

완성본에서는 콘솔창에 에러 뜨는 현상도 전혀 없고 잘 작동 됩니다.

제 코드에 문제가 있는건데 html과 css에는 문제가 없는거 같습니다..  (완성본에 적용해보았습니다)

강의는 두번째 스크롤 비디오 처리까지 들었습니다!

-----

아래는 현재 제 코드입니다.

(()=>{

    let yOffset = 0// window.pageYOffset 대신 쓸 변수
    let prevScrollHeight = 0// 현재 스크롤 위치(yoffset)보다 이전에 위치한 스크롤 섹션들의 스크롤 높이 값의 합
    let currentScene = 0// 현재 활성화된(눈 앞에 보고 있는) 씬(scroll-section)

    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'),
                canvas: document.querySelector('#video-canvas-0'),
                context: document.querySelector('#video-canvas-0').getContext('2d'),
                videoImages: []
            },
            values: {
                videoImagesCount: 300,
                imageSequence: [0299],
                canvas_opacity: [10, { start: 0.9, end: 1}],
                messageA_opacity_in: [01, { start: 0.1, end: 0.2 }],
                messageB_opacity_in: [01, { start: 0.3, end: 0.4 }],
                messageC_opacity_in: [01, { start: 0.5, end: 0.6 }],
                messageD_opacity_in: [01, { start: 0.7, end: 0.8 }],
                messageA_translateY_in: [200, { start: 0.1, end: 0.2 }],
                messageB_translateY_in: [200, { start: 0.3, end: 0.4 }],
                messageC_translateY_in: [200, { start: 0.5, end: 0.6 }],
                messageD_translateY_in: [200, { start: 0.7, end: 0.8 }],
                messageA_opacity_out: [10, { start: 0.25, end: 0.3 }],
                messageB_opacity_out: [10, { start: 0.45, end: 0.5 }],
                messageC_opacity_out: [10, { start: 0.65, end: 0.7 }],
                messageD_opacity_out: [10, { 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, // type normal에서는 필요 없음
            scrollHeight: 0,
            objs: {
                container: document.querySelector('#scroll-section-1')
            }
        },
        {
            // 2
            type: 'sticky',
            heightNum: 5,
            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'),
                canvas: document.querySelector('#video-canvas-1'),
                context: document.querySelector('#video-canvas-1').getContext('2d'),
                videoImages: []
            },
            values: {
                videoImagesCount: 960,
                imageSequence: [0959],
                canvas_opacity_in: [01, { start: 0, end: 0.1 }],
                canvas_opacity_out: [10, { start: 0.95, end: 1 }],
                messageA_translateY_in: [200, { start: 0.15, end: 0.2 }],
                messageB_translateY_in: [300, { start: 0.6, end: 0.65 }],
                messageC_translateY_in: [300, { start: 0.87, end: 0.92 }],
                messageA_opacity_in: [01, { start: 0.25, end: 0.3 }],
                messageB_opacity_in: [01, { start: 0.6, end: 0.65 }],
                messageC_opacity_in: [01, { 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: [10, { start: 0.4, end: 0.45 }],
                messageB_opacity_out: [10, { start: 0.68, end: 0.73 }],
                messageC_opacity_out: [10, { start: 0.95, end: 1 }],
                pinB_scaleY: [0.51, { start: 0.6, end: 0.65 }],
                pinC_scaleY: [0.51, { start: 0.87, end: 0.92 }]
            }
        },
        {
            // 3
            type: 'sticky',
            heightNum: 5,
            scrollHeight: 0,
            objs: {
                container: document.querySelector('#scroll-section-3'),
                canvasCaption: document.querySelector('.canvas-caption')
            },
            values: {
    
            }
        }
    ];

    function setCanvasImages() {
        let imgElem;
        for ( let i = 0i < sceneInfo[0].values.videoImagesCounti++) {
            imgElem = new Image();
            // = imgElems = document.createElement('img');
            imgElem.src = `./video/001/IMG_${6726 + i}.JPG`;
            sceneInfo[0].objs.videoImages.push(imgElem);
        }

        let imgElem2;
        for ( let i = 0i < sceneInfo[2].values.videoImagesCounti++) {
            imgElem2 = new Image();
            // = imgElems = document.createElement('img');
            imgElem2.src = `./video/002/IMG_${7027 + i}.JPG`;
            sceneInfo[2].objs.videoImages.push(imgElem2);
        }
        // console.log(sceneInfo[0].objs.videoImages);
    }
    setCanvasImages();

    function setLayout() {
        // 각 스크롤 섹션의 높이 세팅
        for (let i = 0i < sceneInfo.length; i++) {
            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`;
        }

        yOffset = window.pageYOffset;

        let totalScrollHeight = 0;
        for ( let i = 0i < sceneInfo.length; i++) {
            totalScrollHeight += sceneInfo[i].scrollHeight;
            if (totalScrollHeight >= yOffset) {
                currentScene = i;
                break;
            }
        }
        document.body.setAttribute('id'`show-scene-${currentScene}`);

        const heightRatio = window.innerHeight / 1080;
        sceneInfo[0].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`;
        sceneInfo[2].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`;

        // console.log(sceneInfo);
    }

    function calcValues(values, currentYOffset) {
        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:
                // console.log('0 play');

                let sequence = Math.round(calcValues(values.imageSequencecurrentYOffset));
                // console.log(sequence);
                objs.context.drawImage(objs.videoImages[sequence], 00);
                objs.canvas.style.opacity = calcValues(values.canvas_opacitycurrentYOffset);

                if (scrollRatio <= 0.22) {
                    // in
                    objs.messageA.style.opacity = calcValues(values.messageA_opacity_incurrentYOffset);
                    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_incurrentYOffset)}%, 0)`;
                } else {
                    // out
                    objs.messageA.style.opacity = calcValues(values.messageA_opacity_outcurrentYOffset);
                    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_outcurrentYOffset)}%, 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)`;
                }
    
                if (scrollRatio <= 0.82) {
                    // in
                    objs.messageD.style.opacity = calcValues(values.messageD_opacity_incurrentYOffset);
                    objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_incurrentYOffset)}%, 0)`;
                } else {
                    // out
                    objs.messageD.style.opacity = calcValues(values.messageD_opacity_outcurrentYOffset);
                    objs.messageD.style.transform = `translate3d(0, ${calcValues(values.messageD_translateY_outcurrentYOffset)}%, 0)`;
                }
    
                break;
    
            case 2:
                // console.log('2 play');
                let sequence2 = Math.round(calcValues(values.imageSequencecurrentYOffset));
                objs.context.drawImage(objs.videoImages[sequence2], 00);

                if (scrollRatio <= 0.5) {
                    objs.canvas.style.opacity = calcValues(values.canvas_opacity_incurrentYOffset);
                } else {
                    objs.canvas.style.opacity = calcValues(values.canvas_opacity_outcurrentYOffset);
                }

                if (scrollRatio <= 0.32) {
                    // in
                    objs.messageA.style.opacity = calcValues(values.messageA_opacity_incurrentYOffset);
                    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_incurrentYOffset)}%, 0)`;
                } else {
                    // out
                    objs.messageA.style.opacity = calcValues(values.messageA_opacity_outcurrentYOffset);
                    objs.messageA.style.transform = `translate3d(0, ${calcValues(values.messageA_translateY_outcurrentYOffset)}%, 0)`;
                }
    
                if (scrollRatio <= 0.67) {
                    // in
                    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_incurrentYOffset)}%, 0)`;
                    objs.messageB.style.opacity = calcValues(values.messageB_opacity_incurrentYOffset);
                    objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleYcurrentYOffset)})`;
                } else {
                    // out
                    objs.messageB.style.transform = `translate3d(0, ${calcValues(values.messageB_translateY_outcurrentYOffset)}%, 0)`;
                    objs.messageB.style.opacity = calcValues(values.messageB_opacity_outcurrentYOffset);
                    objs.pinB.style.transform = `scaleY(${calcValues(values.pinB_scaleYcurrentYOffset)})`;
                }
    
                if (scrollRatio <= 0.93) {
                    // in
                    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_incurrentYOffset)}%, 0)`;
                    objs.messageC.style.opacity = calcValues(values.messageC_opacity_incurrentYOffset);
                    objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleYcurrentYOffset)})`;
                } else {
                    // out
                    objs.messageC.style.transform = `translate3d(0, ${calcValues(values.messageC_translateY_outcurrentYOffset)}%, 0)`;
                    objs.messageC.style.opacity = calcValues(values.messageC_opacity_outcurrentYOffset);
                    objs.pinC.style.transform = `scaleY(${calcValues(values.pinC_scaleYcurrentYOffset)})`;
                }
    
                break;
    
            case 3:
                // console.log('3 play');
                break;
        }
    }

    function scrollLoop() {
        prevScrollHeight = 0;
        for (let i = 0i < currentScenei++) {
            prevScrollHeight = prevScrollHeight + sceneInfo[i].scrollHeight// +=를 사용하고 뒤에 prevScrollHeight 지워도 동일
        }

        if(yOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) {
            currentScene++;
            document.body.setAttribute('id'`show-scene-${currentScene}`);
        }

        if(yOffset < prevScrollHeight) {
            if (currentScene === 0return// 브라우저 바운스 효과로 인해 마이너스가 되는것을 방지
            currentScene--;
            document.body.setAttribute('id'`show-scene-${currentScene}`);
        }
        playAnimation();
    }

    window.addEventListener('scroll', () => {
        yOffset = window.pageYOffset;
        scrollLoop();
    });

    window.addEventListener('load', () => {
        setLayout();
        sceneInfo[0].objs.context.drawImage(sceneInfo[0].objs.videoImages[0], 00);
    });
    window.addEventListener('resize'setLayout);
    setLayout();

})();


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

답변 2

1

1분코딩

두가지 버그 모두, 진도를 더 나가시면 자연스럽게 해결될 에러들인데요,
일단 첫번째 에러의 경우 drawImage에서 그릴 이미지 소스에 데이터가 제대로 안들어갈 경우에 이런 에러가 발생합니다.
스크롤 값에 따라 계산되는 맨 끝 인덱스에 오차가 있는 경우가 있어서 발생하는 현상인데, 아래처럼 그려줄 이미지가 있을 경우에만 실행하도록 해주시면 예방할 수 있습니다.

objs.context.drawImage(objs.videoImages[sequence], 0, 0);
// 이 부분과

objs.context.drawImage(objs.videoImages[sequence2], 0, 0);
// 이 부분을
// 각각 아래처럼 바꾸어 주세요

if (objs.videoImages[sequence]) {
	objs.context.drawImage(objs.videoImages[sequence], 0, 0);
}

if (objs.videoImages[sequence2]) {
	objs.context.drawImage(objs.videoImages[sequence2], 0, 0);
}

씬이 바뀌는 중간에 잠깐 이미지가 나타나는 문제 역시, 스크롤값 기반으로 계산하다보니 씬이 바뀌는 순간 발생하는 버그인데
진도 나가다보면 해결하는 부분이 나온답니다. enterNewScene이라는 변수를 두고, 새로운 씬으로 진입 시에는 그려주지 않도록 하는 식으로 처리하고 있습니다^^

0

대림대

아하 뒤에 나와있었군요 하하;;;;;; 감사합니다!! ^^

이미지 배경 문의

0

67

1

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

0

106

1

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

0

109

2

vue강의는안하시나요?!

0

101

1

스크롤 속도에 따른 messageA_opacity_out

0

115

1

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

0

89

1

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

0

127

0

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

0

206

1

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

0

679

1

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

0

195

1

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

0

313

2

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

0

506

2

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

1

488

1

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

0

455

2

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

0

451

2

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

0

431

1

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

0

533

1

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

0

593

2

라이브러리 질문

1

412

2

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

0

409

1

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

0

598

2

scrollLoop 함수 질문

0

476

2

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

0

1235

2

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

0

506

2