๊ฐœ๋ฐœ ๐Ÿพ/Playground

javascript ์Šคํฌ๋กค ์ƒํƒœ๋ฐ” ๋งŒ๋“ค๊ธฐ (window / div)

JOTOKKI 2021. 7. 1. 16:01
728x90

์Šคํฌ๋กค์„ ํ•จ์— ๋”ฐ๋ผ ์ƒํƒœ๋ฐ”๊ฐ€ ์Šคํฌ๋กค ์œ„์น˜์— ๋”ฐ๋ผ ๋ณ€๊ฒฝ๋˜๋ฉฐ ์ƒํƒœ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์Šคํฌ๋กค ํ”„๋กœ๊ทธ๋ ˆ์Šค ๋ฐ”๋ฅผ ๋งŒ๋“ค์–ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. 

์™„์„ฑ๋œ ๋ชจ์Šต

์ƒ๊ฐ๋ณด๋‹ค ๊ฐ„๋‹จํ•ด์„œ ๊ณต์œ ํ•ด๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค. 

์šฐ์„  ๋งˆํฌ์—…์„ ํ•ฉ๋‹ˆ๋‹ค. ๋ณดํ†ต์€ window ์Šคํฌ๋กค์„ ๋งŽ์ด ์‚ฌ์šฉํ•˜์ง€๋งŒ ์ €๋Š” div์— ์Šคํฌ๋กค์„ ์ฃผ๊ณ  ์ ์šฉํ•ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. 

 

// index.html
<div class="wrap">
    <div class="barWrap"><div class="bar"></div></div>
    <div class="perWrap"><span class="per">0%</span></div>
    <div class="inner">
        <ul>
            <li>{ ...contents }</li>
        </ul>
    </div>
</div>
// style.css
html, body, .wrap {
    width: 100%; 
    height: 100%; 
    overflow: hidden;
}

.wrap {
    position: relative; 
    overflow-y: auto;
    padding-top: 13px;
}

.barWrap {
    position: fixed; 
    top: 0; 
    left: 0; 
    width: 100%; 
    height: 13px; 
    background: lightslategrey;
}

.bar {
    position: fixed; 
    top: 0; 
    left: 0;
    height: inherit;
    background: black; 
    color: white;
}

.inner {
    padding: 20px;
    line-height: 3;
    
}

div์—๋งŒ ์Šคํฌ๋กค์„ ์ฃผ๊ธฐ ์œ„ํ•ด html, body ๋ชจ๋‘ overflow hidden ์ฒ˜๋ฆฌ์‹œํ‚ต๋‹ˆ๋‹ค. 

์ด ์ƒํƒœ์—์„œ๋Š” ์Šคํฌ๋กค์„ ๊ฐ€์ง„ ์š”์†Œ๋Š” wrap์ด ๋˜๊ณ  ์ƒํƒœ๋ฅผ ํ‘œ์‹œํ•ด์ค„ ๊ฐ์ฒด๋Š” bar๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. 

๊ทธ๋ฆฌ๊ณ  ํ•ด๋‹น div์—์„œ ์Šคํฌ๋กค์„ ํ• ๋•Œ๋งˆ๋‹ค ๊ฐ’์„ ๊ฐ€์ ธ์™€์•ผ ํ•˜๋ฏ€๋กœ addEventListener์— ํƒ€์ž…์„ scroll๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. 

 

๊ตฌํ˜„์„ ์œ„ํ•ด ํ•„์š”ํ•œ ๊ฒ‚๋“ค์„ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ˜์†”์— ์ฐ์–ด๋ด…์‹œ๋‹ค.

// index.js
let wrap = document.querySelector(".wrap"); 

wrap.addEventListener('scroll', function(){
   console.log("scrollTop: ", wrap.scrollTop);
   console.log("scrollHeight: ", wrap.scrollHeight);
   console.log("clientHeight: ", wrap.clientHeight);
})

๋งŒ์•ฝ ์Šคํฌ๋กค์˜ ๋Œ€์ƒ์ด div๊ฐ€ ์•„๋‹Œ window๋ผ๋ฉด wrap์„ document.querySlector('. wrap')์ด ์•„๋‹Œ document.documentElement์œผ๋กœ ์„ ์–ธํ•ด์ฃผ์„ธ์š”. ์–ด์ฐจํ”ผ ์ด์™ธ์˜ ๋กœ์ง์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ฐ’๋“ค์€ ์ „์ฒด ๋†’์ด์—์„œ ์Šคํฌ๋กค์œ„์น˜์— ๋”ฐ๋ผ ๋น„์œจ์„ ๊ตฌํ•˜๋Š” ๋กœ์ง์„ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. 

