묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결애플 웹사이트 인터랙션 클론!
자꾸 에러가 뜨는데 모르겠습니다ㅠㅠ
안녕하세요 선생님. 강의 너무 유용하고 재밌게 듣고 있습니다. 자꾸 오류가 뜨는데 무슨 문젠지 모르겠어서 너무 답답해서 질문 남깁니다.ㅠㅠ 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(); })();
-
따라하며 배우는 노드, 리액트 시리즈 - 유튜브 사이트 만들기
왜 무한로딩이 될까요...
삭제된 글입니다
-
해결됨실전 리액트 프로그래밍
죄송하지만 Button.js 내용은 어디서 확인할 수 있나요?
죄송하지만 Button.js 내용은 어디서 확인할 수 있나요?
-
미해결[리뉴얼] React로 NodeBird SNS 만들기
차트 라이브러리 response는 어떻게 받아야하나요?
스트리밍때 여쭤보려고 했는데 못물어봐서 강의 질문으로 여쭤봅니다. echart 사용중인데 request 받고 response를 서버에서 보내줄때 echart에 필요한 데이터 형식으로 맞춰서 보내주는 방식으로 코드 작성했는데요, json으로 response 전달되다 보니까 함수코드를 어떻게 전달해야 할지 모르겠습니다 db에서 조회한 데이터를 그냥 client로 넘겨주고 client 단에서 map 이나 filter로 받은 데이터를 echart 형식에 맞게 바꿔주는 방식으로 해야하나요?
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
spring-boot-devtools 사용시 recompile하면 서버가 재시작되나요?
안녕하세요, html 파일 수정시 ctrl + shift + f9 단축키로 recompile하면 서버 재시작 없이 변경사항이 적용 되는줄 알았는데 리컴파일 할때마다 서버자체가 재시작 되면서 데이터베이스의 테이블도 다 드랍했다 생성합니다. ddl-auto: create으로 해놓긴 했지만 리컴파일 할때 서버 재시작이 안되고 반영되는줄 알았는데 무조건 서버 재시작이 되는건가요?
-
미해결따라하며 배우는 노드, 리액트 시리즈 - 챗봇 사이트 만들기
postman에서 post 시 오류
localhost:5000 이 아닌 3000으로 연결되었고, postman에서 포트 번호만 3000으로 변경해서 post했을 때 아래와 같이 오류가 발생합니다. 혹시 원인을 알 수 있을까요? [HPM] Error occurred while trying to proxy request /api/dialogflow/textQuery from localhost:3000 to http://localhost:5000/ (ECONNREFUSED) (https://nodejs.org/api/errors.html#errors_common_system_errors)
-
미해결Vue로 Nodebird SNS 만들기
login 비활성화 등은 해결되었는데 여전히 v-icon 들이 보이지 않습니다.
알려주신 데로 추가 인스통하여 package.json 에도 버전이 다 올라온 상태입니다. 안그레도 modules 여쭈어 보려 했었는데 강의 에는 devModules로 변경하라 하라고 하셨는데 인터넷 찾아보니 buildModules로 되어있습니다. 우선 dev 에서 build로 변경한 상태입니다. 그리고 login 비활성화와 check-box 깨지듯 나오는것은 해결이 되었습니다. 동영상에 보이는 버전들과 유사한데 여전히 아이콘들이 보이질 않습니다. 아이콘 자리에 마우스를 갔다 대면 손가락으로 변하였습니다. 그리고 v-image와 v-list-tile 이란게 없다면서 에러가 뜹니다. 제가 vuetify 에 가서 찾아 봐도 찾지를 못했습니다. v-img 란게 보이긴 한데 동일한것인지는 모르겠습니다.
-
미해결실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발
test case 작성시 필드 주입 방식에 대해서 궁금합니다!
service 구현에서는 생성자 주입 방식이 test case에서도 주입 값을 바꿔서 사용할 수 있다고 하셨었는데요. 실제 test case에서는 필드 주입으로 코드를 작성하시더라구요! 그러면 test case에서 주입되는 memberService값과 MemberService에서 주입되는 memberService값이 똑같은거 아닌가요?ㅜㅜ 여기 부분이 어떻게 다른건지 이해가 잘 안돼서요ㅜㅜ
-
미해결따라하며 배우는 도커와 CI환경 [2023.11 업데이트]
에디터 사용에 대한 접근 어려움이 있습니다 ㅠㅠ
개념이 없어서 어렵습니다. vim을 한두번 써 봤지만 . 폴더를 만들고 에디터를 사용한다는 것이 이해가 안됩니다. 에디터에서 파일을 생성한다? 어떤 파일이 어떻게 에디터에서 어디에 생성이되는 건가요? 이런 문제는 어떻게 접근할 수 있을까요? 너무 초보적인 질문을 드려서 죄송합니다.
-
미해결Vue.js 끝장내기 - 실무에 필요한 모든 것
eslint 적용문제..
안녕하세요, 판교님, 강의 잘 듣고 있습니다. 강의를 한번 더 다시 보구 있는데요. eslint가 제대로 안먹혀서 확인중에 다른분의 댓글을보니 "eslint.workingDirectories": [ "./vue-til" ] 이런식으로 현제 작업폴더 경로를 추가 해보니 잘 먹히더라구요.. cli 버전은 @vue/cli 4.5.6 입니다. vue 2로 설치했구요.. node 버전은 영상과 같이 v10.16.3입니다. 혹시 매번 이런식으로 프로젝트를 생성할때마다 추가를 해줘야 ㅎ는지요??
-
미해결웹 게임을 만들며 배우는 React
dispatch가 자식컴포넌트로 넘어가질 않습니다.
(사진)
-
미해결애플 웹사이트 인터랙션 클론!
섹션구분
섹션구분을 컨테이너클래스 안에서 안하고 밖에서하면 안되는건가용??
-
미해결React로 NodeBird SNS 만들기
제로초님~
제로초님 안녕 하세요 우선 추석 잘 보내시고 복 많이 받으세요 !ㅎㅎ 다름이 아니라 이런 부분 어떻게 안뜨게 하는지 해서 글을 남깁니다!
-
미해결진짜 현업에서 쓰이는 직장인의 실무 엑셀 - 데이터 가공부터 분석까지
구분기호 기준 열분할시, 사용자지정의 추가옵션박스 여부
구분기호기준 열분할을 선택후, 줄바꿈을 하고자합니다. 사용자 지정을 선택하면 강사님께서 말씀해주신 대로라면, 아래쪽에 [특수기호 사용]이 선택지에 있는 옵션창이 하나더 나와야하는데, 이부분이 아예 보이지 않습니다. 엑셀 버전문제인가요?ㅜㅜ
-
미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part6: 웹 서버
함수 바인딩시 매개변수 전달 방법에 대한 질문
안녕하세요 강의에서 19:00 부터onclick 이벤트?에 유저 삭제하는 함수를 바인딩 해주는 부분에서 간단하게 람다를 이용해서 간접적으로 () 라는 익명함수가함수를 호출해주는 방식으로 해주셨는데혹시 이 방법외에 다른 방법들도 어떤것들이 있는지 써주실수 있을까요??
-
미해결진짜 현업에서 쓰이는 직장인의 실무 엑셀 - 데이터 가공부터 분석까지
웹상에서 데이터불러오기 오류
1. 웹상에서 데이터 불러오기 중, 웹페이지 자체가 아래와 같은 오류가 뜨면서 불러와지지 않습니다. 본 오류는 강의의 예제(위키피디아_대한민국의 아카데미 출품작)페이지를 불러오는 시작부터 발생하는오류입니다. 2. 멜론사이트에서 음원곡의 좋아요수를 불러오고 싶은데요.. 이 부분은 불러오고 나서 데이터 로드시 아래와 같은 오류가 발생합니다... 이부분도 도와주세요 https://www.melon.com/chart/month/index.htm?classCd=GN0100
-
미해결HTML+CSS+JS 포트폴리오 실전 퍼블리싱(시즌1)
블라켓츠와 VSCode를 모두 사용하시나요?
블라켓츠와 VSCode를 모두 사용하시나요? VSCode를 다뤄본적이 있어서 블라켓츠와 VSCode 2가지 선택지를 주신거라면 VSCode만 갖고 수강하려합니다. 블라켓츠 강의를 듣기 전에 질문을 단 점 양해부탁드립니다. 2가지 모두 사용하여 작업하신다면 블라켓츠부터 듣도록 하겠습니다^^
-
해결됨스프링 핵심 원리 - 기본편
TestBean 클래스의 자동 빈등록 이유
public class AutowiredTest { @Test public void autowiredOption() { ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class); }위의 예제를 보면 TestBean이 자동으로 컨테이너에 빈으로 등록된다고 하셨는데@Autowired가 있기 때문에 그런 것 같은데 맞나요?
-
미해결제주코딩베이스캠프 Code Festival: Python 100제
99번에 오류가 살짝 있어서 고쳐봤어요
rocks = [1, 2, 1, 4] rabbits = [2, 1, 3] def sol(rocks, rabbits): results = ["pass" for i in range(len(rabbits))] for i in range((len(rabbits))): step = 0 while step < len(rocks): step += rabbits[i] print(f'step: {step}') if step <= len(rocks): rocks[step - 1] -= 1 if rocks[step - 1] < 0: results[i] = 'fail' print(rocks) print('---------------') return results sol(rocks, rabbits) 배열 크기를 벗어나면 오류가 생겨서 if문으로 걸러줬습니다.
-
미해결캐글 Advanced 머신러닝 실전 박치기
아이디어 폐기 여부
안녕하세요. 주어진 소스에 아이디어를 적용해서 더하고 빼면서 컬럼을 추가해보거나 여러 처리를 해 보고 있는데 로컬에서 metric 으로 측정한 점수는 조금 상승했는데 제출을 해보면 오히려 떨어지는 경우가 왕왕 있어서 의욕이 저하됩니다 ㅠㅠ (난사하고 앙상블 하면 좋아질 줄 알았어요...) 적은 점수 차이면 자신을 가지고 밀고 나가야할지 폐기하고 아이디어 적용 전으로 돌아가서 다시 새로운 시도를 할지 경험이 너무 적어서 고민이 됩니다. 감사합니다.