월 15,400원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결애플 웹사이트 인터랙션 클론!
홈페이지에 소스 적용시 오류가 몇개 발생합니다.
적용한 페이지 : http://phonesawa.co.kr/page/index?tpl=etc%2Fvisual.html 안녕하세요 강좌 잘 보고 있습니다. 다름이 아니라 소스코드를 홈페이지에 맞게 (URL 등) 일부분 수정하여 적용을 해보았는데요 ! 몇가지 문제점이 발생하여 질문을 남기게 되었습니다. 1. 홈페이지의 헤더 영역 부분을 밀고 올라와서 보여지는 문제 2. 하단으로 스크롤을 하다가 스크롤을 멈추게 되면 서서히 상단으로 올라가는 문제 위의 두 부분은 어떻게 수정을 해야 할까요 ? 답변좀 부탁드리겠습니다.
- 미해결애플 웹사이트 인터랙션 클론!
스크롤하이트가 정의되지않았다고 에러뜨는데 왜일까요,,??
(() => { 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, imageSequenc: [0, 299], canvas_opacity: [1, 0, {start: 0.9, 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 }], // 20=> translateY를 20%만큼 조정, %는 밑에 playAnimation()에서 붙여줄 거임 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, imageSequenc: [0, 959], canvas_opacity: [1, 0, { start: 0.9, 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[2].values.videoImageCount; i++) { imgElem2 = new Image(); 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 / 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})`; // translate3d로 가운데 정렬 후 scale로 이미지 크기 조정 } 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 = yOffset / 현재 씬의 scrollHeight; const scrollRatio = currentYOffset / scrollHeight; switch (currentScene) { case 0: // console.log('0 play'); let sequence = Math.round(calcValues(values.imageSequenc, 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: // console.log('2 play'); let sequence2 = Math.round(calcValues(values.imageSequenc, currentYOffset)); objs.context.drawImage(objs.videoImages[sequence2], 0, 0); 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 = 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('scroll', () => { yOffset = window.pageYOffset; scrollLoop(); }); // window.addEventListener('DOMcontentLoaded', setLayout) 이미지가 업로드 되기 전에 실행 window.addEventListener('load', () => { setLayout(); sceneInfo[0].objs.context.drawImage(sceneInfo[0].objs.videoImages[0], 0, 0); }); window.addEventListener('resize', setLayout); setCanvasImages(); })();
- 애플 웹사이트 인터랙션 클론!
안녕하세요 에러가 나오는데 어떻게 해결해야되나요?
삭제된 글입니다
- 미해결애플 웹사이트 인터랙션 클론!
두번째 비디오에서 새로고침
안녕하세요 선생님:) 사이트 완성하고 이리저리 눌러보고 새로고침하고 해보는데, 스크롤 끝까지 내렸다가 올렸다가 하다가 두번째 비디오(desc-message) 나오는 부분에서 새로고침할 때 어떨때는 잘 나오다가 어떨때는 맨 마지막에 하단 콘텐츠 추가 부분이 나오는데 버그일까요? 코드를 보내드려야하나욥?ㅠㅠ 제껄로도 테스트해보고, 다운로드 받은 완성파일(7번째 알집)에서 하단 콘텐츠랑 css만 추가해서 테스트해봐도 새로고침에 잘 됐다 안됐다해가지구요 ㅠㅠ
- 미해결애플 웹사이트 인터랙션 클론!
1024px 이하에서 desc-message width 반영 오류
질문을 작성해놓고 모르고 삭제해버렸어요 ㅠㅠ 제목 그대로 desc-message가 화면 1024px미만에서는 width 50%가 적용되어야하는데 적용이 안되더라구요. 그래서 main-message처럼 #scroll-section-2 .main-message 앞에 #scroll-section-2 붙이니 잘 적용이 되더라구요. 혹시 css 작성할 때 부모 언급해야하는 경우와 아닌 경우 알려주실 수 있으실까요?🙏🙏 위와 같은 오류가 종종 발생하는데 제가 원인을 찾지 못해서 부모를 언급해서 css를 작성하니 코드가 길어질 때가 많아서요 ㅠㅠ
- 미해결애플 웹사이트 인터랙션 클론!
안녕하세요. 실행 오류가 뜨는데 질문드립니다
(() => { let yOffset = 0; //window.pageOffset 대신 쓸 수 있는 변수 let prevScrollHeight = 0 // 현재 스크롤 (yOffset)보다 이전에 위치한 스크롤 높이값의 함 let currentScene = 0; // 현재 활성화된 (눈앞에 보고 있는) 씬(scroll-section) let enterNewScene = false; 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_translate_in: [20, 0, { start: 0.1, end: 0.2 }], messageB_translate_in: [20, 0, { start: 0.3, end: 0.4 }], messageC_translate_in: [20, 0, { start: 0.5, end: 0.6 }], messageD_translate_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_translate_out: [0, -20, { start: 0.25, end: 0.3 }], messageA_translate_out: [0, -20, { start: 0.45, end: 0.5 }], messageA_translate_out: [0, -20, { start: 0.65, end: 0.7 }], messageA_translate_out: [0, -20, { start: 0.85, end: 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: [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') } }, ]; function setLayout() { // 각 section 의 높이 세팅 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` } let totalScrollHeight = 0; yOffset = window.pageYOffset; // 새로고침 버튼 눌렀을때 그 씬 장면이 유지 될 수 있게 해주는 역할 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(values, currentYOffset) { let rv; //현재 씬(스크롤 섹션)애서 스크롤된 범위를 비율로 구하기 const scrollHeight = sceneInfo[currentScene].scrollHeight; const scrollRatio = currentYOffset / scrollHeight; if (values.length === 3) { // start ~ end 사이에 애니메이션 진행 const partStart = values[2].start * scrollHeight const partEnd = values[2].end * scrollHeight const partScrollHeight = partEnd - partStart; if (currentYOffset <= partEnd && currentYOffset >= partStart) { rv = (currentYOffset - partStart) / partScrollHeight * (values[1] - values[0]) + values[0]; } else if (currentYOffset < partStart) { rv = values[0]; } else if (currentYOffset > partEnd) { rv = values[1]; } } else { rv = scrollRatio * (values[1] - values[0]) + values[0]; } return rv; } function playAinmation() { 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: // calcValues = (values의 선명도, 현재 스크롤의 위치 if (scrollRatio <= 0.22) { // in objs.messageA.style.opacity = calcValues(values.messageA_opacity_in, currentYOffset); objs.messageA.style.transform = `translateY(${calcValues(values.messageA_translate_in, currentYOffset)}%)`; } else { // out objs.messageA.style.opacity = calcValues(values.messageA_opacity_out, currentYOffset); objs.messageA.style.transform = `translateY(${calcValues(values.messageA_translate_out, currentYOffset)}%)`; } if (scrollRatio <= 0.42) { objs.messageB.style.opacity = calcValues(values.messageB_opacity_in, currentYOffset); objs.messageB.style.transform = `translateY(${calcValues(values.messageB_translate_in, currentYOffset)}%)` } else { objs.messageB.style.opacity = calcValues(values.messageB_opacity_out, currentYOffset); objs.messageB.style.transform = `translateY(${calcValues(values.messageB_translate_out, currentYOffset)}%)`; } if (scrollRatio <= 0.62) { objs.messageC.style.opacity = calcValues(values.messageC_opacity_in, currentYOffset); objs.messageC.style.transform = `translateY(${calcValues(values.messageC_translate_in, currentYOffset)}%)` } else { objs.messageC.style.opacity = calcValues(values.messageC_opacity_out, currentYOffset); objs.messageC.style.transform = `translateY(${calcValues(values.messageC_translate_out, currentYOffset)}%)`; } if (scrollRatio <= 0.82) { objs.messageD.style.opacity = calcValues(values.messageD_opacity_in, currentYOffset); objs.messageD.style.transform = `translateY(${calcValues(values.messageD_translate_in, currentYOffset)}%)` } else { objs.messageD.style.opacity = calcValues(values.messageD_opacity_out, currentYOffset); objs.messageD.style.transform = `translateY(${calcValues(values.messageD_translate_out, currentYOffset)}%)`; } break; case 1: break; case 2: 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; playAinmation() } window.addEventListener('scroll', () => { yOffset = window.pageYOffset; scrollLoop() }); window.addEventListener('resize', setLayout); window.addEventListener('load', setLayout); })()
- 미해결애플 웹사이트 인터랙션 클론!
id를 통한 display: none 을 block 으로 변경 시 적용 문제
안녕하세요. 강의를 수강하는 학생입니다. document.body.setAttribute 를 이용하여 scene 을 보이게 하는데 있어서 문제가 생겨 문의를드립니다. display:none이 block으로 변경되는 부분에 있어서 잘되지 않아 질문을 올려봅니다. 해당문제 아래와 같이 깃헙 주소로 공유해봅니다. https://github.com/Mr-SY/CloneAppleSite 확인 바랍니다! 감사합니다!
- 미해결애플 웹사이트 인터랙션 클론!
씬마다 currentScene 바뀌는 시점이 제각각이예요;
빨간 테두리도 메인화면에서 브라우저에 선생님처럼 꽉 차게 나오지 않고.. 어떤 씬은 맞게 바뀌고 어떤 씬은 따로 바뀌고 제각각인데 왜이런거죠ㅠ //js코드 (() => { let yOffset = 0; let prevScrollHeight = 0; // 현재 스크롤 위치(yOffset)보다 이전에 위치한 스크롤 섹션들의 스크롤 높이 합 let currentScene = 0; // 현재 활성화된 scroll-section const sceneInfo = [ { // currentScene 0 type: 'sticky', heightNum: 5, // 브라우저 높이의 5배로 총 scrollHeight 세팅 scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-0') } }, { // currentScene 1 type: 'normal', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-1') } }, { // currentScene 2 type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-2') } }, { // currentScene 3 type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-3') } } ]; function setLayout() { // 각 스크롤 섹션의 높이 세팅 prevScrollHeight = 0; for(let i=0; i<sceneInfo.length; i++) { sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight; sceneInfo[i].objs.container.style.height = `${sceneInfo[i].scrollHeight}px`; } } function scrollLoop() { prevScrollHeight = 0; for(let i=0; i<currentScene; i++) { prevScrollHeight += sceneInfo[i].scrollHeight; } if (yOffset > sceneInfo[currentScene].scrollHeight + prevScrollHeight) { currentScene++; } if (yOffset < prevScrollHeight) { currentScene--; } console.log(`prevScrollHeight = ${prevScrollHeight}, pageYOffset=${yOffset}, currentScene=${currentScene}`); } // 리사이징 하면 그에 맞는 높이 다시 세팅 window.addEventListener('resize', setLayout); window.addEventListener('scroll', () => { yOffset = window.pageYOffset; scrollLoop(); }); setLayout(); })(); // css 코드 @charset 'utf-8'; html { font-family: 'Noto Sans KR', sans-serif; font-size: 14px; } body { overflow-x: hidden; color: rgb(29, 29, 31); letter-spacing: -0.05em; background: white; } p { line-height: 1.6; } .global-nav { position: absolute; top: 0; left: 0; width: 100%; height: 44px; padding: 0 1rem; } .local-nav { position: absolute; top: 45px; left: 0; width: 100%; height: 52px; padding: 0 1rem; border-bottom : 1px solid #ddd; } .global-nav-links, .local-nav-links { max-width: 1000px; display: flex; align-items: center; height: 100%; margin: 0 auto; } .global-nav-links { justify-content: space-between; } .global-nav-links a { font-size: 1.2rem; } .product-name { margin-right: auto; font-size: 1.4rem; font-weight: bold; } .local-nav-links a:not(.product-name) { margin-left: 2em; font-size: 1rem; } a { color : rgb(29, 29, 31); text-decoration: none; } .scroll-section { padding-top: 50vh; border: 3px solid red; } #scroll-section-0 h1 { font-size: 4rem; text-align: center; } .main-message { display: flex; align-items: center; justify-content: center; margin: 5px 0; height: 3em; font-size: 2.5rem; } .main-message p { line-height: 1.2; font-weight: bold; text-align: center; } .main-message small{ display: block; margin-bottom: 0.5em; font-size: 1.4rem; } #scroll-section-2 .main-message { font-size: 3.5rem; } .description { max-width: 1000px; margin: 0 auto; padding: 0 1rem; font-size: 1.2rem; color: #888; } .description strong { float: left; margin-right: 0.2em; font-size: 3rem; color: rgb(29, 29, 31); } .desc-message { font-weight: bold; width: 50%; max-width: 385px; } .pin { width: 1px; height: 100px; background-color: rgb(29, 29, 31); } .mid-message { max-width: 1000px; margin: 0 auto; padding: 0 1rem; font-size: 2rem; color: #888; } .mid-message strong { color: rgb(29, 29, 31); } .canvas-caption { max-width: 1000px; margin: 0 auto; padding: 0 1rem; color: #888; font-size: 1.2rem; } .footer { display: flex; align-items: center; justify-content: center; height: 7rem; background-color: tan; color: white; } .sticky-elem { display: none; position: fixed; top: 0; left: 0; width: 100%; } #show-scene-0 #scroll-section-0 .sticky-elem, #show-scene-1 #scroll-section-1 .sticky-elem, #show-scene-2 #scroll-section-2 .sticky-elem, #show-scene-3 #scroll-section-3 .sticky-elem { display: block; } @media (min-width: 1024px) { #scroll-section-0 h1 { font-size: 9vw; } .main-message{ font-size: 4vw; } .description { font-size: 2rem; } .description strong{ font-size: 6rem; } #scroll-section-2 .main-message { font-size: 6vw; } .main-message small { font-size: 2vw; } .desc-message { width: 20%; } .mid-message { font-size: 4vw; } .canvas-caption { font-size: 2rem; } }
- 미해결애플 웹사이트 인터랙션 클론!
콘솔창에 에러나는데 왜 이러는 걸까요 ㅠㅠ
(() => { 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, imageSequenc: [0, 299], 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 }], // 20=> translateY를 20%만큼 조정, %는 밑에 playAnimation()에서 붙여줄 거임 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'), }, 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 setCanvasImages() { let imgElem; for (let i = 0; i < sceneInfo[0].values.videoImageCount; i++) { // imgElem = document.createElement('img'); imgElem = new Image(); imgElem.src = `./video/001/IMG_${6726 + i}.JPG`; sceneInfo[0].objs.videoImages.push(imgElem); } } 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}`); } 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 = yOffset / 현재 씬의 scrollHeight; const scrollRatio = currentYOffset / scrollHeight; switch (currentScene) { case 0: // console.log('0 play'); let sequence = Math.round(calcValues(values.imageSequenc, currentYOffset)); objs.context.drawImage(objs.videoImages[sequence], 0, 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_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: // 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 = 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('scroll', () => { yOffset = window.pageYOffset; scrollLoop(); }); // window.addEventListener('DOMcontentLoaded', setLayout) // 이미지가 업로드 되기 전에 실행 window.addEventListener('load', setLayout); window.addEventListener('resize', setLayout); })();
- 미해결애플 웹사이트 인터랙션 클론!
opacity out 이 안되는데 검토 한번만 해주세요
(() => { let yOffset = 0; //window.pageOffset 대신 쓸 수 있는 변수 let prevScrollHeight = 0 // 현재 스크롤 (yOffset)보다 이전에 위치한 스크롤 높이값의 함 let currentScene = 0; // 현재 활성화된 (눈앞에 보고 있는) 씬(scroll-section) let enterNewScene = false; 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 }], messageA_opacity_out: [1, 0, { start: 0.25, end: 0.3 }], } }, { // 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') } }, { // 3 type: 'sticky', heightNum: 5, //브라우저 높이의 5배로 scrollheight 세팅 scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-3') } }, ]; function setLayout() { // 각 section 의 높이 세팅 for (let i = 0; i < sceneInfo.length; i++) { sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight; // sceneInfo[i].objs.container.style.height = `${sceneInfo[i].scrollHeight}px` } let totalScrollHeight = 0; let yOffset = window.pageYOffset; // 새로고침 버튼 눌렀을때 그 씬 장면이 유지 될 수 있게 해주는 역할 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(values, currentYOffset) { let rv; //현재 씬(스크롤 섹션)애서 스크롤된 범위를 비율로 구하기 const scrollHeight = sceneInfo[currentScene].scrollHeight; const scrollRatio = currentYOffset / scrollHeight; if (values.length === 3) { // start ~ end 사이에 애니메이션 진행 const partStart = values[2].start * scrollHeight const partEnd = values[2].end * scrollHeight const partScrollHeight = partEnd - partStart; if (currentYOffset <= partEnd && currentYOffset >= partStart) { rv = (currentYOffset - partScrollHeight) / partScrollHeight * (values[1] - values[0] + values[0]); } else if (currentYOffset < partStart) { rv = values[0]; } else if (currentYOffset > partEnd) { rv = values[1]; } } else { rv = scrollRatio * (values[1] - values[0] + values[0]); } return rv; } function playAinmation() { const objs = sceneInfo[currentScene].objs; const values = sceneInfo[currentScene].values; const currentYOffset = yOffset - prevScrollHeight; const scrollHeight = sceneInfo[currentScene].scrollHeight; const scrollRatio = (yOffset - prevScrollHeight) / scrollHeight; console.log(currentScene) switch (currentScene) { case 0: // calcValues = (values의 선명도, 현재 스크롤의 위치) const messageA_opacity_in = calcValues(values.messageA_opacity_in, currentYOffset) const messageA_opacity_out = calcValues(values.messageA_opacity_out, currentYOffset) if (scrollRatio <= 0.22) { // in objs.messageA.style.opacity = messageA_opacity_in; } else { // out objs.messageA.style.opacity = messageA_opacity_out; } break; case 1: break; case 2: 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; playAinmation() } window.addEventListener('scroll', () => { yOffset = window.pageYOffset; scrollLoop() }); window.addEventListener('resize', setLayout); window.addEventListener('load', setLayout); })()
- 미해결애플 웹사이트 인터랙션 클론!
offsetHeight는 어디서 가져 온 값인가요?
} else if (sceneInfo[i].type === 'normal') { sceneInfo[i].scrollHeight = sceneInfo[i].objs.container.offsetHeight;
- 미해결애플 웹사이트 인터랙션 클론!
case 3 마지막 if 문
안녕하세요 선생님. case 3에서 여러 if문을 사용하는데, 첫 번째 캔버스가 브라우저 상단에 닿는 부분부터 순서대로 if문 작성하시는 부분에서 질문이있어서요. <강의 내용> //캔버스가 브라우저 상단에 닿지 않았다면 부터 시작하는 if문을 보면 if (scrollRatio < values.rect1X[2].end) { step = 1; } else { step = 2; if (scrollRatio > values.blendHeight[2].end) { } if (scrollRatio > values.canvas_scale[2].end && values.canvas_scale[2].end > 0) { } } 이렇게 두번째랑 세번째 if문을 else함수 안에 나란히 작성하셨는데, 그렇게 말고 세번째 if를 두번째 if 안에 포함시키면 문제가 생기나요? 저는 통일감있게 if문 괄호 안에 조건을 하나만 넣고 싶은데 (scrollRatio > object[2].end) 요렇게요. 세번째 if문이 두번째 if문에 포함되지 않고 나란히 작성되면서 values.canvas_scale[2].end > 0 조건이 추가 되어야 하는 것 같아서요.
- 미해결애플 웹사이트 인터랙션 클론!
왜 저는 currentYOffset 값이 소수점으로 나올까요,,?
원래 안그랬는데 이번에 찍어보니깐 소수점 값이 찍히네요ㅜㅜ 선생님껀 정수로 나오는데 왜 저는 갑자기 소수점이 나올까여
- 미해결애플 웹사이트 인터랙션 클론!
부모 요소에 position : relative
선생님 안녕하세요. 캔버스 드로우 애니메이션 2 강의 4분 16초쯤에 css에 .scroll-section { position: relative; padding-top: 50vh; } 부분 추가 하시잖아요. 그런데 case 3에서만 offsetTop값 조정하는건데, id#scroll-section-3 가 아닌 class.scroll-section에 relative를 주는 이유가 따로 있을까요?
- 미해결애플 웹사이트 인터랙션 클론!
선생님 도움요청 부탁드려요
사진에 보시다시피 투명해지지않고 잔상이 남아있습니다, 다음 currentscene으로 넘어가면 없어지구요콘솔창에는 저런 에러가 발생합니다
- 미해결애플 웹사이트 인터랙션 클론!
loading div를 제거할 때 질문이 있습니다.
css에서 loading div를 opacity: 0; 과 함께 display:none을 기본값으로 주어서 body에 befor-load클래스를 없애면서 클릭이 가능하게 하는거랑 아예 loading div 자체를 없애버리는 거랑 어떤 점에서 차이가 있어서 제거를 하시는건가요?? 클릭이 가능하게 하는것은 둘 다 할 수 있어서요
- 미해결애플 웹사이트 인터랙션 클론!
도움 요청 드려요 ..
이러다가 삽을 계속 파게 될 거 같아서.. 도움을 요청합니다 main.add.js 코드 옮기고 나서 애니메이션 동작이 안돼요 https://github.com/kimjinseong1/apple-test
- 미해결애플 웹사이트 인터랙션 클론!
const , let 차이
const scrollRatio = currentYOffset / sceneInfo[currentScene].scrollHeight; 여기서 const 상수 즉 , 변하지 않는 값이라고 알고 있는데 console.log(scrollRatio) 출력하면 0~1 사이의 값들이 출력하는데.. 제가 지금 개념을 잘못 알고 있는 건가요?
- 미해결애플 웹사이트 인터랙션 클론!
선생님 recalculatedInnerWidth에 대한 질문입니다!
const recalculatedInnerWidth = document.body.offsetWidth / canvasScaleRatio; values.rect1X[0] = (objs.canvas.width - recalculatedInnerWidth) / 2; values.rect2X[0] = values.rect1X[0] + recalculatedInnerWidth - whiteRectWidth; 제가 canvas에 대해 잘몰라서 이해를 잘 못하는 것 같습니다. 선생님께서 canvas의 너비를 다시구하는 부분이 잘 이해가 되지않아서 생각해 보던중 선생님께서 말씀해주신 canvas에서 보이는 부분의 너비를 빼고 2로 나누어서 잘려진 부분의 너비를 구하고 그 너비를 시작으로 박스를 만든다고 이해했습니다. 1. objs.canvas.width * canvasScaleRatio를 하게되면 현재 브라우저에 설정된 canvas의 너비를 구할 수 있다고 생각합니다. 이 값에서 values.rect1X[0] = ((objs.canvas.width * canvasScaleRatio) - document.body.offsetWidth) /2 를 설정하고 values.rect2X[0] = values.rect1X[0] + document.body.offset - whiteRectWidth 을 해도 될거같아서 해봤는데..ㅠ 결과는 왼쪽은 맞는데 오른쪽이 맞지 않았습니다. (왼쪽도 선생님께서 구하신 것보다는 딱맞는다는 느낌은 들지 않았습니다.) 제가 느끼기에는 fillRect에 설정하는 값이 브라우저에서 사용하는 값과 이격이 있는거 같은데... 맞나요?? 예를 들어서 fillRect에 x값을 100을 설정하는 것과 브라우저의 100px과는 다른것 같아서 여쭤봅니다..ㅠㅠ 2.그리고 이거는 다른 질문인데 선생님께서 마우스를 이용하여 픽셀 높이를 줄자처럼 재시던데.. 그거는 혹시 프로그램인가요?
- 미해결애플 웹사이트 인터랙션 클론!
주제에 좀 벗어난 질문 같지만 답답해서 문의 좀 드립니다~^^;
자바스크립트를 잘 몰라 문의 드려봅니다! playAnimation() 함수안의 calcValues(values.messageA_opacity,currentYOffset); 라인의 currentYOffset는 이렇게 값을 넣어 calcValues()에 넘기는데요. calcValues() 함수안의 let scrollRatio = currentYOffset / sceneInfo[currentScene].scrollHeight; currentScene은 보내지도 않았는데 어디서 어떻게 값을 받아서 사용할수있는건가요? function calcValues(values,currentYOffset){ let rv; //현재 씬 (스크롤섹션)에서 스크롤된 범위를 구하기 //현 재씬에서 스크롤된 값 / let scrollRatio = currentYOffset / sceneInfo[currentScene].scrollHeight; ///////////////////////////////////////////////////////////////////////////////////////////////// console.log('currentYOffset: '+currentYOffset);//현재 씬에서 스크롤된 높이 //////////////////////////////////////////////////////////////////////////////////////////////// } function playAnimation(){ const objs = sceneInfo[currentScene].objs; const values = sceneInfo[currentScene].values; const currentYOffset = yOffset-prevScrollHeight;//현재 씬에서 스크롤된 높이=전체 씬에서 스크롤된 높이-이전 섹션의 높이의 합 //console.log('currentYOffset: '+currentYOffset);//현재 씬에서 스크롤된 높이 //console.log('yOffset: '+yOffset);//전체 씬에서 스크롤된 높이 //console.log('prevScrollHeight: '+prevScrollHeight);//이전 섹션의 높이 switch (currentScene){ case 0: //console.log('0 play'); let mesageA_opacity_0 = values.messageA_opacity[0]; let mesageA_opacity_1 = values.messageA_opacity[1]; //console.log("currentYOffset: "+currentYOffset); ///////////////////////////////////////////////////////////////////////////////////////// calcValues(values.messageA_opacity,currentYOffset); ///////////////////////////////////////////////////////////////////////////////////////// break; case 1: calcValues(values.messageA_opacity,currentYOffset); //console.log(currentScene, currentYOffset); break; case 2: console.log(currentScene, currentYOffset); break; case 3: console.log(currentScene, currentYOffset); break; } }