๊ฐ๊ฐ์˜ ๊ฐ’์€ ์•„๋ž˜์˜ ์ด๋ฏธ์ง€๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”. 

์ฃ„์†กํ•ด์š” ๋ฐœ๋กœ ๊ทธ๋ ธ์Œ..

๋จผ์ € ์ „์ฒด ๋†’์ด(scrollHeight)์—์„œ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ๋†’์ด(clientHeight)๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋‚˜๋จธ์ง€์—์„œ ์Šคํฌ๋กค์˜ ์œ„์น˜๋ฅผ ๋‚˜๋ˆˆ๋‹ค๋ฉด ๋‚˜๋จธ์ง€ ๊ฐ’์ด ๋‚˜์˜ต๋‹ˆ๋‹ค. 100์„ ๊ณฑํ•˜์—ฌ ํผ์„ผํŠธ๋กœ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

// index.js
let wrap = document.querySelector(".wrap");
let bar = document.querySelector('.bar');

wrap.addEventListener('scroll', function(){
    let scrollTop = wrap.scrollTop;
    let scrollHeight = wrap.scrollHeight - wrap.clientHeight;
    let percentage = (scrollTop/scrollHeight) * 100;
    bar.style.width = percentage + '%';
})

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šคํฌ๋กค์— ๋”ฐ๋ผ progress bar๊ฐ€ ์œ„์น˜์— ๋”ฐ๋ผ ๋ณ€ํ™”ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

์ข€ ๋” ๋ถ€๋“œ๋Ÿฌ์šด ์›€์ง์ž„์„ ์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด bar์— transition์„ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด๋ฉ๋‹ˆ๋‹ค. 

// style.css

.bar {
    ...
    transition: .1s ease;
}

 

์–ด์ฐจํ”ผ bar์˜ width๊ฐ’์ด ๋„˜์–ด์˜ค๋‹ˆ ์ด๋ฅผ ์ด์šฉํ•ด์„œ ํผ์„ผํŠธ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ˆซ์ž๋„ ์ถ”๊ฐ€ํ•ด ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

๊ฐ’์„ ๊ณ„์‚ฐํ• ๋•Œ ์†Œ์ˆ˜์ ๊นŒ์ง€ ๋‚˜ํƒ€๋‚˜๋ฏ€๋กœ Math.floor๋กœ ์†Œ์ˆ˜์ ์„ ์ œ๊ฑฐํ•ด ์ค„ ๊ฒ๋‹ˆ๋‹ค. 

// index.html
<div class="wrap">
    <div class="barWrap"><div class="bar"></div></div>
    <div class="perWrap"><span class="per">0%</span></div> <!-- add -->
    <div class="inner">
        { ... }
    </div>
</div>
// style.css

{...}

.perWrap {
    position: fixed; 
    top: 20px; 
    left: 10px;
    width: 50px; 
    height: 50px; 
    text-align: center;
    background: black; 
    color: #fff; 
    border-radius: 100%;
    line-height:3.5;
    font-size: 13px;
}
// index.js
let wrap = document.querySelector(".wrap");
let bar = document.querySelector('.bar');
let per = document.querySelector('.per'); // add

wrap.addEventListener('scroll', function(){
    {...}
    per.innerText = Math.floor(percentage) + '%'; // add
})

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ˆซ์ž๋กœ ํ‘œ์‹œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

ํ•˜์ง€๋งŒ ํ•œ ๊ฐ€์ง€ ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์Šคํฌ๋กค ํ•˜๋˜ ์ค‘ viewport์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋‹ฌ๋ผ์ ธ ๋ฒ„๋ฆฐ๋‹ค๋ฉด, ๊ณ„์‚ฐ์„ ํ•˜์ง€ ๋ชปํ•˜๊ณ  NaN์„ ๋ฑ‰์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. (Not-A-Number:์ˆซ์ž๊ฐ€ ์•„๋‹˜) 

NaN์ธ ๊ฒฝ์šฐ 0์„ ๋ฆฌํ„ดํ•˜๋„๋ก ์Šคํฌ๋ฆฝํŠธ ํ•œ ์ค„์„ ์ถ”๊ฐ€ํ•ด ์ค๋‹ˆ๋‹ค. 

let wrap = document.querySelector(".wrap");
let bar = document.querySelector('.bar');
let per = document.querySelector('.per');

wrap.addEventListener('scroll', function(){
    {...}
    if(isNaN(percentage)) percentage = 0;  // add
    bar.style.width = percentage + '%';
    per.innerText = Math.floor(percentage) + '%';
})

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋น„๋กœ์†Œ ์™„์„ฑ์ž…๋‹ˆ๋‹ค! ๐Ÿ˜ธ

 

 

๋ฐ˜์‘ํ˜•