๊ตญ๋น์ง์ D+51
Front-end ๋ฏธ๋ํ๋ก์ ํธ 7์ผ์ฐจ
- ๋ฆฌ์ฝ๋ฉ ์์ ๋ฐ ์น์ 0 ์ ๋๋ฉ์ด์ ์ค์ -
์ค๋ ํ ์ผ
- global nav, local nav ์ ์
- section ๋ ์ด์์ ์ค์
- section0 ์ ๋๋ฉ์ด์ ์ค์
ํ์ผ ๊ตฌ์ฑ ๋ฐ ๋ด์ฉ
• style.css
@charset 'utf-8';
html {
font-family: 'Noto Sans KR', sans-serif;
font-size: 14px;
}
body {
word-spacing: -0.08rem;
letter-spacing: -0.03rem;
overflow-x: hidden;
}
a {
text-decoration: none;
font-size: 0.9rem;
color: white;
}
.global {
/* absolute - section์์ญ์ค์ ์ ์ํ ๋
๋ฆฝ์์ญ์์ฑ */
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 44px;
padding: 0 5% 0 5%;
background-color: black;
}
.global-container {
/* flex - global-container์ global-item๋ค์ ๋ฐฐ์น ์ํ์ ๊ตฌ์กฐ ๋ชฉ์ */
display: flex;
max-width: 1000px;
height: 100%;
align-items: center;
justify-content: space-between;
margin: 0 auto;
}
.local {
/* absolute - section์์ญ์ค์ ์ ์ํ ๋
๋ฆฝ์์ญ์์ฑ */
position: absolute;
top: 44px;
left: 0;
width: 100%;
height: 52px;
padding: 0 5% 0 5%;
border-bottom: 1px solid gray;
}
.local-container {
/* flex - global-container์ global-item๋ค์ ๋ฐฐ์น ์ํ์ ๊ตฌ์กฐ ๋ชฉ์ */
display: flex;
max-width: 1000px;
height: 100%;
align-items: center;
justify-content: right;
margin: 0 auto;
}
.local-item-main {
margin-right: auto;
font-size: 1.5rem;
}
.local-item {
margin-left: 1em;
}
.local-item, .local-item-main {
color: black;
font-weight: bold;
}
/* static - section์ ๊ธฐ์กด๋ฌธ์์ ํ๋ฆ์ ๋ฐ๋ฅด๋๋ก ํ๋ค. */
.section0-main {
padding-top: 2em;
text-align: center;
font-size: 6rem;
}
.section0-message {
/* fixed - ์คํฌ๋กค์ด๋ฒคํธ ๋ฐ์์ ์ ๋๋ฉ์ด์
ํจ๊ณผ ์ถ๊ฐํ ๊ฒ */
position: fixed;
width: 100%;
display: none;
text-align: center;
font-size: 5rem;
font-weight: bold;
opacity: 0;
}
.show-section0 .section0-message {
display: block;
}
.section1, footer {
border: 2px solid red;
}
• index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- ์นํฐํธ -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;700&display=swap" rel="stylesheet">
<!-- ์คํ์ผ -->
<link rel="stylesheet" href="./reset.css">
<link rel="stylesheet" href="./style.css">
</head>
<body class ="show-section0">
<!-- global nav -->
<nav class="global">
<div class="global-container">
<a href="#" class="global-item">Home</a>
<a href="#" class="global-item">History</a>
<a href="#" class="global-item">Store</a>
<a href="#" class="global-item">Contact</a>
</div>
</nav>
<!-- local nav -->
<nav class="local">
<div class="local-container">
<a href="#" class="local-item-main">RealApplePeach</a>
<a href="#" class="local-item">Overview</a>
<a href="#" class="local-item">Compare</a>
<a href="#" class="local-item">Buy</a>
</div>
</nav>
<!-- section0 -->
<section class="section0">
<div class="section0-main"><h1>Apple taste</h1></div>
<div id="section0-message-0" class="section0-message">
<p>์จ์ ํ ๋น ์ ธ๋ค๊ฒ ํ๋ ๋น๊น</p>
</div>
<div id="section0-message-1" class="section0-message">
<p>๋์ ๊ฑด๊ฐ์ ์ฑ์์ฃผ๋ ํฅ๊ธฐ</p>
</div>
<div id="section0-message-2" class="section0-message">
<p>๊นจ๋ํ ์์ฐ์ ์ ์ ํจ</p>
</div>
<div id="section0-message-3" class="section0-message">
<p>์๋กญ๊ฒ ์
๊ฐ๋ฅผ ์ฐพ์์จ ๋งคํน</p>
</div>
</section>
<!-- section1 -->
<section class="section1">
<div class="section1-message">
<p>
์ง์ง ์ฌ๊ณผ ์ด์ผ๊ธฐ
์ฌ๊ณผ๋ฅผ ๋งค์ผ ํ๋์ฉ ๋จน์ผ๋ฉด ์์ฌ ๋ณผ ์ผ์ด ์๋ค
(an apple a day keeps the doctor away)๋ ์๋ด์ด ์์ ์ ๋๋ก
์ ๋ช
ํ ๊ฐ์ ๊ณผ์ผ ์ค ํ๋๋ค. ๋น์ทํ ์๋ด์ด ํ ๋งํ ์๋ ์๋ค.
๊ทธ๋งํผ ๋นํ๋ฏผC์ ๋ฌด๊ธฐ์ง์ด ๋ง์ ๊ฐ์ ๋์ฉ์ผ๋ก ์ฌ๊ณผ๋ฅผ ํ ์ ๋จน๋๋ค๋ฉด
๋นํ๋ฏผC ๋ถ์กฑ์ ์๋ฌ๋ฆด ์ผ์ ์๋ค. ๋ค๋ง ๊ณผ๋น์ด ๋ง์์ ํต์์ ์ธ ์ด๋ฏธ์ง์๋
๋ฌ๋ฆฌ ๋ค์ด์ดํธ ์ํ์ผ๋ก์๋ ๊ทธ๋ค์ง ํจ๋ฅ์ด ์ข์ง ์์๋ฐ, ๋จ์ ์ค๋ ๋น ์ด๋์
์๋ณด์นด๋๋ ๋ฐ๋๋ ๋ฑ๊ณผ ํจ๊ป ์ ๋ฒ ๋์ ํธ์ ์ํ๋ค.
๋น์ฐํ ์ฌ๊ณผ์ ํฌ๊ธฐ์ ์์์ํ์ ๋ฐ๋ผ ๋ค๋ฅด์ง๋ง 300g ์ ๋ ๋๊ฐ๋ ํ ์์ด
200kcal๋ ๋์ ์ ์๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค.
๋นํ๋ฏผ C๊ฐ ํ๋ถํ ๋งํผ ๊ฐ๊ธฐ ์๋ฐฉ์ ํจ๊ณผ์ ์ด๋, ํ์ํ์ ์ผ๋ก ์ฌ๊ณผ๋
์ฐจ๊ฐ์ด ์ฑ์ง์ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ชฉ๊ฐ๊ธฐ๋ ๊ธฐ์นจ์ ์ข์ง ์๋ค๊ณ ํ๋ค.
๊ฐ๊ธฐ์ ์ข๋ค๊ณ ํ๋ ๊ณผ์ผ์ ๋ฐฐ, ๊ทธ๋ฆฌ๊ณ ๊ทค๋ ์ข๋ค๊ณ ํ๋ค.
๋ฐฐ๋ ๊ณผ์ผ ์ค์์๋ ํนํ ์๋ถ, ๋ฌด๊ธฐ์ง์ด ๋ง์ ๊ณผ์ผ ์ค ํ๋์ด๊ธฐ ๋๋ฌธ์
๊ฐ๊ธฐ์ ๊ฑธ๋ ธ์ ๋ ์๋ถ ๋ณด์ถฉ์ ์์ฃผ ์ ์ ํ ์ํ์ด๋ค.
</p>
</div>
</section>
<!-- footer -->
<footer>
<div>
<p>Copyleft 2022 PARK SUHYEON Allright reserved.</p>
</div>
</footer>
<script src="./main.js"></script>
</body>
</html>
• main.js
(() => {
/*
currentScrollY : ํ์ฌ scrollY ์์น๊ฐ
currentSection : ํ์ฌ ์น์
์์น
sectionYOffset : ํ์ฌ ์น์
์ ๋ฐ๋ฅธ scrollY ์๋๊ฐ
*/
let currentScrollY = 0;
let currentSection = 0;
let sectionYOffset = 0;
// sectionSet : n๋ฒ์งธ ์น์
์ ๋ํ ๊ฐ์ข
์ ๋ณด์งํฉ
const sectionSet = [
// section0
{
height: 0,
multiplyValue: 5,
elemInfo: {
section: document.querySelector(".section0"),
message: [
document.querySelector("#section0-message-0"),
document.querySelector("#section0-message-1"),
document.querySelector("#section0-message-2"),
document.querySelector("#section0-message-3"),
],
},
opacitySettingsValues: {
message0_opacity_out: [0, 1, { start: 0.05, end: 0.14 }],
message0_opacity_in: [1, 0, { start: 0.15, end: 0.24 }],
message1_opacity_out: [0, 1, { start: 0.25, end: 0.34 }],
message1_opacity_in: [1, 0, { start: 0.35, end: 0.44 }],
message2_opacity_out: [0, 1, { start: 0.45, end: 0.54 }],
message2_opacity_in: [1, 0, { start: 0.55, end: 0.64 }],
message3_opacity_out: [0, 1, { start: 0.65, end: 0.74 }],
message3_opacity_in: [1, 0, { start: 0.75, end: 0.84 }],
},
},
// section1
{
height: 0,
multiplyValue: 3,
elemInfo: {
section: document.querySelector(".section1"),
},
},
];
/////////////////////////////////////////////////////////
// ์ผ๋ฐ ํจ์
// setLayout : window์ฐฝ ํฌ๊ธฐ์ ๋ํ section ์ฌ์ด์ฆ ์์ญ ์ค์
// - parameter : x
// - return : x
const setLayout = function () {
const currentHeight = window.innerHeight;
for (let i = 0; i < sectionSet.length; i++) {
sectionSet[i].height = currentHeight * sectionSet[i].multiplyValue;
sectionSet[i].elemInfo.section.style.height = `${sectionSet[i].height}px`;
}
};
// getCurrentSection : scrollY ์์น์ ๋ฐ๋ฅธ ํ์ฌ section ์์น ๊ตฌํ๊ธฐ
// - parameter : x
// - return : ํ์ฌ ์น์
๊ฐ
const getCurrentSection = function () {
let value = 0;
let sum = 0;
let index = 0;
for (let i = 0; i < sectionSet.length; i++) {
sum = sum + sectionSet[i].height;
if (currentScrollY <= sum) {
value = index;
break;
}
index++;
}
return value;
};
// getSectionYOffset : ํ์ฌ ์น์
์์น์ ๋ฐ๋ฅธ scrollY์ ์๋๊ฐ ๊ตฌํ๊ธฐ
// - parameter : x
// - return : ํ์ฌ ์น์
์์น์ ๋ฐ๋ฅธ scrollY ์๋๊ฐ
const getSectionYOffset = function () {
let value = currentScrollY;
for (let i = 0; i < currentSection; i++) {
value = value - sectionSet[i].height;
}
return value;
};
// setBodyClass : ํ์ฌ ์น์
์์น์ ๋ฐ๋ฅธ body class ์
๋ฐ์ดํธ
// section0์ ๋ด์ฉ์ด ๋ค๋ฅธ ์น์
์ ์์นํ๊ฒ ํ์ ๋ ์๋ณด์ด๊ฒ ํ๊ธฐ์ํ ๊ฒ
// - parameter : x
// - return : x
const setBodyClass = function () {
document.body.className = `show-section${currentSection}`;
};
// calcValue : ์ ๋๋ฉ์ด์
์ ์ ์ฉํ๊ธฐ ์ํ ๊ฐ์ CSSํ ํ๋ค.
// - parameter : ๊ฐ์์ญ์ ํฌ๋ช
๋์ค์ ๊ฐ ([0, 1, { start: 0.05, end: 0.14 }])
// - return : CSSํํ ๊ฐ
const calcValue = function (opacityValue) {
let rate;
let result;
let height = sectionSet[currentSection].height;
let startValue = height * opacityValue[2].start;
let endValue = height * opacityValue[2].end;
let heightValue = endValue - startValue;
rate = (sectionYOffset - startValue) / heightValue;
result = rate * (opacityValue[1] - opacityValue[0]) + opacityValue[0];
if (result < 0) {
result = 0;
} else if (result > 1) {
result = 1;
}
return result;
};
// playAnimation : ์น์
์ ๋ฐ๋ฅธ ์ ๋๋ฉ์ด์
๋์ ์ํค๊ธฐ
// - parameter : x
// - return : x
const playAnimation = function () {
let value;
let opacityValue;
let messageValue;
const yOffsetRate = sectionYOffset / sectionSet[currentSection].height;
switch (currentSection) {
case 0:
sectionSet[0].elemInfo.message.map((el) => {
el.style.opacity = 0;
});
opacityValue = sectionSet[0].opacitySettingsValues;
messageValue = sectionSet[0].elemInfo.message;
if (yOffsetRate < 0.15) {
value = calcValue(opacityValue.message0_opacity_out);
messageValue[0].style.opacity = value;
} else if (yOffsetRate >= 0.15 && yOffsetRate < 0.25) {
value = calcValue(opacityValue.message0_opacity_in);
messageValue[0].style.opacity = value;
} else if (yOffsetRate >= 0.25 && yOffsetRate < 0.35) {
value = calcValue(opacityValue.message1_opacity_out);
messageValue[1].style.opacity = value;
} else if (yOffsetRate >= 0.35 && yOffsetRate < 0.45) {
value = calcValue(opacityValue.message1_opacity_in);
messageValue[1].style.opacity = value;
} else if (yOffsetRate >= 0.45 && yOffsetRate < 0.55) {
value = calcValue(opacityValue.message2_opacity_out);
messageValue[2].style.opacity = value;
} else if (yOffsetRate >= 0.55 && yOffsetRate < 0.65) {
value = calcValue(opacityValue.message2_opacity_in);
messageValue[2].style.opacity = value;
} else if (yOffsetRate >= 0.65 && yOffsetRate < 0.75) {
value = calcValue(opacityValue.message3_opacity_out);
messageValue[3].style.opacity = value;
} else if (yOffsetRate >= 0.75 && yOffsetRate < 0.85) {
value = calcValue(opacityValue.message3_opacity_in);
messageValue[3].style.opacity = value;
} else {
}
break;
case 1:
break;
}
};
/////////////////////////////////////////////////////////
// ์ด๋ฒคํธ ํธ๋ค๋ฌ
window.addEventListener("load", () => {
setLayout();
currentScrollY = window.scrollY;
currentSection = getCurrentSection();
sectionYOffset = getSectionYOffset();
setBodyClass();
});
window.addEventListener("scroll", () => {
currentScrollY = window.scrollY;
currentSection = getCurrentSection();
sectionYOffset = getSectionYOffset();
setBodyClass();
playAnimation();
});
})();
๊ฒฐ๊ณผํ๋ฉด
๋ฐ์ํ
๋๊ธ