묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결제주코딩베이스캠프 Code Festival: JavaScript 100제
아스키 코드 연산 가능 유무
아스키 코드 연산도 문제에서는 불가능한가요? 저는 문자열을 서로 뺄셈하여 숫자를 구했습니다.
-
해결됨파이썬 알고리즘 문제풀이 입문(코딩테스트 대비)
코드 관련 질문입니다.
문제에서는 'N개의 숫자로 이뤄진 숫자열이 주어지면' 이라고 숫자열 범위의 제한이 명시되어 있는데, 해당 코드로 한다면 범위의 제한이 없는 거 아닌가요??
-
미해결윤재성의 Vue.js 프로젝트를 통한 실무 개발 과정
v-model.number
v-model.number 수식어 부분에서 문자열만 쓰고 버튼을 누르면 강의처럼 string이라고 나옵니다 ex) asdf 문자열+숫자를 쓰고 버튼을 누르면 역시 강의처럼 string이라고 나옵니다 ex)asdf1234 근데 숫자+문자열을 쓰고 버튼을 누르면 number라고 나오고 뒤에 문자열이 지워집니다 ex)1234asdf 이 부분에 대한 설명을 들을 수 있을까요?
-
미해결자바 스프링 프레임워크(renew ver.) - 신입 프로그래머를 위한 강좌
게시판을 제작하는 강의는 어디있는건가요 ?
게시판 제작 강의는 어디있는건가요 ?
-
따라하며 배우는 노드, 리액트 시리즈 - 기본 강의
[해결]npm run start 에러
삭제된 글입니다
-
해결됨스프링 프레임워크 핵심 기술
결국 다른 패키지에 있는 빈들을 스캔할려면
MyService같은 다른 패키지에 있는 빈들을 스캔할려면 펑션을 사용한 빈 등록처럼 직접 applicationContext에 다가 빈을 등록하는수 밖에 없나요? 그리고 펑션을 사용한 빈 등록은 인스턴스를 이용해 생성해서 직접 빈 등록해서 구동시 성능을 증가한다고 보면 될까요? 그런데 단점으로는 설정파일이 너무 많아지는점이구요
-
해결됨스프링 프레임워크 핵심 기술
마지막 스프링부트에서 bean관리 하는 방법 설명에서
기존에서는 xml , java로 componentscan으로 @component인 클래스들 빈으로 해서 ApplicationContext에서 관리 했다면 최종단계는 @SpringbootApplication에 componentscan하고 config 다 붙어 있어서 필요 없는걸까요? 스프링부트에서 ApplicationContext도 자동으로 생성하고 scan도 하고 관리도하니까
-
미해결당신을 함께 일하고 싶은 개발자로 만들어 줄 클린 코드 작성법
그냥 지나가려 했는데 뭐가 자꾸 보이네요..
동료에게 혼란만 줄 뿐이다. -> 동료에게 혼란만 줄 뿐입니다 별거 아닌거 지적해서 죄송합니다,,
-
미해결당신을 함께 일하고 싶은 개발자로 만들어 줄 클린 코드 작성법
그밖의 좋은 코드 작성을 위한 Tip2 : Tell, Don't ask 설명이 누락된 것 같습니다
그밖의 좋은 코드 작성을 위한 Tip2 : Tell, Don't ask 에서 나쁜 예를 소개할 때 엘리베이터를 관리하는 ElevatorManager와 Elevator 클래스가 있다고 가정하여 예로 들어보았습니다. 라고 했는데 ElevatorManager 와 Elevator 클래스가 어떤 클래스인지 코드가 나와있지 않습니다. 변화된 모습은 나오는데 변화되기 전의 형상이 없어 왜 tell 방식이 ask방식보다 좋은지 이해가 안되네요
-
미해결트렐로 개발로 배우는 Vuejs, Vuex, Vue-Router 프론트엔드 실전 기술
addEventListener를 사용하였는데 removeEventListener 해주어야 하지 않을까요?
addEventListener가 mounted 라이프사이클 훅에 걸려있어 열고 닫을때마다 addEventListener가 계속 생성될텐데 그대로 둬도 될지 잘 모르겠네용.. ㅠㅠ
-
미해결웹 게임을 만들며 배우는 React
hooks로 변환하니 다음과 같은 에러가 납니다.
제 생각에는 초기 배열이 빈배열이어서 length를 쓸 수 없어서 나는 에러 같은데 어떻게 해결해야 할지 모르겠습니다.
-
미해결애플 웹사이트 인터랙션 클론!
4개의 씬을 5개로 늘려서 응용하려는 데 작동이 잘 안되네요 ㅠㅠ
@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; } a { color: rgb(29, 29, 31); text-decoration: none; } body.before-load { overflow: hidden; } .container { /* iPhone 가로 스크롤 방지 */ overflow-x: hidden; } .global-nav { position: absolute; top: 0; left: 0; z-index: 10; width: 100%; height: 44px; padding: 0 1rem; } .local-nav { position: absolute; top: 45px; left: 0; z-index: 11; width: 100%; height: 52px; padding: 0 1rem; border-bottom: 1px solid #ddd; } .local-nav-sticky .local-nav { position: fixed; top: 0; background: rgba(255, 255, 255, 0.1); /* for iPhone */ -webkit-backdrop-filter: saturate(180%) blur(15px); -moz-backdrop-filter: saturate(180%) blur(15px); -o-backdrop-filter: saturate(180%) blur(15px); backdrop-filter: saturate(180%) blur(15px); } .global-nav-links, .local-nav-links { display: flex; align-items: center; max-width: 1000px; height: 100%; margin: 0 auto; } .global-nav-links { justify-content: space-between; } .local-nav-links .product-name { margin-right: auto; font-size: 1.4rem; font-weight: bold; } .local-nav-links a { font-size: 0.8rem; } .local-nav-links a:not(.product-name) { margin-left: 2em; } .scroll-section { position: relative; padding-top: 50vh; border: 3px red solid; } #scroll-section-0 h1 { position: relative; top: -10vh; z-index: 5; font-size: 4rem; text-align: center; } #scroll-section-1 h1 { position: relative; top: -10vh; z-index: 5; font-size: 4rem; text-align: center; } .main-message { display: flex; align-items: center; justify-content: center; top: 35vh; margin: 5px 0; height: 3em; font-size: 2.5rem; opacity: 0; } .main-message p { font-weight: bold; text-align: center; line-height: 1.2; } .main-message small { display: block; margin-bottom: 0.5em; font-size: 1.2rem; } #scroll-section-3 .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 { width: 50%; font-weight: bold; opacity: 0; } .pin { width: 1px; height: 100px; background: rgb(29, 29, 31); } #scroll-section-3 .b { top: 10%; left: 40%; } #scroll-section-3 .c { top: 15%; left: 45%; } .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: -24rem auto 0; padding: 0 1rem; font-size: 1.2rem; color: #888; } .footer { display: flex; align-items: center; justify-content: center; height: 7rem; color: white; background: darkorange; } .sticky-elem { display: none; position: fixed; 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, #show-scene-4 #scroll-section-4 .sticky-elem { { display: block; will-change: transform, opacity; } .sticky-elem-canvas { top: 0; height: 100%; } .sticky-elem-canvas canvas { position: absolute; top: 50%; left: 50%; } #scroll-section-3 { display: flex; flex-direction: column; align-items: center; } .image-blend-canvas.sticky { position: fixed; top: 0; } .loading { display: flex; align-items: center; justify-content: center; position: fixed; top: 0; right: 0; bottom: 0; left: 0; z-index: 100; background: white; opacity: 0; transition: 0.5s; } .before-load .container { display: none; } .before-load .loading { opacity: 1; } @keyframes loading-spin { 100% { transform: rotate(360deg); } } @keyframes loading-circle-ani { 0% { stroke-dashoffset: 157; } 75% { stroke-dashoffset: -147; } 100% { stroke-dashoffset: -157; } } .loading-circle { width: 54px; height: 54px; animation: loading-spin 3s infinite; } .loading-circle circle { stroke: black; stroke-width: 4; /* getTotalLength()로 stroke의 길이를 얻어올 수 있음 */ stroke-dasharray: 157; stroke-dashoffset: 0; fill: transparent; animation: loading-circle-ani 1s infinite; /* transition: 1s; */ } /* .loading-circle:hover circle { stroke-dashoffset: -157; } */ @media (min-width: 1024px) { #scroll-section-0 h1 { font-size: 9vw; } #scroll-section-1 h1 { font-size: 9vw; } .main-message { font-size: 4vw; } .description { padding: 0; font-size: 2rem; } .description strong { font-size: 6rem; } #scroll-section-3 .main-message { font-size: 6vw; } .main-message small { font-size: 1.5vw; } .desc-message { width: 20%; } #scroll-section-3 .b { top: 20%; left: 53%; } #scroll-section-3 .c { left: 55%; } .mid-message { width: 1000px; padding: 0; font-size: 4vw; } .canvas-caption { margin-top: -8rem; padding: 0; font-size: 2rem; } } <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>AirMug Pro</title> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;900&display=swap" rel="stylesheet"> <link rel="stylesheet" href="css/default.css"> <link rel="stylesheet" href="css/main.css"> </head> <body class="before-load"> <div class="loading"> <svg class="loading-circle"> <circle cx="50%" cy="50%" r="25"></circle> </svg> </div> <div class="container"> <nav class="global-nav"> <div class="global-nav-links"> <a href="#" class="global-nav-item">Rooms</a> <a href="#" class="global-nav-item">Ideas</a> <a href="#" class="global-nav-item">Stores</a> <a href="#" class="global-nav-item">Contact</a> </div> </nav> <nav class="local-nav"> <div class="local-nav-links"> <a href="#" class="product-name">AirMug Pro</a> <a href="#">개요</a> <a href="#">제품사양</a> <a href="#">구입하기</a> </div> </nav> <section class="scroll-section" id="scroll-section-0"> <h1>영주마실 사과즙 30포</h1> <img src="./images/blend-image-1.jpg" alt=""> </section> <section class="scroll-section" id="scroll-section-1"> <!--<h1>영주마실 사과즙 30포</h1>--> <div class="sticky-elem sticky-elem-canvas"> <canvas id="video-canvas-0" width="1920" height="1080"></canvas> </div> <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> </section> <section class="scroll-section" id="scroll-section-2"> <p class="description"> <strong>보통 스크롤 영역</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae est ipsa minima, eligendi error cum vel dolorum pariatur officia facilis ipsam voluptatibus ad quasi porro quod quisquam quidem tempora accusantium accusamus, quaerat aliquam velit exercitationem incidunt? Id vitae quisquam saepe quasi accusantium tempore enim! Aperiam dolorum a vero repellat dolor, inventore ab odit totam molestias expedita? Enim quia dolor maiores veniam ea! Quam illo, est incidunt ipsa reiciendis modi quisquam reprehenderit fuga velit dolorem odit sequi autem blanditiis, ullam commodi quibusdam. Accusamus repellat aperiam quis neque laudantium, dignissimos hic nisi magnam praesentium enim beatae sint architecto cum numquam inventore rerum animi sed nostrum quae delectus, voluptas molestiae placeat aliquid! Vel quaerat error officiis magnam dolorum iste aspernatur at est! Quo, consequuntur? Reiciendis, dolor. Quo at cupiditate in iure obcaecati voluptatum vel ea! Ab vel harum facere hic fuga ducimus sapiente dolore dolorem, nobis sint perferendis cumque esse! Omnis fugiat sint error laborum eveniet labore nam ducimus quisquam in repudiandae impedit excepturi dignissimos tenetur libero placeat rerum maxime tempore, aut nihil. Qui, quam? Voluptate fuga possimus itaque quas nesciunt iste, facilis mollitia illo qui placeat temporibus inventore obcaecati. Recusandae, sequi dignissimos in natus eum maiores dolorem, deleniti nobis accusantium, aspernatur beatae. </p> </section> <section class="scroll-section" id="scroll-section-3"> <div class="sticky-elem sticky-elem-canvas"> <canvas id="video-canvas-1" width="1920" height="1080"></canvas> </div> <div class="sticky-elem main-message a"> <p> <small>편안한 촉감</small> 입과 하나 되다 </p> </div> <div class="sticky-elem desc-message b"> <p> 편안한 목넘김을 완성하는 디테일한 여러 구성 요소들, 우리는 이를 하나하나 새롭게 살피고 재구성하는 과정을 거쳐 새로운 수준의 머그, AirMug Pro를 만들었습니다. 입에 뭔가 댔다는 감각은 어느새 사라지고 오롯이 당신과 음료만 남게 되죠. </p> <div class="pin"></div> </div> <div class="sticky-elem desc-message c"> <p> 디자인 앤 퀄리티 오브 스웨덴,<br>메이드 인 차이나 </p> <div class="pin"></div> </div> </section> <section class="scroll-section" id="scroll-section-4"> <p class="mid-message"> <strong>Retina 머그</strong><br> 아이디어를 광활하게 펼칠<br> 아름답고 부드러운 음료 공간. </p> <canvas class="image-blend-canvas" width="1920" height="1080"></canvas> <p class="canvas-caption"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet at fuga quae perspiciatis veniam impedit et, ratione est optio porro. Incidunt aperiam nemo voluptas odit quisquam harum in mollitia. Incidunt minima iusto in corporis, dolores velit. Autem, sit dolorum inventore a rerum distinctio vero illo magni possimus temporibus dolores neque adipisci, repudiandae repellat. Ducimus accusamus similique quas earum laborum. Autem tempora repellendus asperiores illum ex! Velit ea corporis odit? Ea, incidunt delectus. Sapiente rerum neque error deleniti quis, et, quibusdam, est autem voluptate rem voluptas. Ratione soluta similique harum nihil vel. Quas inventore perferendis iusto explicabo animi eos ratione obcaecati. </p> </section> <footer class="footer"> 2020, 1분코딩 </footer> </div> <script src="js/main.js"></script> </body> </html> (() => { let yOffset = 0; // window.pageYOffset 대신 쓸 변수 let prevScrollHeight = 0; // 현재 스크롤 위치(yOffset)보다 이전에 위치한 스크롤 섹션들의 스크롤 높이값의 합 let currentScene = 0; // 현재 활성화된(눈 앞에 보고있는) 씬(scroll-section) let enterNewScene = false; // 새로운 scene이 시작된 순간 true let acc = 0.2; let delayedYOffset = 0; let rafId; let rafState; const sceneInfo = [ { // 0 type: 'normal', //heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅 scrollHeight: 0, objs:{ container:document.querySelector('#scroll-section-0') } }, { // 1 type: 'sticky', heightNum: 5, // 브라우저 높이의 5배로 scrollHeight 세팅 scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-1'), messageA: document.querySelector('#scroll-section-1 .main-message.a'), messageB: document.querySelector('#scroll-section-1 .main-message.b'), messageC: document.querySelector('#scroll-section-1 .main-message.c'), messageD: document.querySelector('#scroll-section-1 .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.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 }], 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 }] } }, { // 2 type: 'normal', // heightNum: 5, // type normal에서는 필요 없음 scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-2') } }, { // 3 type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-3'), messageA: document.querySelector('#scroll-section-3 .a'), messageB: document.querySelector('#scroll-section-3 .b'), messageC: document.querySelector('#scroll-section-3 .c'), pinB: document.querySelector('#scroll-section-3 .b .pin'), pinC: document.querySelector('#scroll-section-3 .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 }] } }, { // 4 type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-4'), canvasCaption: document.querySelector('.canvas-caption'), canvas: document.querySelector('.image-blend-canvas'), context: document.querySelector('.image-blend-canvas').getContext('2d'), imagesPath: [ './images/blend-image-1.jpg', './images/blend-image-2.jpg' ], images: [] }, values: { rect1X: [ 0, 0, { start: 0, end: 0 } ], rect2X: [ 0, 0, { start: 0, end: 0 } ], blendHeight: [ 0, 0, { start: 0, end: 0 } ], canvas_scale: [ 0, 0, { start: 0, end: 0 } ], canvasCaption_opacity: [ 0, 1, { start: 0, end: 0 } ], canvasCaption_translateY: [ 20, 0, { start: 0, end: 0 } ], rectStartY: 0 } } ]; function setCanvasImages() { let imgElem; for (let i = 0; i < sceneInfo[1].values.videoImageCount; i++) { imgElem = new Image(); imgElem.src = `./video/001/IMG_${6726 + i}.JPG`; sceneInfo[1].objs.videoImages.push(imgElem); } let imgElem2; for (let i = 0; i < sceneInfo[3].values.videoImageCount; i++) { imgElem2 = new Image(); imgElem2.src = `./video/002/IMG_${7027 + i}.JPG`; sceneInfo[3].objs.videoImages.push(imgElem2); } let imgElem3; for (let i = 0; i < sceneInfo[4].objs.imagesPath.length; i++) { imgElem3 = new Image(); imgElem3.src = sceneInfo[4].objs.imagesPath[i]; sceneInfo[4].objs.images.push(imgElem3); } } function checkMenu() { if (yOffset > 44) { document.body.classList.add('local-nav-sticky'); } else { document.body.classList.remove('local-nav-sticky'); } } 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[1].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`; sceneInfo[3].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`; } function calcValues(values, currentYOffset) { let rv; // 현재 씬(스크롤섹션)에서 스크롤된 범위를 비율로 구하기 const scrollHeight = sceneInfo[currentScene].scrollHeight; const scrollRatio = currentYOffset / scrollHeight; if (values.length === 4) { // 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]; } //console.log(scrollHeight); return rv; } //console.log(calcValues); 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 1: console.log(objs.messageA.style.opacity); console.log(objs.messageB.style.opacity); console.log(objs.messageC.style.opacity); console.log(objs.messageD.style.opacity); console.log(currentYOffset); console.log(scrollHeight); // 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 3: // console.log('2 play'); // let sequence2 = Math.round(calcValues(values.imageSequence, currentYOffset)); // objs.context.drawImage(objs.videoImages[sequence2], 0, 0); if (scrollRatio <= 0.5) { // in objs.canvas.style.opacity = calcValues(values.canvas_opacity_in, currentYOffset); } else { // out objs.canvas.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)})`; } // currentScene 3에서 쓰는 캔버스를 미리 그려주기 시작 if (scrollRatio > 0.9) { const objs = sceneInfo[4].objs; const values = sceneInfo[4].values; const widthRatio = window.innerWidth / objs.canvas.width; const heightRatio = window.innerHeight / objs.canvas.height; let canvasScaleRatio; if (widthRatio <= heightRatio) { // 캔버스보다 브라우저 창이 홀쭉한 경우 canvasScaleRatio = heightRatio; } else { // 캔버스보다 브라우저 창이 납작한 경우 canvasScaleRatio = widthRatio; } objs.canvas.style.transform = `scale(${canvasScaleRatio})`; objs.context.fillStyle = 'white'; objs.context.drawImage(objs.images[0], 0, 0); // 캔버스 사이즈에 맞춰 가정한 innerWidth와 innerHeight const recalculatedInnerWidth = document.body.offsetWidth / canvasScaleRatio; const recalculatedInnerHeight = window.innerHeight / canvasScaleRatio; 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( parseInt(values.rect1X[0]), 0, parseInt(whiteRectWidth), objs.canvas.height ); objs.context.fillRect( parseInt(values.rect2X[0]), 0, parseInt(whiteRectWidth), objs.canvas.height ); } break; case 4: // console.log('3 play'); let step = 0; // 가로/세로 모두 꽉 차게 하기 위해 여기서 세팅(계산 필요) const widthRatio = window.innerWidth / objs.canvas.width; const heightRatio = window.innerHeight / objs.canvas.height; let canvasScaleRatio; if (widthRatio <= heightRatio) { // 캔버스보다 브라우저 창이 홀쭉한 경우 canvasScaleRatio = heightRatio; } else { // 캔버스보다 브라우저 창이 납작한 경우 canvasScaleRatio = widthRatio; } objs.canvas.style.transform = `scale(${canvasScaleRatio})`; objs.context.fillStyle = 'white'; objs.context.drawImage(objs.images[0], 0, 0); // 캔버스 사이즈에 맞춰 가정한 innerWidth와 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].start = (window.innerHeight / 2) / scrollHeight; values.rect2X[2].start = (window.innerHeight / 2) / scrollHeight; 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( 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 ); if (scrollRatio < values.rect1X[2].end) { step = 1; // console.log('캔버스 닿기 전'); objs.canvas.classList.remove('sticky'); } else { step = 2; // console.log('캔버스 닿은 후'); // 이미지 블렌드 // values.blendHeight: [ 0, 0, { start: 0, end: 0 } ] values.blendHeight[0] = 0; values.blendHeight[1] = objs.canvas.height; values.blendHeight[2].start = values.rect1X[2].end; values.blendHeight[2].end = values.blendHeight[2].start + 0.2; const blendHeight = calcValues(values.blendHeight, currentYOffset); objs.context.drawImage(objs.images[1], 0, objs.canvas.height - blendHeight, objs.canvas.width, blendHeight, 0, objs.canvas.height - blendHeight, objs.canvas.width, blendHeight ); objs.canvas.classList.add('sticky'); objs.canvas.style.top = `${-(objs.canvas.height - objs.canvas.height * canvasScaleRatio) / 2}px`; if (scrollRatio > values.blendHeight[2].end) { values.canvas_scale[0] = canvasScaleRatio; values.canvas_scale[1] = document.body.offsetWidth / (1.5 * objs.canvas.width); values.canvas_scale[2].start = values.blendHeight[2].end; values.canvas_scale[2].end = values.canvas_scale[2].start + 0.2; objs.canvas.style.transform = `scale(${calcValues(values.canvas_scale, currentYOffset)})`; objs.canvas.style.marginTop = 0; } if (scrollRatio > values.canvas_scale[2].end && values.canvas_scale[2].end > 0) { objs.canvas.classList.remove('sticky'); objs.canvas.style.marginTop = `${scrollHeight * 0.4}px`; values.canvasCaption_opacity[2].start = values.canvas_scale[2].end; values.canvasCaption_opacity[2].end = values.canvasCaption_opacity[2].start + 0.1; values.canvasCaption_translateY[2].start = values.canvasCaption_opacity[2].start; values.canvasCaption_translateY[2].end = values.canvasCaption_opacity[2].end; objs.canvasCaption.style.opacity = calcValues(values.canvasCaption_opacity, currentYOffset); objs.canvasCaption.style.transform = `translate3d(0, ${calcValues(values.canvasCaption_translateY, currentYOffset)}%, 0)`; } } break; } } function scrollLoop() { enterNewScene = false; prevScrollHeight = 0; for (let i = 0; i < currentScene; i++) { prevScrollHeight += sceneInfo[i].scrollHeight; } if (delayedYOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) { enterNewScene = true; currentScene++; document.body.setAttribute('id', `show-scene-${currentScene}`); } if (delayedYOffset < prevScrollHeight) { enterNewScene = true; if (currentScene === 0) return; // 브라우저 바운스 효과로 인해 마이너스가 되는 것을 방지(모바일) currentScene--; document.body.setAttribute('id', `show-scene-${currentScene}`); } if (enterNewScene) return; playAnimation(); } function loop() { delayedYOffset = delayedYOffset + (yOffset - delayedYOffset) * acc; if (!enterNewScene) { if (currentScene === 1 || currentScene === 3) { const currentYOffset = delayedYOffset - prevScrollHeight; const objs = sceneInfo[currentScene].objs; const values = sceneInfo[currentScene].values; let sequence = Math.round(calcValues(values.imageSequence, currentYOffset)); if (objs.videoImages[sequence]) { objs.context.drawImage(objs.videoImages[sequence], 0, 0); } } } // 추가 코드 // home이나 end를 이용해 페이지 끝으로 고속 이동하면 body id가 제대로 인식 안되는 경우를 해결 // home 키로 페이지 맨 위로 갈 경우: scrollLoop와 첫 scene의 기본 캔버스 그리기 수행 /* if (delayedYOffset < 1) { scrollLoop(); sceneInfo[0].objs.canvas.style.opacity = 1; sceneInfo[0].objs.context.drawImage(sceneInfo[0].objs.videoImages[0], 0, 0); }*/ // end 키로 페이지 맨 아래로 갈 경우: 마지막 섹션은 스크롤 계산으로 위치 및 크기를 결정해야할 요소들이 많아서 1픽셀을 움직여주는 것으로 해결 if ((document.body.offsetHeight - window.innerHeight) - delayedYOffset < 1) { let tempYOffset = yOffset; scrollTo(0, tempYOffset - 1); } rafId = requestAnimationFrame(loop); if (Math.abs(yOffset - delayedYOffset) < 1) { cancelAnimationFrame(rafId); rafState = false; } } window.addEventListener('load', () => { document.body.classList.remove('before-load'); setLayout(); //sceneInfo[0].objs.context.drawImage(sceneInfo[0].objs.videoImages[0], 0, 0); let tempYOffset = yOffset; let tempScrollCount = 0; if (tempYOffset > 0) { let siId = setInterval(() => { scrollTo(0, tempYOffset); tempYOffset += 5; if (tempScrollCount > 20) { clearInterval(siId); } tempScrollCount++; }, 20); } window.addEventListener('scroll', () => { console.log(`yOffset: ${yOffset}`); yOffset = window.pageYOffset; scrollLoop(); checkMenu(); if (!rafState) { rafId = requestAnimationFrame(loop); rafState = true; } }); window.addEventListener('resize', () => { if (window.innerWidth > 900) { setLayout(); sceneInfo[4].values.rectStartY = 0; } if (currentScene === 4) { // 추가 코드 // Scene 3의 요소들은 위치나 크기가 미리 정해지지 않고 // 현재 창 사이즈나 스크롤 위치에 따라 가변적으로 변하기 때문에 // 리사이즈에 일일이 대응시키기가 까다롭습니다. // Scene 3에 진입 시점에 요소들의 위치와 크기가 결정이 되는 특징을 이용해서 // 현재 Scene이 3일 경우에는 좀 위로 스크롤이 되도록 해서 // Scene 3의 시작 지점 이전으로 돌리는 식으로 요소들의 레이아웃이 깨지는 현상을 방지해 줍니다. // 시작 지점 이전으로 스크롤을 이동 시키는 동작은 // 바로 위 518 라인의 자동 스크롤 코드를 그대로 활용했습니다. let tempYOffset = yOffset; let tempScrollCount = 0; if (tempYOffset > 0) { let siId = setInterval(() => { scrollTo(0, tempYOffset); tempYOffset -= 50; if (tempScrollCount > 20) { clearInterval(siId); } tempScrollCount++; }, 20); } } }); console.log(sceneInfo.length); window.addEventListener('orientationchange', () => { setTimeout(setLayout, 500); }); document.querySelector('.loading').addEventListener('transitionend', (e) => { document.body.removeChild(e.currentTarget); }); }); setCanvasImages(); })();
-
미해결홍정모의 따라하며 배우는 C++
5:15 예외클래스의 전달 과 캐치
5:15 경에 예외클래스를 전달하고 캐치시에 catch(Exception & e ) -> Exception 클래스의 print 실행 catch(ArrayException & e)-> ArrayException 클래스의 print 실행 로 reference로 받고있는데 이러면 음 .. 강의에서 말씀하시는것처럼 ' 객체잘림 '이라기 보다는 '부모클래스의 print에 virtual이 붙지않아 ,다형성으로 구현할때 오버라이딩이 안됐다. ' 라고 보는게 조금 더 맞지않나 싶은데 ( 12.9 객체잘림과 reference_wrapper 강의를 보면 객체잘림을 설명하실때 객체잘림은 refernce 나 포인터가 아닌 instance 끼리의 대입연산자(=) 를 할때 이루어지는것으로 보여지거든요) 이부분은 어떻게 생각하시나요?
-
해결됨애플 웹사이트 인터랙션 클론!
안녕하세요 '현재 활성시킬 씬 결정하기' 강좌편에서 문의가 있습니다.
안녕하세요 다름이 아니라 해당 '현재 활성시킬 씬 결정하기' 에서 코드를 입력하고 있는데 원하는 위치 스크롤 보다 400픽셀 앞에서 currentScene 변수가 변경하고 있어서 질문 드립니다. 아무리 확인해도 문제가 되는 부분이 없는거 같은데 확인 부탁드립니다. index. html <!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>AirMug Pro</title> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;900&display=swap" rel="stylesheet" /> <link rel="stylesheet" href="css/main.css" /> </head> <body id=""> <div class="contaner"> <nav class="global-nav"> <div class="global-nav-links"> <a href="#" class="global-nav-item">Room</a> <a href="#" class="global-nav-item">Ideas</a> <a href="#" class="global-nav-item">Stores</a> <a href="#" class="global-nav-item">Contact</a> </div> </nav> <nav class="local-nav"> <div class="local-nav-links"> <a href="#" class="product-name">AirMug Pro</a> <a href="#">개요</a> <a href="#">제품사양</a> <a href="#">구입하기</a> </div> </nav> <section class="scroll-section" id="scroll-section-0"> <h1>AirMug Pro</h1> <div class="sticky-elem main-message"> <p>온전히 빠져들게 하는<br />최고급 세라믹</p> </div> <div class="sticky-elem main-message"> <p>주변 맛을 느끼게 해주는<br />주변 맛 허용 모드</p> </div> <div class="sticky-elem main-message"> <p>온중일 편안한<br />맞춤형 손잡이</p> </div> <div class="sticky-elem main-message"> <p>새롭게 입가를<br />찾아온 매혹</p> </div> </section> <section class="scroll-section" id="scroll-section-1"> <p class="description"> <strong> 보통 스크롤 영역 </strong> Lorem ipsum dolor sit amet consectetur adipisicing elit. Ullam, soluta quia? Soluta repellat consequatur aliquam sit deleniti atque qui nemo, molestiae, veritatis repudiandae, earum tempora mollitia dolores? Ipsa a ea ab nostrum ullam beatae, natus, nulla recusandae praesentium corporis magni, atque impedit error aliquid consequatur. Culpa cupiditate velit molestias sapiente! Aspernatur molestiae facilis repudiandae, fugiat nulla, hic culpa esse impedit eos, quam sapiente? Laboriosam ut perferendis atque velit sint, non mollitia? Provident cum obcaecati ex illo asperiores accusantium harum voluptas doloremque inventore possimus eum tenetur tempora ipsam debitis natus nulla similique veritatis recusandae, voluptatum accusamus quia adipisci perspiciatis. Itaque architecto eius veritatis rem quae facere illo ipsum error, explicabo nesciunt eos quibusdam dolorem magni impedit, magnam amet voluptates fugit assumenda deserunt consequuntur numquam. Quasi hic nisi molestias enim fugiat vel eveniet modi quisquam suscipit? Recusandae voluptates expedita exercitationem excepturi velit repellat error similique porro deleniti architecto tenetur quaerat corporis culpa, libero, neque facilis ullam eius reiciendis itaque et fugiat eum! Magnam totam at commodi nesciunt, quae dolores, praesentium labore, maxime perspiciatis iure omnis sed assumenda laborum harum. Dolor, voluptatem id. Eos qui, quidem assumenda sit asperiores quia beatae consequuntur necessitatibus dignissimos architecto, aspernatur facere ut porro cum repellat. Tempora, minima? </p> </section> <section class="scroll-section" id="scroll-section-2"> <div class="sticky-elem main-message"> <p> <small> 편안한 촉감 </small> 입과 하나 되다 </p> </div> <div class="sticky-elem desc-message"> <p> 편안한 목넘김을 완성하는 디테일한 여러 구성 요소들, 우리는 이를 하나하나 새롭게 살피고 재구성하는 과정을 거쳐 새로운 수준의 머그, AirMug Pro를 만들었습니다. 입에 뭔가 댔다는 감각은 어느새 사라지고 오롯이 당신과 음료만 남게 되죠. </p> <div class="pin"></div> </div> <div class="sticky-elem desc-message"> <p>디자인 앤 퀄리티 오브 스웨덴,<br />메이드 인 차이나</p> <div class="pin"></div> </div> </section> <section class="scroll-section" id="scroll-section-3"> <p class="mid-message"> <strong>Retina 머그</strong><br /> 아이디어를 광활하게 펼칠<br /> 아름답고 부드러운 음료 공간. </p> <!-- <canvas class="image-blend-canvas" width="1920" height="1080"></canvas> --> <p class="canvas-caption"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet at fuga quae perspiciatis veniam impedit et, ratione est optio porro. Incidunt aperiam nemo voluptas odit quisquam harum in mollitia. Incidunt minima iusto in corporis, dolores velit. Autem, sit dolorum inventore a rerum distinctio vero illo magni possimus temporibus dolores neque adipisci, repudiandae repellat. Ducimus accusamus similique quas earum laborum. Autem tempora repellendus asperiores illum ex! Velit ea corporis odit? Ea, incidunt delectus. Sapiente rerum neque error deleniti quis, et, quibusdam, est autem voluptate rem voluptas. Ratione soluta similique harum nihil vel. Quas inventore perferendis iusto explicabo animi eos ratione obcaecati. </p> </section> <footer class="footer"> 2020, 1분코딩 </footer> <script src="js/main.js"></script> </div> </body> </html> main.js (() => { let yOffset = 0; // window.pageYOffset 대신 쓸 변수 let prevScrollHeight = 0; // 현재 스크롤 위치(yOffSet)보다 이전에 위치한 스킄롤 섹션들의 스크롤 높이값의 합 let currentScene = 0; // 현재 활성화된 (눈앞에 보고 있는) 씬(scroll-section) const sceneInfo = [ { // 0 type: "sticky", heightNum: 5, // 브라우저 높이의 5배로 scrollHeght 세팅 scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-0"), }, }, { // 1 type: "normal", heightNum: 5, // 브라우저 높이의 5배로 scrollHeght 세팅 scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-1"), }, }, { // 2 type: "sticky", heightNum: 5, // 브라우저 높이의 5배로 scrollHeght 세팅 scrollHeight: 0, objs: { container: document.querySelector("#scroll-section-2"), }, }, { // 3 type: "sticky", heightNum: 5, // 브라우저 높이의 5배로 scrollHeght 세팅 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`; } } /** * 현재 보고 있는 화면에서 스크롤 높이 구하기 */ function scrollLoop() { prevScrollHeight = 0; for (let i = 0; i < currentScene; i++) { prevScrollHeight = prevScrollHeight + sceneInfo[i].scrollHeight; } if (yOffset > prevScrollHeight + sceneInfo[currentScene].scrollHeight) { currentScene++; } if (yOffset < prevScrollHeight) { if (currentScene === 0) { // 브라우저 바운스 효과로 인한 마이너스가 되는것을 방지 (모바일) return; } currentScene--; } console.log(currentScene); } window.addEventListener("resize", setLayout); window.addEventListener("scroll", () => { yOffset = window.pageYOffset; scrollLoop(); }); setLayout(); })(); main.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; margin: 0; } p { line-height: 1.6; } a { color: rgb(29, 29, 31); text-decoration: none; } .global-nav { position: absolute; top: 0; left: 0; width: 100%; height: 44px; padding: 0 1rem; } .local-nav { position: absolute; top: 45px; /* .global-nav 보다 1px 위에 */ left: 0; width: 100%; height: 52px; border-bottom: 1px solid #ddd; } .global-nav-links, .local-nav-links { display: flex; align-items: center; max-width: 1000px; height: 100%; margin: 0 auto; } .local-nav-links a:not(.product-name) { margin-left: 2em; } .local-nav-links .product-name { margin-right: auto; font-size: 1.4rem; font-weight: bold; } .local-nav-links a { font-size: 0.8rem; } .global-nav-links { justify-content: space-between; } /* */ .scroll-section { position: relative; border: 3px solid red; padding-top: 50vh; } #scroll-section-0 h1 { position: relative; 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 { font-weight: bold; text-align: center; line-height: 1.2; } /* */ .main-message small { display: block; margin-bottom: 0.5em; font-size: 1.2rem; } #scroll-section-2 .main-message { font-size: 3.5rem; } .description { font-size: 2rem; max-width: 1000px; 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%; } .pin { width: 1px; height: 100px; background-color: rgb(29, 29, 31); } .mid-message { padding: 0 1rem; font-size: 2rem; color: #888; max-width: 1000px; margin: 0 auto; } .mid-message strong { color: rgb(29, 29, 31); } .canvas-caption { color: #888; padding: 0 1rem; font-size: 1.2rem; max-width: 1000px; margin: 0 auto; } .footer { display: flex; align-items: center; justify-content: center; height: 7rem; color: white; background-color: darkorange; } @media (min-width: 1024px) { #scroll-section-0 h1 { font-size: 9vw; } .main-message { font-size: 4vw; } .description { margin: 0 auto; } .description strong { font-size: 6rem; } #scroll-section-2 .main-message { font-size: 6vw; } .main-message small { font-size: 1.5vw; } .desc-message { width: 20%; } .mid-message { font-size: 4vw; } .canvas-caption { font-size: 2rem; } } /* */ .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; }
-
미해결React로 NodeBird SNS 만들기
리뉴얼 강좌 쿠폰
조현영의 react nodebird에 새로운 리뉴얼 강의가 출시했는데 제가 알기론 새로운 강의가 출실할시 기존에 react nodebird강의가 있는 분은 50% 할인 쿠폰이 있다고 들었습니다. 하지만 쿠폰은 오지가 않아 저만 못받은것인지 아니면 받는데 시간이 걸리는지 잘 모르겠습니다. 확인 부탁드립니다.
-
미해결함수형 프로그래밍과 JavaScript ES6+
강의 내용 정리
안녕하세요 좋은 강의 감사드립니다. 강의를 듣고 개인적으로 정리한 내용을 깃헙이나 블로그에 올려도 괜찮을까요??
-
미해결파이썬 무료 강의 (활용편2) - GUI 프로그래밍 (4시간)
강의를 통해 많은 도움을 받았습니다.
안녕하세요 나도코딩 강좌를 며칠간 저녁 시간을 쪼개어 처음부터 끝까지 보고 따라하면서 정말 많은 도움을 받았습니다. 사실 이미지 합치는 프로그램을 따라하면서 궁금한 점이 있어서 이렇게 게시판에 글을 올리게 되었습니다. 질문 내용은 다음과 같습니다. 이미지 리사이징을 한 후에 높이가 2500 이상이 될 경우에는 더이상 이미지를 합치지 않고 다음 파일명으로 저장을 하고 싶을 때에는 어떻게 하면 좋을까요? 예를들어 이미지 리사이징을 한 후에 파일의 total_height가 10000일 경우에 desk 001.jpg, desk 002.jpg, desk 003.jpg, desk 004.jpg 등으로 가능하게 하려면 코딩을 어떻게 하면 좋을까요? 오늘 하루종일 여기저기 살펴보고 그랬는데 잘 모르겠어서 이렇게 문의를 드리게 되었습니다. 감사합니다.
-
해결됨스프링 웹 MVC
파일 다운로드 OutputStream / ResponseEntity 차이 질문입니다
안녕하세요 기선님, 항상 좋은 강의 감사드립니다. 강의를 들으면서 오늘 처음으로 궁금한 점이 생겨 질문 드립니다. 저는 강의를 수강하기 전에 파일 다운로드 기능을 구현할 때 아래와 같은 형식으로 Stream 관련 api을 사용하여 다운로드 기능을 구현했었는데요. 아래는 강의를 들으면서 한 코드입니다. 강의를 들으며 오늘 처음 ResponseEntity 를 사용해보면서 문득 궁금점이 생겨, 혼자 예제를 만들어 테스트를 해봤습니다. 혹시 위 두 방식 사이에서 차이점이 있는지 궁금합니다. Stream을 통해 다운로드를 구현하는 방식과 ResponseEntity Body에 File Resource 를 넣어 반환하는 방식이 결과적으로 파일 다운로드하는 것은 같고, 단지 구현하는 방식의 차이일까요?
-
미해결누구나 따라하면서 배우는 JSP 커뮤니티 게시판 만들기
user.getUserID() 질문이요
loginAction.jsp 에 있는 int result = userDAO.login(user.getUserID(), user.getUserPassword()); // 여기서 user.getUserID() 한거에서 user. 는 어디에 있는 user인가요? 설마 user는 user패지키 이름 과 일치해야 하고user패키지에 있는 getUserID() 메서드를 실행 시키는거라서 user.getUserID() 라고 적은 건가요?
-
미해결[백문이불여일타] 데이터 분석을 위한 고급 SQL
between 궁금한 점이 있습니다.
between A and B 라면 A <= X <= B 일까요? WHERE 절에서 쓸 때와 JOIN 절에서 쓸 때 모두 A <= X <= B 인지 궁금합니다. 감사합니다!