미해결
애플 웹사이트 인터랙션 클론!
안녕하세요. 코드를 재구성하면서 따라가고 있는데 마지막 scroll-section-3에서 문자가 보이는 화면에서 새로고침을 했을 때, pageYOffset이 제자리에 있지 않고 위로 이동하는 현상이 발생합니다. 디버깅을 한다고 했는데 도저히 모르겠어서 질문드립니다. 도움 주시면 감사하겠습니다. # index.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 rel="stylesheet" href="style.css"> <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;900&display=swap" rel="stylesheet"> </head> <body class="before-load"> <div class="loading"> <svg class="loading-circle"> <circle cx="50%" cy="50%" r="25"></circle> </svg> </div> <nav class="global-nav"> <div class="global-nav-links"> <a href="#">Rooms</a> <a href="#">Ideas</a> <a href="#">Stores</a> <a href="#">Contact</a> </div> </nav> <nav class="local-nav"> <div class="local-nav-links"> <a href="#" class="product-name">AirMug Pro</a> <div class="local-nav-right"> <a href="#">Overview</a> <a href="#">Specification</a> <a href="#">Purchase</a> </div> </div> </nav> <div class="container"> <div class="scroll-section" id="scroll-section-0"> <div class="sticky-elem sticky-elem-canvas"> <canvas id="video-canvas-0" width="1920" height="1080"></canvas> </div> <h1>AirMug Pro</h1> <div class="sticky-elem main-message" id="main-message-a"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eveniet, quisquam. </div> <div class="sticky-elem main-message" id="main-message-b"> Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eaque, mollitia. </div> <div class="sticky-elem main-message" id="main-message-c"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Cupiditate, dolorem. </div> <div class="sticky-elem main-message" id="main-message-d"> Lorem ipsum dolor sit, amet consectetur adipisicing elit. Obcaecati cumque, vitae iste aperiam tempora impedit. Voluptatem nobis nihil deleniti sint! </div> </div> <div class="scroll-section" id="scroll-section-1"> <p class="description"> <strong>AirMug Pro</strong> Lorem ipsum dolor sit amet consectetur adipisicing elit. Dicta commodi illo voluptates quae, reiciendis laborum quam beatae similique recusandae itaque. Exercitationem, aspernatur quidem, qui alias eveniet aliquid neque numquam labore voluptates, harum ipsum error quam magni voluptatibus atque repellat pariatur assumenda deleniti quaerat reprehenderit. Tempore quaerat soluta praesentium esse error id a quod voluptate minima asperiores maxime repudiandae nobis molestias ipsam unde sunt consectetur quidem modi tempora enim, quas voluptas ad. Amet eveniet quas inventore excepturi tempore nisi ullam sed iusto harum, voluptatum earum libero, dolorum omnis. Voluptatum, sit. Repellendus explicabo aut, modi dolorum nihil delectus nam minus mollitia quaerat. </p> </div> <div class="scroll-section" id="scroll-section-2"> <div class="sticky-elem sticky-elem-canvas"> <canvas id="video-canvas-1" width="1920" height="1080"></canvas> </div> <div class="sticky-elem desc-message" id="desc-message-a"> Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ipsam, quidem unde? Delectus optio architecto consectetur accusantium fugiat odit animi doloremque. <div class="pin"></div> </div> <div class="sticky-elem desc-message" id="desc-message-b"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quos, consequuntur? Suscipit ut maiores voluptatem, pariatur in consequatur sapiente delectus iure odio ipsa soluta atque modi! <div class="pin"></div> </div> <div class="sticky-elem desc-message" id="desc-message-c"> Lorem ipsum dolor sit amet consectetur adipisicing elit. Eum dolore ut sunt, inventore distinctio saepe sit! Iure fugit neque, ducimus enim rem odit maiores consectetur. <div class="pin"></div> </div> </div> <div class="scroll-section" id="scroll-section-3"> <p class="mid-message"> <strong>Retina Mug</strong><br> Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi, ratione. </p> <canvas class="image-blend-canvas" id="video-canvas-2" width="1920" height="1080"></canvas> <p class="canvas-caption"> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusantium unde molestiae aliquam sit, incidunt rerum aliquid sunt animi quasi provident sapiente obcaecati autem maiores ex libero minima tempore? Cumque eligendi recusandae sint tenetur ducimus iusto, excepturi ullam in veritatis maxime, libero dolores eveniet dolor odit reiciendis aliquam itaque? Distinctio, corporis dolorem. Delectus iure asperiores, quia veritatis modi sequi aperiam iusto nulla, et ea non nihil consectetur, eos nemo. Obcaecati perferendis ut assumenda distinctio est nam autem deleniti. Culpa beatae recusandae et incidunt iste dolorem error quia, fugit dicta in, tenetur dolore ad ab? Tenetur, eius. Mollitia beatae esse quibusdam nam doloremque fuga architecto rerum rem? Minus quae praesentium iusto rem maxime tempora hic distinctio, est non laborum ipsam cupiditate quis, quod totam at itaque perspiciatis repudiandae nesciunt vero officiis natus doloribus inventore unde? Dolores amet molestiae cupiditate aliquam ratione doloribus enim libero odio maiores atque inventore doloremque officia consequuntur ut, pariatur quis dolorum fugiat. Placeat dolore earum aperiam odit beatae perspiciatis, at provident pariatur recusandae neque facilis exercitationem officia unde consectetur quam assumenda. Ex vero quis fugit magnam, excepturi, voluptates debitis ipsum dolorem iste incidunt natus laboriosam dolores quibusdam. Accusantium numquam facere ullam quos totam nam aliquid magni delectus laudantium! </p> </div> </div> <footer class="footer">Copyright by Whi</footer> <script src="main.js"></script> </body> </html> # main.js class Website { constructor() { this.enterNewScene = false; this.acc = 0.1; this.delayedYOffset = 0; this.rafState = false; this.rafId; this.sceneInfo = [ { type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-0'), localNav: document.querySelector('.local-nav'), canvas: document.querySelector('#video-canvas-0'), context: document.querySelector('#video-canvas-0').getContext('2d'), messageA: document.querySelector('#main-message-a'), messageB: document.querySelector('#main-message-b'), messageC: document.querySelector('#main-message-c'), messageD: document.querySelector('#main-message-d'), videoImages: [], }, 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_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}], canvas_opacity: [1, 0, {start: 0.9, end: 1.0}], canvas: [0, 299, {start: 0, end: 1}], }, }, { type: 'normal', scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-1'), } }, { type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-2'), canvas: document.querySelector('#video-canvas-1'), context: document.querySelector('#video-canvas-1').getContext('2d'), messageA: document.querySelector('#desc-message-a'), messageB: document.querySelector('#desc-message-b'), messageC: document.querySelector('#desc-message-c'), pinA: document.querySelector('#desc-message-a .pin'), pinB: document.querySelector('#desc-message-b .pin'), pinC: document.querySelector('#desc-message-c .pin'), videoImages: [], }, values: { 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_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}], messageA_translateY_in: [20, 0, {start: 0.25, end: 0.3}], messageB_translateY_in: [30, 0, {start: 0.6, end: 0.65}], messageC_translateY_in: [30, 0, {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}], pinA_scaleY: [0.5, 1, {start: 0.25, end: 0.3}], pinB_scaleY: [0.5, 1, {start: 0.6, end: 0.80}], pinC_scaleY: [0.5, 1, {start: 0.87, end: 0.92}], canvas_opacity: [1, 0, {start: 0.9, end: 1.0}], canvas: [0, 959, {start: 0, end: 1}], } }, { type: 'sticky', heightNum: 5, scrollHeight: 0, objs: { container: document.querySelector('#scroll-section-3'), canvas: document.querySelector('#video-canvas-2'), context: document.querySelector('#video-canvas-2').getContext('2d'), images: [], }, values: { rect1X: [0, 0, {start: 0, end: 0}], rect2X: [0, 0, {start: 0, end: 0}], rectStartY: 0, blendHeight: [0, 0, {start: 0, end: 0}], canvas_scale: [0, 0, {start: 0, end: 0}], }, } ] this.prepareVideoImages(); this.addEventListener(); } setLayout() { for (let idx = 0; idx < this.sceneInfo.length; idx++) { const info = this.sceneInfo[idx]; if (info.type === 'sticky') { info.scrollHeight = info.heightNum * window.innerHeight; } else { info.scrollHeight = info.objs.container.offsetHeight; } info.objs.container.style.height = `${info.heightNum * window.innerHeight}px`; } let totalScrollHeight = 0; this.currentScene = 0; for (let idx = 0; idx < this.sceneInfo.length; idx++) { totalScrollHeight += this.sceneInfo[idx].scrollHeight; if (totalScrollHeight > this.yOffset) { this.currentScene = idx; break; } } document.body.setAttribute('id', `show-scene-${this.currentScene}`); const heightRatio = window.innerHeight / 1080; this.sceneInfo[0].objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${heightRatio})`; } scrollLoop() { if (this.enterNewScene) { return } this.prevScrollHeight = 0; for (let idx = 0; idx < this.currentScene; idx++) { this.prevScrollHeight += this.sceneInfo[idx].scrollHeight; } if (this.yOffset > this.prevScrollHeight + this.sceneInfo[this.currentScene].scrollHeight) { this.enterNewScene = true; this.currentScene += 1; // TODO: REFACTOR this.prevScrollHeight = 0; for (let idx = 0; idx < this.currentScene; idx++) { this.prevScrollHeight += this.sceneInfo[idx].scrollHeight; } } else if (this.yOffset < this.prevScrollHeight) { this.enterNewScene = true; this.currentScene -= 1; this.prevScrollHeight = 0; for (let idx = 0; idx < this.currentScene; idx++) { this.prevScrollHeight += this.sceneInfo[idx].scrollHeight; } } document.body.setAttribute('id', `show-scene-${this.currentScene}`); this.playAnimation(); this.enterNewScene = false; } playAnimation() { const sceneScrollHeight = this.yOffset - this.prevScrollHeight; const sceneScrollRatio = sceneScrollHeight / this.sceneInfo[this.currentScene].scrollHeight; const objs = this.sceneInfo[this.currentScene].objs; const values = this.sceneInfo[this.currentScene].values; let imgIdx; let canvasHeightRatio; let canvasWidthRatio; let canvasRescaleRatio; switch (this.currentScene) { case 0: imgIdx = Math.round(this.calcValues(values.canvas, sceneScrollRatio)); canvasHeightRatio = window.innerHeight / objs.canvas.height; canvasWidthRatio = window.innerWidth / objs.canvas.width; canvasRescaleRatio = canvasHeightRatio; if (canvasWidthRatio > canvasHeightRatio) { canvasRescaleRatio = canvasWidthRatio; } objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${canvasRescaleRatio})`; // objs.context.drawImage(objs.videoImages[imgIdx], 0, 0); if (sceneScrollRatio < 0.22) { objs.messageA.style.opacity = this.calcValues(values.messageA_opacity_in, sceneScrollRatio); } else { objs.messageA.style.opacity = this.calcValues(values.messageA_opacity_out, sceneScrollRatio); } if (sceneScrollRatio < 0.42) { objs.messageB.style.opacity = this.calcValues(values.messageB_opacity_in, sceneScrollRatio); } else { objs.messageB.style.opacity = this.calcValues(values.messageB_opacity_out, sceneScrollRatio); } if (sceneScrollRatio < 0.62) { objs.messageC.style.opacity = this.calcValues(values.messageC_opacity_in, sceneScrollRatio); } else { objs.messageC.style.opacity = this.calcValues(values.messageC_opacity_out, sceneScrollRatio); } if (sceneScrollRatio < 0.82) { objs.messageD.style.opacity = this.calcValues(values.messageD_opacity_in, sceneScrollRatio); } else { objs.messageD.style.opacity = this.calcValues(values.messageD_opacity_out, sceneScrollRatio); } if (sceneScrollRatio > 0.85) { objs.canvas.style.opacity = this.calcValues(values.canvas_opacity, sceneScrollRatio); } break; case 1: break; case 2: imgIdx = Math.round(this.calcValues(values.canvas, sceneScrollRatio)); canvasHeightRatio = window.innerHeight / objs.canvas.height; canvasWidthRatio = window.innerWidth / objs.canvas.width; canvasRescaleRatio = canvasHeightRatio; if (canvasWidthRatio > canvasHeightRatio) { canvasRescaleRatio = canvasWidthRatio; } objs.canvas.style.transform = `translate3d(-50%, -50%, 0) scale(${canvasRescaleRatio})`; // objs.context.drawImage(objs.videoImages[imgIdx], 0, 0); if (sceneScrollRatio < 0.35) { objs.messageA.style.opacity = this.calcValues(values.messageA_opacity_in, sceneScrollRatio); objs.messageA.style.transform = `translate3d(0, ${this.calcValues(values.messageA_translateY_in, sceneScrollRatio)}%, 0)`; objs.pinA.style.transform = `scaleY(${this.calcValues(values.pinA_scaleY, sceneScrollRatio)})`; } else { objs.messageA.style.opacity = this.calcValues(values.messageA_opacity_out, sceneScrollRatio); objs.messageA.style.transform = `translate3d(0, ${this.calcValues(values.messageA_translateY_out, sceneScrollRatio)}%, 0)`; objs.pinA.style.transform = `scaleY(${this.calcValues(values.pinA_scaleY, sceneScrollRatio)})`; } if (sceneScrollRatio < 0.67) { objs.messageB.style.opacity = this.calcValues(values.messageB_opacity_in, sceneScrollRatio); objs.messageB.style.transform = `translate3d(0, ${this.calcValues(values.messageB_translateY_in, sceneScrollRatio)}%, 0)`; objs.pinB.style.transform = `scaleY(${this.calcValues(values.pinB_scaleY, sceneScrollRatio)})`; } else { objs.messageB.style.opacity = this.calcValues(values.messageB_opacity_out, sceneScrollRatio); objs.messageB.style.transform = `translate3d(0, ${this.calcValues(values.messageB_translateY_out, sceneScrollRatio)}%, 0)`; objs.pinB.style.transform = `scaleY(${this.calcValues(values.pinB_scaleY, sceneScrollRatio)})`; } if (sceneScrollRatio < 0.94) { objs.messageC.style.opacity = this.calcValues(values.messageC_opacity_in, sceneScrollRatio); objs.messageC.style.transform = `translate3d(0, ${this.calcValues(values.messageC_translateY_in, sceneScrollRatio)}%, 0)`; objs.pinC.style.transform = `scaleY(${this.calcValues(values.pinC_scaleY, sceneScrollRatio)})`; } else { objs.messageC.style.opacity = this.calcValues(values.messageC_opacity_out, sceneScrollRatio); objs.messageC.style.transform = `translate3d(0, ${this.calcValues(values.messageC_translateY_out, sceneScrollRatio)}%, 0)`; objs.pinC.style.transform = `scaleY(${this.calcValues(values.pinC_scaleY, sceneScrollRatio)})`; } if (sceneScrollRatio > 0.85) { objs.canvas.style.opacity = this.calcValues(values.canvas_opacity, sceneScrollRatio); } break; case 3: canvasHeightRatio = window.innerHeight / objs.canvas.height; canvasWidthRatio = window.innerWidth / objs.canvas.width; canvasRescaleRatio = canvasHeightRatio; if (canvasWidthRatio > canvasHeightRatio) { canvasRescaleRatio = canvasWidthRatio; } const recalculatedInnerWidth = window.innerWidth / canvasRescaleRatio; const recalculatedInnerHeight = window.innerHeight / canvasRescaleRatio; if (!values.rectStartY) { values.rectStartY = objs.canvas.offsetTop + (objs.canvas.height - objs.canvas.height * canvasRescaleRatio) / 2; values.rect1X[2].start = (window.innerHeight / 2) / this.sceneInfo[this.currentScene].scrollHeight; values.rect1X[2].end = values.rectStartY / this.sceneInfo[this.currentScene].scrollHeight; values.rect2X[2].start = (window.innerHeight / 2) / this.sceneInfo[this.currentScene].scrollHeight; values.rect2X[2].end = values.rectStartY / this.sceneInfo[this.currentScene].scrollHeight; } objs.canvas.style.transform = `scale(${canvasRescaleRatio})`; objs.context.fillStyle = 'white'; objs.context.drawImage(objs.images[0], 0, 0); const whiteRectWidth = 0.15 * recalculatedInnerWidth; 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(this.calcValues(values.rect1X, sceneScrollRatio)), 0, parseInt(whiteRectWidth), objs.canvas.height); objs.context.fillRect( parseInt(this.calcValues(values.rect2X, sceneScrollRatio)), 0, parseInt(whiteRectWidth), objs.canvas.height); if (sceneScrollRatio < values.rect1X[2].end) { objs.canvas.classList.remove('sticky'); } else { objs.canvas.classList.add('sticky'); objs.canvas.style.top = `-${(objs.canvas.height - objs.canvas.height * canvasRescaleRatio) / 2}px`; if (!values.blendHeight[1]) { 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 blendImageheight = this.calcValues(values.blendHeight, sceneScrollRatio); objs.context.drawImage( objs.images[1], 0, objs.canvas.height - blendImageheight, objs.canvas.width, blendImageheight, 0, objs.canvas.height - blendImageheight, objs.canvas.width, blendImageheight); if (values.blendHeight[2].end < sceneScrollRatio) { if (!values.canvas_scale[0]) { values.canvas_scale[0] = canvasRescaleRatio; values.canvas_scale[1] = 0.5; 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(${this.calcValues(values.canvas_scale, sceneScrollRatio)})`; if (values.canvas_scale[2].end < sceneScrollRatio) { objs.canvas.classList.remove('sticky'); objs.canvas.style.marginTop = `${0.4 * this.sceneInfo[this.currentScene].scrollHeight}px`; } else { objs.canvas.style.marginTop = 0; } } } break; } } calcValues(data, currPos) { let result; const [startVal, endVal, valRange] = data; const { start: startRange, end: endRange } = valRange; if (currPos <= startRange) { result = startVal; } else if (endRange <= currPos) { result = endVal; } else { result = startVal + (endVal - startVal) * (currPos - startRange) / (endRange - startRange) } return result; } prepareVideoImages() { let imgElem; for (let idx = 0; idx < 300; idx++) { imgElem = new Image(); imgElem.src = `./video/001/IMG_${6726 + idx}.JPG`; this.sceneInfo[0].objs.videoImages.push(imgElem); } let imgElem2; for (let idx = 0; idx < 960; idx++) { imgElem2 = new Image(); imgElem2.src = `./video/002/IMG_${7027 + idx}.JPG`; this.sceneInfo[2].objs.videoImages.push(imgElem2); } let imgElem3; const imgPaths = ['./images/blend-image-1.jpg', './images/blend-image-2.jpg'] for (const imgPath of imgPaths) { imgElem3 = new Image(); imgElem3.src = imgPath; this.sceneInfo[3].objs.images.push(imgElem3); } } loop() { this.delayedYOffset = this.delayedYOffset + (this.yOffset - this.delayedYOffset) * this.acc; if (!this.enterNewScene) { if (this.currentScene === 0 || this.currentScene === 2) { const sceneScrollHeight = this.delayedYOffset - this.prevScrollHeight; const sceneScrollRatio = sceneScrollHeight / this.sceneInfo[this.currentScene].scrollHeight; const values = this.sceneInfo[this.currentScene].values; const objs = this.sceneInfo[this.currentScene].objs; let imgIdx = parseInt(this.calcValues(values.canvas, sceneScrollRatio)); if (objs.videoImages[imgIdx]) { objs.context.drawImage(objs.videoImages[imgIdx], 0, 0); } } } this.rafId = requestAnimationFrame(this.loop.bind(this)); if (Math.abs(this.yOffset - this.delayedYOffset) < 1) { cancelAnimationFrame(this.rafId) this.rafState = false; } } checkMenu() { if (this.yOffset > 44) { this.sceneInfo[0].objs.localNav.classList.add('local-nav-sticky'); } else { this.sceneInfo[0].objs.localNav.classList.remove('local-nav-sticky'); } } addEventListener() { window.addEventListener('load', () => { document.body.classList.remove('before-load'); this.setLayout(); debugger; // this.sceneInfo[0].objs.context.drawImage(this.sceneInfo[0].objs.videoImages[0], 0, 0); this.yOffset = window.pageYOffset; console.log('yoffset', this.yOffset) let tempYOffSet = this.yOffset; let tempScrollCount = 0; if (tempYOffSet > 0) { let siId = setInterval(() => { window.scrollTo(0, tempYOffSet); tempYOffSet += 5; tempScrollCount++; if (tempScrollCount > 20) { clearInterval(siId); } }, 20) } window.addEventListener('scroll', () => { this.yOffset = window.pageYOffset; this.scrollLoop(); this.checkMenu(); if (!this.rafState) { this.rafId = requestAnimationFrame(this.loop.bind(this)); this.rafState = true; } }) document.querySelector('.loading').addEventListener('transitionend', (e) => { document.body.removeChild(e.currentTarget); }) }) } } const website = new Website(); # style.css html { font-size: 12px; font-family: 'Noto Sans KR', sans-serif; } body { overflow-x: hidden; position: relative; margin: 0; } div, span, article, section, header, footer, aside, p, ul, li, fieldset, legend, label, a, nav, form { box-sizing: border-box; } body * { overflow-x: hidden; } body.before-load { overflow: hidden; } .before-load .global-nav, .before-load .local-nav, .before-load .container, .before-load .footer { display: none; } .loading { position: fixed; display: flex; align-items: center; justify-content: center; top: 0; right: 0; bottom: 0; left: 0; z-index: 100; opacity: 0; background: white; transition: 2.0s; } .before-load .loading { opacity: 1; } @keyframes loading-circle-ani { 0% { stroke-dashoffset: 157; } 75% { stroke-dashoffset: -147; } 100% { stroke-dashoffset: -157; } } @keyframes loading-spin { 100% { transform: rotate(360deg); } } .loading-circle { width: 54px; height: 54px; animation: loading-spin 3s infinite; } .loading-circle circle { stroke: black; stroke-width: 4; stroke-dasharray: 157; stroke-dashoffset: 0; fill: transparent; animation: loading-circle-ani 3s infinite; } div { box-sizing: border-box; } a { text-decoration: none; color: black; } .global-nav { position: absolute; width: 100%; top: 0; left: 0; height: 44px; z-index: 5; } .global-nav-links, .local-nav-links { display: flex; align-items: center; justify-content: space-between; max-width: 1000px; margin: 0 auto; padding: 0 1rem; height: 100%; } .local-nav { position: absolute; width: 100%; left: 0; top: 50px; height: 55px; z-index: 6; border-bottom: 1px solid #888888; } .local-nav-sticky { position: fixed; top: 0; background: rgba(255, 255, 255, 0.1); backdrop-filter: saturate(180%) blur(15px); } .local-nav-right a { margin-left: 2em; } .product-name { font-size: 1.3rem; font-weight: 700; } .footer { position: relative; bottom: 0; height: 45px; width: 100%; background: orange; display: flex; align-items: center; justify-content: center; } .scroll-section { position: relative; padding-top: 50vh; width: 100%; margin: 0 auto; } .scroll-section h1 { font-size: 3rem; top: -10vh; text-align: center; position: relative; } .main-message { top: 45vh; font-size: 1.3rem; text-align: center; margin: 0 auto; opacity: 0; } .sticky-elem { position: fixed; left: 0; width: 100%; display: none; } .sticky-elem-canvas { top: 0; height: 100%; } .sticky-elem-canvas canvas { position: absolute; left: 50%; top: 50%; } .description { font-size: 1.3rem; max-width: 1000px; margin: 0 auto; padding: 0 1rem; } .description strong { font-size: 3em; float: left; margin-right: 0.5em; } .mid-message { font-size: 1.4rem; text-align: center; margin: 0 auto; padding-left: 1rem; padding-right: 1rem; } .mid-message .strong { font-size: 3em; font-weight: 600; } .image-blend-canvas.sticky{ position: fixed; top: 0; } #scroll-section-3 { display: flex; flex-direction: column; align-items: center; } .canvas-caption { font-size: 1.2rem; color: rgb(41, 37, 37); max-width: 1000px; margin: 0 auto; margin-top: -10vh; padding: 0 1rem; padding-bottom: 3rem; } .desc-message { font-size: 1rem; width: 20%; } #desc-message-a { left: 40%; top: 30%; } #desc-message-b { left: 40%; top: 25%; } #desc-message-c { left: 40%; top: 10%; } #show-scene-0 #scroll-section-0 .sticky-elem { display: block; } #show-scene-1 #scroll-section-1 .sticky-elem { display: block; } #show-scene-2 #scroll-section-2 .sticky-elem { display: block; } .pin { height: 10rem; width: 1px; background: black; } @media (min-width: 1024px) { html { font-size: 14px; } #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; } #scroll-section-2 .b { top: 20%; left: 53%; } #scroll-section-2 .c { left: 55%; } .main-message small { font-size: 1.5vw; } .desc-message { width: 20%; } .mid-message { font-size: 4vw; } .canvas-caption { margin-top: -8rem; padding: 0; font-size: 2rem; } }
HTML/CSS 웹 디자인 svg javascript 인터랙티브-웹 클론코딩
Hwi Kwon
2020-10-19T13:32:36.698Z
댓글 3
좋아요 0
조회수 337