미해결
애플 웹사이트 인터랙션 클론!
안녕하세요 선생님. 강의 너무 유용하고 재밌게 듣고 있습니다. 자꾸 오류가 뜨는데 무슨 문젠지 모르겠어서 너무 답답해서 질문 남깁니다.ㅠㅠ opacity가 정의되어 있지 않다그러고 Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas) 이런 오류가 뜨네요.. 분명 캔버스로 잘 정의한 것 같 은데요...ㅠㅠㅠㅠㅠ 분명 선생님을 다 따라 쳤는데도 어디서 문제가 생긴건지 모르겠습니다.. 도와주시면 감사하겠습니다.흑흑 ( () => { let yOffset = 0 ; // window.pageYOffset 대신 쓸 변수 let prevScrollHeight = 0 ; // 현재 스크롤 위치 (yOffset) 보다 이전에 위치한 스크롤 섹션들의 스크롤 높이 합 let currentScene = 0 ; // 현재 활성화 된(눈 앞에 보고 있는) 씬 (scroll-section) let enterNewScene = false ; // 새로운 씬이 시작 된 순간 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 ' ) , canvas : document . querySelector ( ' #video-canvas-0 ' ) , context : document . querySelector ( ' #video-canvas-0 ' ) . getContext ( ' 2d ' ) , videoImages : [] , }, values : { videoImageCount : 300 , imageSequence : [ 0 , 299 ] , canvas_opacity : [ 1 , 0 , { start : 0.8 , end : 1 } ] , 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, // type normal에서는 필요없음 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 ' ) , canvas : document . querySelector ( ' #video-canvas-1 ' ) , context : document . querySelector ( ' #video-canvas-1 ' ) . getContext ( ' 2d ' ) , videoImages : [] , }, values : { videoImageCount : 960 , imageSequence : [ 0 , 959 ] , canvas_opacity_in : [ 0 , 1 , { start : 0 , end : 0.1 } ] , canvas_opacity_out : [ 1 , 0 , { start : 0.95 , end : 1 } ] , 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 setCanvasImages () { let imgElem ; for ( let i = 0 ; i < sceneInfo [ 0 ] . values . videoImageCount ; i ++ ) { imgElem = new Image () ; // imgElem = document.createElement('img'); imgElem . src = ` ./video/001/IMG_ ${ 6726 + i } .JPG ` ; sceneInfo [ 0 ] . objs . videoImages . push ( imgElem ) ; } let imgElem2 ; for ( let i = 0 ; i < sceneInfo [ 0 ] . values . videoImageCount ; i ++ ) { imgElem2 = new Image () ; // imgElem = document.createElement('img'); imgElem2 . src = ` ./video/002/IMG_ ${ 7027 + i } .JPG ` ; sceneInfo [ 2 ] . objs . videoImages . push ( imgElem2 ) ; } } function setLayout () { // 각 스크롤 섹션의 높이 세팅 for ( let i = 0 ; i < 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 = 0 ; i < sceneInfo . length ; i ++ ) { // 새로고침 해도 씬이 고정되게 세팅 totalScrollHeight += sceneInfo [ i ] . scrollHeight ; if ( totalScrollHeight >= yOffset ) { currentScene = i ; break ; } } document . body . setAttribute ( ' id ' , ` show-scene- ${ currentScene }` ) ; const heightRatio = window . innerHeight / 1000 ; // 캔버스 원래 height = 1000 sceneInfo [ 0 ] . objs . canvas . style . transform = ` scale( ${ heightRatio } ) translate(-50%,-50%) ` ; sceneInfo [ 2 ] . objs . canvas . style . transform = ` scale( ${ heightRatio } ) translate(-50%,-50%) ` ; } function calcValues ( values , currentYOffset ) { let rv ; // 현재 씬(스크롤섹션)에서 스크롤 된 범위를 0~1 사이의 비율로 구하기 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 : let sequence = Math . round ( calcValues ( values . imageSequence , currentYOffset ) ) ; objs . context . drawImage ( objs . videoImages [ sequence ] , 0 , 0 ) ; objs . canvas . style . opacity = calcValues ( values . canvas_opacity , currentYOffset ) ; 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_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 2 : let sequence2 = Math . round ( calcValues ( values . imageSequence , currentYOffset ) ) ; objs . context . drawImage ( objs . videoImages [ sequence2 ] , 0 , 0 ) ; if ( scrollRatio <= 0.5 ) { // in objs . context . style . opacity = calcValues ( values . canvas_opacity_in , currentYOffset ) ; } else { // out objs . context . style . opacity = calcValues ( values . canvas_opacity_out , currentYOffset ) ; } 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 : break ; } } function scrollLoop () { enterNewScene = false ; 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 === 0 ) return ; // 브라우저 바운스 효과로 인해 마이너스가 되는 것을 방지 (모바일) currentScene --; document . body . setAttribute ( ' id ' , ` show-scene- ${ currentScene }` ) ; } if ( enterNewScene ) return ; playAnimation () ; } // window.addEventListener('DOMcontentLoaded', setLayout) // 이미지가 업로드 되기 전에 실행 window . addEventListener ( ' scroll ' , () => { yOffset = window . pageYOffset ; scrollLoop () ; } ) ; window . addEventListener ( ' load ' , () => { setLayout () ; sceneInfo [ 0 ] . objs . context . drawImage ( sceneInfo [ 0 ] . objs . videoImages [ 0 ] , 0 , 0 ) ; } ) ; window . addEventListener ( ' resize ' , setLayout ) ; setCanvasImages () ; } )() ;
HTML/CSS javascript 인터랙티브-웹 웹 디자인 svg 클론코딩
우왕
2020-09-30T19:04:15.640Z
댓글 1
좋아요 0
조회수 285