월 15,400원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨애플 웹사이트 인터랙션 클론!
페이지 업 / 다운키로 스크롤 제어시
page up / page down 버튼으로 스크롤을 올리면 body에 아이디가 제대로 안들어가는건 해결이 안될까요? 페이지 다운 페이지 업
- 해결됨애플 웹사이트 인터랙션 클론!
오류
검은 박스가 밖에서 안으로 들어오려는거 같은데 원인을 알 수 있을까요? case 3: // 가로, 세로 모두 100%로 채우기 위한 세팅(계산 필요) const widthRatio = window.innerWidth / objs.canvas.width; const heightRatio = window.innerHeight / objs.canvas.height; let canvasScaleRatio; if (widthRatio <= heightRatio) { // 브라우저 width < 캔버스 width인 경우 canvasScaleRatio = heightRatio; } else { // 브라우저 height < 캔버스 height 경우 canvasScaleRatio = widthRatio; } objs.canvas.style.transform = `scale(${canvasScaleRatio})`; objs.context.drawImage(objs.images[0], 0, 0); // 캔버스 사이즈에 맞춰 가정한 innerWdth와 innerHeight const recalculatedInnerWidth = document.body.offsetWidth / canvasScaleRatio; const recalculatedInnerHeight = window.innerHeight / canvasScaleRatio; if (!values.rectStartY) { // values.rectStartY = objs.canvas.getBoundingClientRect().top; values.rectStartY = objs.canvas.offsetTop + (objs.canvas.height - objs.canvas.height * canvasScaleRatio) / 2; values.rect1X[2].end = values.rectStartY / scrollHeight; values.rect2X[2].end = values.rectStartY / scrollHeight; } const whiteRectWidth = recalculatedInnerWidth * 0.15; values.rect1X[0] = (objs.canvas.width - recalculatedInnerWidth) / 2; values.rect1X[1] = values.rect1X[0] - whiteRectWidth; values.rect2X[0] = values.rect1X[0] + recalculatedInnerWidth - whiteRectWidth; values.rect2X[1] = values.rect2X[0] + whiteRectWidth; // 좌우 화이트박스 그리기 // objs.context.fillRect(values.rect1X[0], 0, parseInt(whiteRectWidth), objs.canvas.height); // objs.context.fillRect(values.rect2X[0], 0, parseInt(whiteRectWidth), objs.canvas.height); objs.context.fillRect( parseInt(calcValues(values.rect1X, currentYOffset)), 0, parseInt(whiteRectWidth), objs.canvas.height ); objs.context.fillRect( parseInt(calcValues(values.rect2X, currentYOffset)), 0, parseInt(whiteRectWidth), objs.canvas.height ); break;
- 미해결애플 웹사이트 인터랙션 클론!
페이지 load될때 캔버스 화면에 사진이 안뜨는 현상
// 20200626 이미지를 담고 있는 배열 생성 const setCanvas = ()=>{ let image; for (let i=0;i<infoArr[0].values.videoImageCount;i++) { image =new Image(); image.src = `../video/001/IMG_${6726+i}.JPG`; infoArr[0].objs.videoImages.push(image); } } #1. setCanvas(); window.addEventListener('load',()=>{ console.log(infoArr[0].objs.videoImages); console.log(infoArr[0].objs.videoImages[0]) setLayout(); infoArr[0].objs.context.drawImage(infoArr[0].objs.videoImages[0],0,0); }) #1에서는 페이지 로드 완료시 스크롤 없이도 첫번째 사진이 잘 렌더링 vs #2 window.addEventListener('load',()=>{ setCanvas(); console.log(infoArr[0].objs.videoImages); console.log(infoArr[0].objs.videoImages[0])//사진 setLayout(); infoArr[0].objs.context.drawImage(infoArr[0].objs.videoImages[0],0,0); }) #2에서는 페이지 로드 완료시 스크롤 없으면 첫번째 사진의 렌더링이 일어나지 않습니다.콘솔에 찍어보니 #1괴 #2모두 캔버스에 들어갈 사진들이 잘 나오구요. 이미지를 넣고 나서 로드 vs 로드한 후에 이미지를 넣는 것의 차이라 그런걸까요?도무지 모르겠어서 여쭤봅니다~
- 미해결애플 웹사이트 인터랙션 클론!
rv구하는 공식 질문이요.
rv=(현재스크롤 높이-1번파트 시작위치)/(1번파트 스크롤 크기)*(opacity 1-opacity 0)+opacity 0이잖아요.여기서 마지막에 opacity 0 은 값이 0이라서 더해줘도 의미 없지 않나요?
- 해결됨애플 웹사이트 인터랙션 클론!
reset.css vs default.js
저 스스로 클론하다보니 reset.css를 사용했는데 선생님께서는 default.css를 사용하셨더라구요. 구글링해보니 reset.css나 noramalize같은 건 많이 나오던데 혹시 직접 만들어 놓으신건지 /실무에서는 필요에 따라 아무거나 써도 상관없는지가 궁금합니다.
- 애플 웹사이트 인터랙션 클론!
질문
삭제된 글입니다
- 미해결애플 웹사이트 인터랙션 클론!
transform 함수에 대해 문의드립니다.
안녕하세요 1분 코딩 강사님! 즐겁고 유익한 강의 잘 듣고 있습니다. 선생님의 깨알같은 노잼개그는....개그의 다양성을 존중합니다. canvas를 중앙정렬하는 강의 중에 transform을 쓸 때 position을 absolute로 하더라도 top, left를 0으로 할 수 없다. transform은 다른 속성의 영향을 받지 않는다는 요지의 말씀을 하셨는데 top:0은 안 되고 top: 50%는 작동하는 이유를 알고싶습니다. 관련 코드 스니펫 첨부합니다. 감사합니다.
- 미해결애플 웹사이트 인터랙션 클론!
아니 갑자기 뭐에요?
버전 별로 파일이 나눠진 것도 아니고, 지금 나오는 코드랑 최종코드가 너무 달라요 갑자기 잘 되다가 안되니깐 짜증이 몰려오네요 ㅋ
- 미해결애플 웹사이트 인터랙션 클론!
css에서 자동완성
브라켓을 사용하고 있는데요 강의에서 보면 css에서 .produc만 쓰셨는데 밑에 자동완성기능으로 html에서 쓰신 class 이름이 자동완성기능이 있던데 브라켓에는 없을까요?
- 미해결애플 웹사이트 인터랙션 클론!
스크롤 애니메이션 구현 3번에서의 오류
안녕하세요 평소 배우고 싶은 강의가 딱 있어 재미있게 듣는 과정 중에 오류가 발생하였습니다. (() => { 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, //scroll-section id를 바로 가져와서 사용할수 있게 객체화 시킨다. 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: { //opacity와 transform 함수를 사용 하여 변화를 준다 //전체 범위(700) messageA_opacity: [0, 1] } }, { //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() { //각 스크롤 섹션의 높이 세팅 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`; } // 새로고침 할때도 동일한 currentscene 표시 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; // 현재 scene(scroll-section)에서 스크롤된 범위를 비율로 구하기 // 현재 scroll된 길이를 현재 scene의 높이를 나눠주면 비율을 구할수있다. let scrollRatio = currentYOffset / sceneInfo[currentScene].scrollHeight; 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; // console.log(currentScene,currentYOffset); switch (currentScene) { case 0: // console.log('0 play'); let messageA_opacity_in = calcValues(values.messageA_opacity, currentYOffset); // console.log(messageA_opacity_0,messageA_opacity_1); // console.log(currentYOffset); // console.log( calcValues(values.messageA_opacity,currentYOffset) ); // console.log(messageA_opacity_in); // console.log(messageA_opacity_in); objs.messageA.style.opacity = messageA_opacity_in; break; case 1: // console.log('1 play'); break; case 2: // console.log('2 play'); break; case 3: // console.log('3 play'); break; } } function scrollLoop() { prevScrollHeight = 0; for (let i = 0; i <currentScene; i++) { prevScrollHeight += sceneInfo[i].scrollHeight; } if (yOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) { currentScene++; document.body.setAttribute('id', `show-scene-${currentScene}`); } if (yOffset < prevScrollHeight) { if(currentScene === 0) return; currentScene--; document.body.setAttribute('id', `show-scene-${currentScene}`); } playAnimation(); //document.body.setAttribute('id', `show-scene-${currentScene}`); } window.addEventListener('scroll', () => { yOffset = window.pageYOffset; scrollLoop(); }); // load는 앞에 과정 모두 로드 한후 실행, DOM은 관련 로직만 실행되면 바로 실행 window.addEventListener('load', setLayout); window.addEventListener('resize', setLayout); })(); 지금 이 과정까지 소스코드를 작성하고 확인하는데 opacity를 확인하려는데 계속 Uncaught TypeError: Cannot read property 'style' of null 오류가 발생하네요 영상 여러번 돌려보면서 확인 해보왔는데도 오류가 뜨네요 참고로 HTML부분 Class도 <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> 강의와 같이 수정하였습니다. 꼭 제발 도움좀 부탁드립니다. ㅠㅠ
- 미해결애플 웹사이트 인터랙션 클론!
Canvas vs MP4 vs SVG (Bodymovin)
안녕하세요. 현재 canvas를 이용해서 인터렉티브한 개인 포트폴리오용 웹사이트를 만들고 있는데 큰 도움이 되었습니다. 추가적으로 "이미지, 영상, 웹사이트 로드속도"에 대해 궁금한점이 있어 질문을 남겨봅니다. 정적인 이미지를 로드 할 때 - 카메라로 담긴 실제 사진은 jpg 또는 배경 상황에따라 png 로 - 일러스트로 만들어진 아이콘, 그래픽디자인은 svg 로 업로드 하면 여러방면에서 괜찮다고 들었습니다. <<<궁금한점은 gif animation처럼 짧은 모션디자인이나 영상 mp4 클립을 일반적으로 (인터렉티브 function 이 없는 경우) 어떤 방식으로 업로드해야 가장 효율적인지 입니다. >>> 최대 15초 가량되는 1920 x 1080 FHD 영상을 업로드 한다면 어떤 방법이 가장 효율적인지 궁금합니다. 포트폴리오 목적이기에, 많은 모션영상이 업로드 될 예정이고 처음부터 탄탄하게 웹사이트를 제작하고 싶습니다. CANVAS vs HTML Video vs SVG (body Movin from after effects 또는 직접 만들기) 강좌에 포함된 파일에서 비교영상을 보았을 때, 인터렉티브한(예: 스크롤) function 을 적용 했을 경우 canvas가 더 효과적이라고 이해했습니다. 인터넷으로 리서치 해 본 결과도 이 분야에서는 대체적으로 canvas > svg > html mp4 로 이해하고 있습니다. <<< canvas의 단점은 오로지 svg 와 html mp4 에 비해 작업양이 더 많기 때문인가요? >>> 경험을 바탕으로 개인적인 의견 부탁드리겠습니다. 그리고 다시 한 번 좋은 강좌 감사합니다!
- 미해결애플 웹사이트 인터랙션 클론!
캔버스 width height 사이즈
애플의 예> <canvas width="900" height="650" style="width: 900px; height:650px;"> 애플 웹사이트나 캔버스를 사용하는 다른 사이트들을 "검사" 로 통해 보면 canvas element 자체에서 width height px 값이 변경되는것으로 보입니다. 질문 : 강사님이 강좌에서 보여준것처럼 canvas 에 parent element 를 만들어서 그 height 값을 조정하는것과 canvas element 자체에서 사이즈 조정하는것, 사용 용도에 따라 다르다고 하셨는데 굳이 차이점을 찾는다면 어떤것이 있나요? 이미지 로드 속도? 아니면 resize 시 오류 대응?..
- 미해결애플 웹사이트 인터랙션 클론!
작업 프로그램이 뭐에요?
무슨 프로그램으로 하는건지 알려주세요 뭘로 따라해야하는건지 모르겠어요
- 미해결애플 웹사이트 인터랙션 클론!
선생님 질문있습니다.
main.js적용내용 강의중에서요 녹화하신 영상 보면 case 2: 부분에 if (scrollRatio <= 0.57) { } 부분에서 objs.pinB.style.opacity = `scaleY(${calcValues(values.pinB_opacity_in)})`; 주셨는데요 opacity 적용인데 앞에 scaleY 는 오타인건가요??
- 해결됨애플 웹사이트 인터랙션 클론!
main.js 적용내용 강좌에서 에러가 나서 문의 드려요~
(() => { 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: [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,//브라우저 높이의 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'), canvasCaption:document.querySelector('.canvas-caption') }, valeus:{ canvasCaption_opacity: [ 0, 1, { start: 0, end: 0 } ], canvasCaption_translateY: [ 20, 0, { start: 0, end: 0 } ] } }, ] 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`; } 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(values, currentYOffset){ 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_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)`; } break; case 1: // console.log('1 play'); break; case 2: // console.log('2 play'); 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); })() 0.62 scrollRatio 에서 에러가 나서 문의 드려요. main.js:187 Uncaught TypeError: Cannot read property 'style' of null
- 미해결애플 웹사이트 인터랙션 클론!
canvas가 성능상의 이점을 가지는 이유가 궁금합니다.
안녕하세요! 좋은 강의 감사합니다. 이미지 태그의 src를 직접 바꾸는 것 보다는 canvas를 사용하는 것이 좀 더 부드러운 애니매이션이 가능하다고 강의에서 언급해주셨는데요, 어떤 이유로 canvas가 성능상의 이점을 가지는지가 궁금해져 질문드립니다.
- 미해결애플 웹사이트 인터랙션 클론!
좋은강의 감사합니다. 그런데 익스에서 아예실행안되는거 맞나요..?
오늘 결제해서 소스 다운받고 먼저 둘러보았는데 익스에서 아예 안돌아가던데.. 실화인가여..? 아니면 바벨로 컴파일하기전이라서 그런건지.. 아니면 제가 확인을 잘못한건지...... 설마..... 아니죠..? 확인부탁드립니다 ㅠ__ㅠ
- 미해결애플 웹사이트 인터랙션 클론!
opacity out 이 안됩니다. script 검토한번 부탁드릴게요.
(() => { let yOffset = 0; // window.pageYOffset 대신 쓸 변수 let prevScrollHeight = 0; // let currentScene = 0; // let enterNewScene = false; // 새로운 Scene 이 시작도는 순간. const sceneInfo = [ { 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: [0, 1, { start: 0.25, end: 0.3 }], } }, { type: 'normal', heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅; scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-1") } }, { type: 'sticky', heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅; scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-2") } }, { type: 'sticky', heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅; scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-3") } } ] function setLayout() { for (let i = 0; i < sceneInfo.length; i++) { sceneInfo[i].scrollHeight = sceneInfo[i].heightNum * window.innerHeight; // A : 각 section height 값 sceneInfo[i].objs.container.style.height = `${sceneInfo[i].scrollHeight}px`; // A값을 각 section에 적용. } 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 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; // 안써주면 undefined } 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'); 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 : // console.log('1 play'); break; case 2 : // console.log('2 play'); 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}`); } // console.log(currentScene); if (enterNewScene) return; playAnimation(); } window.addEventListener('resize',setLayout); window.addEventListener('scroll',() => { yOffset = window.pageYOffset; scrollLoop(); }); setLayout(); })();
- 미해결애플 웹사이트 인터랙션 클론!
안녕하세요!
20초짜리 동영상 1920 x1080을 프레임 추출하니 1257개의 파일이 나왔습니다! 동영상크기보다 4배더 큰데... 이미지 압축은 구글해서 검색해서 실시간 압축해주는 곳을 찾아서 압출을 했습니다. 그런데도 파일크기가 너무 큽니다.. 어떻게 하면 좋을까요 ㅠㅠ 웹에 호스팅을 했는데 로딩시간이 너무 길어서 문제에요 ㅠㅠㅠ
- 미해결애플 웹사이트 인터랙션 클론!
스크롤 section 0-3 정확하지가 않습니다.
section별로 currentScene 0,1,2,3이 정확하게 안떨어집니다. .scroll-section { padding-top: 50vh; border:1px solid red; } 여기서 padding-top: 50vh 를 비활성화 하니 정확하게 들어맞습니다. javscript 에서 scrollHeight 계산시 padding-top 50vh 값을 제외하는것 같아요.