• 카테고리

    질문 & 답변
  • 세부 분야

    프론트엔드

  • 해결 여부

    미해결

scroll-section-3에서 reload 했을 때 원래 자리를 찾지 못합니다.

20.10.19 22:32 작성 조회수 170

0

안녕하세요.

코드를 재구성하면서 따라가고 있는데 마지막 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;
    }
}

답변 3

·

답변을 작성해보세요.

0

아, 약간은 차이가 있을 수 있을듯한데 혹시 제가 드린 완성파일도 똑같이 동작하나요? 만약 완성파일은 괜찮은데 이것만 그런거라면 뭔가 차이가 있다는건데.. 저도 시간날때 휘님 하신것처럼 클래스로 한번 바꾸어 볼게요^^

0

Hwi Kwon님의 프로필

Hwi Kwon

질문자

2020.10.24

확인 감사합니다. setLayout을 추가했음에도 아래와 같이 제자리를 찾지 못하고 있습니다.

선생님께서 테스트하셨을 때는 저런 현상이 없으셨나요? ㅠ

0

class로 바꾸어보고 계시네요^^
제가 테스트 해보니 큰 이상은 발견하지 못했는데,

window.addEventListener('load', () => {

완성파일의 이 부분을 보시면,
콘텐츠 양에 따라 높이 계산 오차를 방지하도록 before-load 클래스를 제거하기 전에 setLayout을 한번 더 호출해주는데,
작성하신 소스에는 그 부분이 빠져있습니다.

this.setLayout();
document.body.classList.remove('before-load');
this.setLayout();

이렇게 추가하고 테스트를 해보시면 어떨까 싶네요~

일단 더 간단한 형태인 @simple-version에 있는 버전으로 수정해보셔도 좋을 것 같습니다^^