๊ตญ๋น์ง์ D+49
Front-end ๋ฏธ๋ํ๋ก์ ํธ 5์ผ์ฐจ
- ์คํฌ๋กค ์ ๋๋ฉ์ด์ ๊ตฌ์ฒดํ -
์ค๋ ํ ์ผ
- section0์ ๋ํ ์คํฌ๋กค ์ ๋๋ฉ์ด์ ์ถ๊ฐ(๊ตฌ์ฒดํ) ๋ฐ ํ ์คํธ
ํ์ผ ๊ตฌ์ฑ ๋ฐ ๋ด์ฉ
• index.html
- ๋ฉ์์ง 4๊ฐ์ ์คํฌ๋กค ์ ๋๋ฉ์ด์ ์ ๋์์ํค๊ธฐ ์ํด ์ฃผ์์ ํด์ ํด ์ฃผ์๋ค.
<section id="section-0" class="scroll-section">
<div class="section0-product-name">
<h1 class="product-name">Real Apple Pro</h1>
</div>
<div class="sticky-element section0-message a">
<p>์จ์ ํ ๋น ์ ธ๋ค๊ฒ ํ๋ ๋น๊น</p>
</div>
<div class="sticky-element section0-message b">
<p>๋์ ๊ฑด๊ฐ์ ์ฑ์์ฃผ๋ ํฅ๊ธฐ</p>
</div>
<div class="sticky-element section0-message c">
<p>๊นจ๋ํ ์์ฐ์ ์ ์ ํจ</p>
</div>
<div class="sticky-element section0-message d">
<p>์๋กญ๊ฒ ์
๊ฐ๋ฅผ ์ฐพ์์จ ๋งคํน</p>
</div>
</section>
• main.js
- ์คํฌ๋กค์ด๋ฒคํธ๋ฅผ ์ข๋ ๊ตฌ์ฒดํํ๊ธฐ ์ํด์ ๊ธฐ์กด ํจ์๋ฅผ ์ข ๋ ๊ตฌ์ฒดํ ํด์ฃผ์๋ค.
(() => {
let yOffset = 0; // ์คํฌ๋กค ์์น๊ฐ
let currentSection = 0; // ํ์ฌ ์น์
๋ฒํธ
// ํ์ํ ์ด์ - yOffset์ด๋ผ๋๊ฐ์ ๊ฐ์ง๊ณ ๊ฐ ์น์
์ ๋ํ ๋น์จ์ ๊ณ์ฐํ๋๋ฐ ์ด๋ ค์
// ์น์
์ ๋น์จ๊ฐ์ ๋ฐ๋ฅธ CSS๊ฐ์ ํธํ๊ฒ ๊ณ์ฐํ๊ธฐ ์ํด์ sectionYOffset์ ๋ง๋ค์๋ค.
let sectionYOffset = 0;
// section ์ ๋ณด ์งํฉ
const sectionSet = [
// section-0์ ์ ๋ณด๋ค - ๋์ด, ๋ฐฐ์, ์๋ฆฌ๋จผํธ์ ๋ณด
{
height : 0,
hMultiple : 5,
objs : {
container : document.querySelector('#section-0'),
messageA : document.querySelector('.section0-message.a'),
messageB : document.querySelector('.section0-message.b'),
messageC : document.querySelector('.section0-message.c'),
messageD : document.querySelector('.section0-message.d'),
},
// vals : message์ ๋ํ ํฌ๋ช
๋์ translateY์ ๋ํ ์ ๋ณด๊ฐ
vals : {
messageA_opacity_out : [0, 1, {start: 0.05, end: 0.14}],
messageA_opacity_in : [1, 0, {start:0.15, end: 0.24}],
messageA_translateY_out : [0, -40, {start: 0.05, end: 0.14}],
messageA_translateY_in : [-40, -80, {start:0.15, end: 0.24}],
messageB_opacity_out : [0, 1, {start: 0.25, end: 0.34}],
messageB_opacity_in : [1, 0, {start:0.35, end: 0.44}],
messageB_translateY_out : [0, -40, {start: 0.25, end: 0.34}],
messageB_translateY_in : [-40, -80, {start:0.35, end: 0.44}],
messageC_opacity_out : [0, 1, {start: 0.45, end: 0.54}],
messageC_opacity_in : [1, 0, {start:0.55, end: 0.64}],
messageC_translateY_out : [0, -40, {start: 0.45, end: 0.54}],
messageC_translateY_in : [-40, -80, {start:0.55, end: 0.64}],
messageD_opacity_out : [0, 1, {start: 0.65, end: 0.74}],
messageD_opacity_in : [1, 0, {start:0.75, end: 0.84}],
messageD_translateY_out : [0, -40, {start: 0.65, end: 0.74}],
messageD_translateY_in : [-40, -80, {start:0.75, end: 0.84}]
}
},
// section-1์ ์ ๋ณด๋ค
{
height : 0,
hMultiple : 2,
objs : {
container : document.querySelector('#section-1')
}
}
];
////////////////////////////////////////////////////////
// ์ผ๋ฐํจ์
// Element์ ํฌ๊ธฐ, ์์น๋ฑ์ ์ค์
const setLayout = function()
{
// section-0๊ณผ section-1์ ๋์ด๋ฅผ ์ค์ ํ๋ค.
for(let i = 0; i < sectionSet.length; i++)
{
sectionSet[i].height = window.innerHeight * sectionSet[i].hMultiple;
sectionSet[i].objs.container.style.height = `${sectionSet[i].height}px`;
}
}
const getCurrentSection = function()
{
let section = 0;
let segment = [
sectionSet[0].height,
sectionSet[0].height + sectionSet[1].height
];
if(yOffset <= segment[0])
{
section = 0;
}
else if((yOffset > segment[0]) &&
(yOffset <= segment[1]))
{
section = 1;
}
else
{
}
return section;
}
const setBodyID = function(section)
{
document.body.setAttribute('id', `show-section${section}`);
}
// ํ์ฌ ์น์
์ ์์ ์๋ ์น์
์ ๋์ด ํฉ.
const getPrevSectionHeight = function()
{
// ํ์ฌ ์น์
์ด 0 ==> 0
// ํ์ฌ ์น์
1 ==> section0์ ๋์ด
// ํ์ฌ ์น์
2 ==> section0์ ๋์ด + section1์ ๋์ด
let prevHeight = 0;
for(let i = 0; i < currentSection; i++)
{
prevHeight = prevHeight + sectionSet[i].height;
}
return prevHeight;
}
// messageA_opacity_out : [0, 1, {start: 0.05, end: 0.14}]
const calcValue = function(values)
{
let result = 0;
let rate = 0;
const height = sectionSet[currentSection].height;
let partStart; // start ์คํฌ๋กค๊ฐ
let partEnd; // end ์คํฌ๋กค๊ฐ
let partHeihgt; // end - start
if(values.length === 2)
{
// 1. ์คํฌ๋กค ๋น์จ์ ๊ตฌํ๋ค.
rate = sectionYOffset / height;
// 2. ๋น์จ์ ๋ฐ๋ฅธ ์ค์ ์ ์ฉํ CSS๊ฐ์ ๊ณ์ฐํ๋ค.
result = (rate * (values[1] - values[0])) + values[0];
}
else if(values.length === 3)
{
// step01) ๋ชจ๋ ๊ฐ๋ค์ ๋น์จ์ด ์๋ ์ค์ ํ ํ๋ค.
// -- ์์์์น์ ์ค์ ์คํฌ๋กค๊ฐ
partStart = values[2].start * height;
// -- ๋๋๋ ์์น์ ์ค์ ์คํฌ๋กค๊ฐ
partEnd = values[2].end * height;
// -- ์ค์ ๋์ด๊ฐ
partHeihgt = partEnd - partStart;
// ์ค์ ํ ๋ฒ์๊ฐ์ ๋ฒ์ด๋ ๊ฐ์ 0๋๋ 1๋ก ์ค์ ํด์ค๋ค.
//-- ์คํฌ๋กค ๊ฐ์ด ์์์์น ์ด์ ์ธ ๊ฒฝ์ฐ values[0]์ ํ์ฅํด์ ์ ์ฉ
if(sectionYOffset < partStart)
{
result = values[0];
}
//-- ์คํฌ๋กค ๊ฐ์ด ๋๋๋๊ฐ ์ดํ์ธ ๊ฒฝ์ฐ values[1]์ ํ์ฅํด์ ์ ์ฉ
else if(sectionYOffset > partEnd)
{
result = values[1];
}
else
{
// step02) sectionYOffset์์ partStart๊ฐ์ ๋นผ๋ด์ด ์ค์ ๋ฒ์๋ด์ ํฌ๊ธฐ๋ฅผ ๊ตฌํ๊ณ
// -- ๋น์จ์ ๊ตฌํ๋ค. ๋ถ๋ถ์์ญ์์ ์ผ๋งํผ ์งํํ๋์ง ๋น์จ์ ๊ตฌํ๋ค.
rate = (sectionYOffset - partStart) / partHeihgt;
// step03) ๊ฐ์ cssํ ํ์ฌ result์์ ๋ฃ์ด์ค๋ค.
result = (rate * (values[1] - values[0])) + values[0];
}
}
return result;
}
const playAnimation = function()
{
let value;
let scrollRate = sectionYOffset / sectionSet[currentSection].height;
let objects = sectionSet[currentSection].objs;
let values = sectionSet[currentSection].vals;
switch(currentSection)
{
case 0:
// message์ ๋ํ ํฌ๋ช
๋ ๊ฐ ์ด๊ธฐํ
objects.messageA.style.opacity = 0;
objects.messageB.style.opacity = 0;
objects.messageC.style.opacity = 0;
objects.messageD.style.opacity = 0;
if(scrollRate < 0.15) // messageA_out
{
value = calcValue(values.messageA_opacity_out);
objects.messageA.style.opacity = value;
value = calcValue(values.messageA_translateY_out);
objects.messageA.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.15) && (scrollRate < 0.25)) // messageA_in
{
value = calcValue(values.messageA_opacity_in);
objects.messageA.style.opacity = value;
value = calcValue(values.messageA_translateY_in);
objects.messageA.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.25) && (scrollRate < 0.35)) // messageB_out
{
value = calcValue(values.messageB_opacity_out);
objects.messageB.style.opacity = value;
value = calcValue(values.messageB_translateY_out);
objects.messageB.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.35) && (scrollRate < 0.45)) // messageB_in
{
value = calcValue(values.messageB_opacity_in);
objects.messageB.style.opacity = value;
value = calcValue(values.messageB_translateY_in);
objects.messageB.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.45) && (scrollRate < 0.55)) // messageC_out
{
value = calcValue(values.messageC_opacity_out);
objects.messageC.style.opacity = value;
value = calcValue(values.messageC_translateY_out);
objects.messageC.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.55) && (scrollRate < 0.65)) // messageC_in
{
value = calcValue(values.messageC_opacity_in);
objects.messageC.style.opacity = value;
value = calcValue(values.messageC_translateY_in);
objects.messageC.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.65) && (scrollRate < 0.75)) // messageD_out
{
value = calcValue(values.messageD_opacity_out);
objects.messageD.style.opacity = value;
value = calcValue(values.messageD_translateY_out);
objects.messageD.style.transform = `translateY(${value}%)`;
}
else if((scrollRate >= 0.75) && (scrollRate < 0.85)) // messageD_in
{
value = calcValue(values.messageD_opacity_in);
objects.messageD.style.opacity = value;
value = calcValue(values.messageD_translateY_in);
objects.messageD.style.transform = `translateY(${value}%)`;
}
else
{
objects.messageA.style.opacity = 0;
objects.messageB.style.opacity = 0;
objects.messageC.style.opacity = 0;
objects.messageD.style.opacity = 0;
objects.messageA.style.transform = 'translateY(0%)';
objects.messageB.style.transform = 'translateY(0%)';
objects.messageC.style.transform = 'translateY(0%)';
objects.messageD.style.transform = 'translateY(0%)';
}
break;
case 1:
break;
default:
break;
}
}
////////////////////////////////////////////////////////
// ์ด๋ฒคํธ ํธ๋ค๋ฌ
// ์คํฌ๋กค์ system์ด๊ธฐ ๋๋ฌธ์ ์์ window์ ์ด๋ฒคํธ์ถ๊ฐ
window.addEventListener('scroll', () => {
yOffset = window.scrollY;
// ํ์ฌ ์น์
๊ฐ ๋ฐ ์น์
๋ด์์์ yoffset๊ฐ์ ๊ตฌํ๋ค.
currentSection = getCurrentSection(); // ์คํฌ๋กคํ ๋๋ง๋ค ์น์
์์น๋ฅผ ์
๋ฐ์ดํธ
sectionYOffset = yOffset - getPrevSectionHeight();
setBodyID(currentSection); // currentSection์ ํตํด ๋ฐ์์จ ์น์
์์น๋ฅผ ํตํด body์ id๊ฐ ์๋ก๊ณ ์นจ
playAnimation();
});
// load : ๋ชจ๋ ์์
์ด ๋๋ฌ๋ค.
window.addEventListener('load', () => {
// ์น์
์ ๋ํ ๋์ด๋ฅผ ์ค์ ํ๋ค.
setLayout();
})
})();
๊ฒฐ๊ณผํ๋ฉด
๋ฐ์ํ
๋๊ธ