스크롤 이동시키기 (2)

ahncheer·2024년 8월 7일
0

LWC & LWR

목록 보기
47/52

(1) 에서 스크롤 시 현재 스크롤 위치를 파악하여 font-weight bold 추가하도록 함

1-1. html 작성

<template>
    <div class="cpHistory">
        <div class="full-img">
            <div class="txt-wrap">
                <h4>Our History</h4>
                <p>회사 소개가 들어갑니다.</p>
            </div>
            <div class="scroll-area">
                Scroll down <br /></div>
        </div>

        <div class="history-wrap">
            <!-- 연혁 메뉴 부분 -->
            <ul class="menu">
                <template for:each={historyList} for:item="item" for:index="index">
                    <li key={item.value} data-val={item.value} onclick={scrollToHistory} class="menu-title">
                            {item.title}
                    </li>
                </template>
            </ul>

            <!-- 연혁 부분 -->
            <ul class="history">
                <template for:each={historyList} for:item="item" for:index="index">
                    <li class="history-con" key={item.value} data-hcon={item.value}>
                        <div class="img-area"></div>
                        <div class="txt-area">
                            <h4>{item.title}</h4>
                            <p>{item.des}</p>
                        </div>
                    </li>
                </template>
            </ul>
        </div>
    </div>
</template>

1-2. JS 작성

import { LightningElement, track } from 'lwc';
export default class CpHistory extends LightningElement {
    @track historyList = [
        {title : '2019', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2019'},
        {title : '2020', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2020'},
        {title : '2021', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2021'},
        {title : '2022', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2022'},
        {title : '2023', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2023'},
        {title : '2024', des : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry. ', value : '2024'},
    ];
    @track hScrollList = [];

    async connectedCallback(){
        window.addEventListener("scroll", (event) => {
            this.checkScroll();
        });
        window.addEventListener("resize", (event) => {
            this.setHScrollList();
        });
    }
    @track isFirstLender = true;
    renderedCallback(){
        if(this.isFirstLender){
            this.setHScrollList();
        }
    }
    setHScrollList(){
        let lastVal = this.historyList[(this.historyList.length - 1)];
        console.log('lastVal : ', JSON.parse(JSON.stringify(lastVal)));

        if(lastVal){
            this.hScrollList = [];
            this.historyList.forEach((el, index) => { 
                let x = this.template.querySelector(`[data-hcon="${el.value}"]`);
                let hEl= {element : x, offsetTop : x.offsetTop, value : x.value};
                this.hScrollList.push(hEl);

            }); 
            console.log('this.hScrollList : ', JSON.parse(JSON.stringify(this.hScrollList)));
            this.isFirstLender = false;

            this.checkScroll();
        }
    }
    checkScroll(){
        // console.log('window.scrollY : ', window.scrollY);
        let menuEl = this.template.querySelector('.history-wrap .menu');

        let boldEl = 0;
        let menuElList = this.template.querySelectorAll('.menu-title');
        this.hScrollList.forEach((el, index) => {  
            if(window.scrollY > (el.offsetTop - menuEl.offsetHeight)){
                boldEl = index;
            }
        }); 
        // console.log('boldEl : ', boldEl);
        // console.log('menuElList : ', JSON.parse(JSON.stringify(menuElList)));

        menuElList.forEach((el, index) => {  
            if(boldEl == index){
                el.classList.add('is-active');
            }else{
                el.classList.remove('is-active');
            }
        }); 
    }

    scrollToHistory(e){
        let targetName = e.currentTarget.dataset.val;
        console.log('targetName : ', targetName);

        let el = this.template.querySelector(`[data-hcon="${targetName}"]`);
        console.log('el : ', el);
        let menuEl = this.template.querySelector('.history-wrap .menu');
        console.log('menuEl : ', menuEl.offsetHeight);
        let x = el.offsetTop - menuEl.offsetHeight;
        console.log('x : ', x);

        if(x > -1){
            window.scrollTo({top: x, behavior:'smooth'});
        }
        
    }


}

1-3. CSS 작성

/* full img */
.full-img {
    height: calc(100vh - 60px);
    background-color: #333;
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    padding-bottom: 110px;
}

.full-img .txt-wrap h4 {
    color: #fff;
    font-size: 42px;
}

.full-img .txt-wrap p {
    color: #fff;
    text-align: center;
    padding-top: 16px;
    font-size: 18px;
}

.scroll-area {
    position: absolute;
    text-align: center;
    color: #fff;
    bottom: 30px;
    font-size: 18px;
    background-color: rgb(255 255 255 / 18%);
    padding: 10px 30px;
    border-radius: 5px;
}

/* menu */
.history-wrap{
    max-width: 1080px;
    margin: 0 auto 450px;
}
ul.menu {
	padding: 15px 0;
    display: flex;
    justify-content: center;
    gap: 30px;
    border-bottom: 1px solid #000;
	position: sticky;
    top: 0;
    background-color: #fff;
}

ul.menu li {
    padding: 10px 15px;
    font-size: 22px;
    color: #666;
    cursor: pointer;
}
ul.menu li.is-active {
    font-weight: bold;
}
ul.menu li:hover {
    text-decoration: underline;
    color: #000;
}


ul.history .history-con:nth-child(2n) {
    flex-direction: row-reverse;
}

ul.history .history-con {
    display: flex;
    gap: 30px;
    align-items: center;
	padding: 20px;
    background-color: #f4f4f4;
	margin-top: 60px;
}

ul.history .history-con .img-area {
    width: 50%;
    background-color: #ddd;
    height: 700px;
}

ul.history {
	padding-top: 60px 0;
}

ul.history .history-con .txt-area h4 {
    font-size: 18px;
    padding-bottom: 10px;
}
profile
개인 공부 기록용.

0개의 댓글