์คํฌ๋กค์ ํจ์ ๋ฐ๋ผ ์ํ๋ฐ๊ฐ ์คํฌ๋กค ์์น์ ๋ฐ๋ผ ๋ณ๊ฒฝ๋๋ฉฐ ์ํ๋ฅผ ๋ณด์ฌ์ฃผ๋ ์คํฌ๋กค ํ๋ก๊ทธ๋ ์ค ๋ฐ๋ฅผ ๋ง๋ค์ด๋ณด์์ต๋๋ค.
์๊ฐ๋ณด๋ค ๊ฐ๋จํด์ ๊ณต์ ํด๋ณด๊ณ ์ ํฉ๋๋ค.
์ฐ์ ๋งํฌ์ ์ ํฉ๋๋ค. ๋ณดํต์ 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) + '%';
})
์ด๋ ๊ฒ ํ๋ฉด ๋น๋ก์ ์์ฑ์ ๋๋ค! ๐ธ
'๊ฐ๋ฐ ๐พ > Playground' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
ํ๋์ฉ ๋ํ๋๋ ํต ๋ฉ๋ด ๋ง๋ค๊ธฐ (SCSS & CSS) (0) | 2021.07.12 |
---|---|
ํคํจ๋๋ก ๋น๋ฐ๋ฒํธ ์ ๋ ฅํ๊ธฐ (HTML+SASS+JavaScript) (2) | 2021.07.08 |
[html, css, javascript] ์ฌ์ฌํด์ ๋ง๋ค์ด๋ณธ ๋ฉ์ธ ํ๋ฉด ํจ๊ณผ (0) | 2021.02.06 |