๐ป THE ONE BURGER ํด๋ก ์ฝ๋ฉ
์ฒ์์ ํ๋ธ๋ฆฟ ๊ตฌ๊ฐ๊น์ง๋ง swiper ์ฌ์ฉ์ ํฌ๋งํ์ฌ ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํ์๋ค. ํ์ง๋ง ํด๋น์ฝ๋๋ 1023px ์ดํ์์ 1024px ์ด์์ผ๋ก ํด์๋๋ฅผ ๋๋ฆด ๊ฒฝ์ฐ swiper๊ฐ ๊ณ์ ์คํ๋์๋ค.
์ฆ, 1023px ์ดํ์์ swiper๋ฅผ ํ๋ฒ ํธ์ถํ๋ฉด ๋ชจ๋ ๊ตฌ๊ฐ์์ ๊ณ์ ํธ์ถ๋์ด ์ํ๋ ๊ตฌ๊ฐ์์ ์ค์์ดํผ ์ฌ์ฉ์ ์ค์ง์ํฌ ์ ์์๋ค.
let windowWidth = window.innerWidth;
function initSwiper() {
const swiper = new Swiper('.swiper', {
slidesPerView: 2,
spaceBetween: 5,
loop: true
})
}
if (windowWidth <= 1023) {
initSwiper();
} else {
// swiper ์คํ ์ํจ
}
window.addEventListener('resize', function() {
windowWidth = window.innerWidth;
if (windowWidth <= 1023) {
initSwiper();
}
});
object
์ด๊ณ , ํธ์ถ๋์ง ์์ swiper์ ํ์
์ undefined
์ด๋ค.console.log('1023 ์ดํ', typeof swiper)
console.log('1024 ์ด์', typeof swiper)
์ฌ๋ผ์ด๋ ์ธ์คํด์ค๋ฅผ ์ญ์ ํ๋ ๋ฉ์๋์ธ swiper.destroy()
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
์ด๋ฏธ ํธ์ถ๋ swiper์ destroy ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด swiper๊ฐ ์ ๊ฑฐ๋๋ค. ํ์ง๋ง ์ด๋ฏธ ํธ์ถ๋ swiper๋ ์ ๊ฑฐ ํ ๊ฒฝ์ฐ์๋ object ํ์ ์ด๋ค. ๋ฐ๋ผ์ swiper๋ฅผ ์ ๊ฑฐํจ๊ณผ ๋์์ ํ์ ๋ undefined๋ก ๋ณ๊ฒฝํด์ผ ํ๋ค.
๐ ์์ฑ์ฝ๋
let swiper = undefined; // ๋ณ์ ์ ์ธ
function initSwiper() {
let windowWidth = window.innerWidth;
if(windowWidth <= 1023 && swiper == undefined) {
// ์ฌํ ๋น
swiper = new Swiper('.swiper', {
slidesPerView: 2,
spaceBetween: 5,
loop: true
})
} else if(windowWidth >= 1024 && swiper != undefined) {
swiper.destroy(); // ์ค์์ดํผ ์ ๊ฑฐ
swiper = undefined; // ํ์
๋ณ๊ฒฝ(object -> undefined)
}
}
initSwiper();
window.addEventListener('resize', initSwiper);
๋ด๊ฐ ํด๋ก ์ฝ๋ฉํ THE ONE BURGER ์ฌ์ดํธ๋ ํ์ด์ง๋ฅผ ๋ฐฉ๋ฌธํ ์๊ฐ ๋ถํฐ ์ข ๋ฃํ ๋ ๊น์ง ์ค์๊ฐ์ผ๋ก ์ผ๋ง๋ ๋จธ๋ฌผ๋ฌ ์์๋์ง ๋ณด์ฌ์ฃผ๋ UI๊ฐ ์กด์ฌํ๋ค. ํ๋จ์ ๊ณ ์ ๋์ด ์๋ค๊ฐ ํน์ ๊ตฌ๊ฐ์์ ์ฌ๋ผ์ง๋ฉด์ ํน์ ํผ์ณ์์ ๊ณ์์ ์ผ๋ก ๋ณด์ฌ์ฃผ๋ ์ฌ๋ฏธ์๋ ๋ถ๋ถ์ด๋ค.
๋ด๊ฐ ์ฌ์ฉํ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ๋ค.
1) ๋ก๋์์ ์ ํ์ฌ ์๊ฐ์ ๊ตฌํด์ defaultTime ๋ณ์์ ์ ์ฅํ๋ค.
let defaultTime = 0;
window.addEventListener('load', function() {
defaultTime = new Date().getTime(); // ๋ก๋ ์์ ํ์ฌ ์๊ฐ ๊ตฌํ๊ธฐ
})
2) ์ดํ 1์ด๋น ํ ๋ฒ์ฉ ํ์ฌ ์๊ฐ์ ๋ถ๋ฌ์์ nowTime ๋ณ์์ ์ ์ฅํ๋ค.
๊ทธ๋ฆฌ๊ณ , nowTime - defaultTime ์ new Date()์ ๋ฃ์ด ๋ถ๊ณผ ์ด๋ฅผ ๊ตฌํ๋ค.
์ด ๋ setTimeout์ ์ฌ๊ท์คํ ํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๋ฃจํ๊ฐ ๋๋๋ก ํ์๋ค. (์ฆ, setInterval ์ฌ์ฉ X)
let timeStart;
timeStart = () => {
const timeEl = document.querySelector('.time');
const nowTime = new Date().getTime();
const newTime = new Date(nowTime - defaultTime);
const minutes = String(newTime.getMinutes()).padStart(2, '0'); // ๋ถ
const seconds = String(newTime.getSeconds()).padStart(2, '0'); // ์ด
setTimeout(() => {
timeEl.textContent = `${minutes}:${seconds}`;
timeStart(); // ์ฌ๊ทํธ์ถ
}, 1000);
}
timeStart(); // ํจ์์คํ
๐ ์์ฑ์ฝ๋
ํน์ ์๊ฐ๋ง๋ค ํจ์๋ฅผ ๋ฌดํ ๋ฐ๋ณต์ํฌ ์ ์๋ ๋ฐฉ๋ฒ์๋ setInterval()๊ณผ setTimeout()์ ์ฌ๊ท ํจ์(์ค์ค๋ก๋ฅผ ํธ์ถํ๋ ํจ์)๊ฐ ์๋ค. ๋์ ๊ธฐ๋ฅ์ ๋ฌดํ ๋ฐ๋ณต์ด๋ผ๋ ์ ์์ ๊ฐ์ง๋ง ๋ฏธ์ธํ ์ฐจ์ด๊ฐ ์กด์ฌํ๋ค.
setInterval()์ ๋๋ ์ด ์๊ฐ์ด ํจ์๋ฅผ ์คํํ๋ ๊ฒ๊น์ง ํฌํจ๋์ด ์๋ค.
์ฆ, ํจ์์ ์๋ ์๊ฐ๊น์ง ๋๋ ์ด ์๊ฐ์ ํฌํจ๋์ด ์๊ธฐ ๋๋ฌธ์ ์๋ฌด๋๋ ๋๋ ์ด ์๊ฐ์ด ๋ช ํํ์ง ์์ ์ ์๋ค.
ํ์ง๋ง, setTimout()์ ์ฌ๊ท ํจ์๋ฅผ ์ด์ฉํ๊ฒ ๋๋ฉด ํจ์์ ์๋์ด ๋ชจ๋ ๋๋ ํ ๋๋ ์ด๊ฐ ์ ํด์ง ์๊ฐ ๋งํผ ์๋๋๋ค. ์ฆ, ๋ด๊ฐ ์ ํ ๋๋ ์ด ์๊ฐ์ด ๋ช ํํ๊ฒ ๋ณด์ฅ๋ฐ๋๋ค๋ ์๋ฏธ์ธ ๊ฒ์ด๋ค.
์์ ๋น๋์ค ์์ฑ์ ๋ํด ๋จผ์ ์ ๋ฆฌํด ๋ณด์๋ค.
currentTime ์์ฑ์ ๋น๋์ค์ ํ์ฌ ์ฌ์ ์์น๋ฅผ ๋ฐํํ๋ฉฐ ์ค์ ๋ ๊ฐ๋ฅํ๋ค.
์ด ์์ฑ์ ์ค์ ํ๋ ๊ฒฝ์ฐ, ์ฌ์์ด ์ง์ ๋ ์์น๋ก ์ด๋ํ๋ค.
const video = document.querySelector('video');
video.currentTime = 5; // ๋น๋์ค ์ฌ์์ ํ์ฌ ์์น(์ด)๋ฅผ ์ค์
console.log(video.currentTime);
currentTime์ด ์ ๋ฐ์ดํธ ๋๋ฉด ์ด๋ฒคํธ๊ฐ ์์๋๋ค.
<div class="video">
<video autoplay muted controls>
<source src="./assets/videos/section-home.mp4" type="video/mp4" />
</video>
</div>
const video = document.querySelector('video');
video.addEventListener('timeupdate', function() {
console.log(video.currentTime); // ๋น๋์ค์ ํ์ฌ ์๊ฐ ์ถ๋ ฅ
})
๋น๋์ค์ ์ ์ฒด ๊ธธ์ด๋ duration ์์ฑ์ ์ด์ฉํ์ฌ ๊ฐ์ ธ์ฌ ์ ์๋ค.
ํ์ง๋ง ๋น๋์ค ๋ฐ์ดํฐ์ ๋ํ ๋ก๋ฉ์ด ๋๋์ง ์์ ์ํ์์ duration ๊ฐ์ ํธ์ถํ๊ฒ ๋๋ฉด NaN ๊ฐ์ด ๋์จ๋ค. ๋ฐ๋ผ์ ๋น๋์ค ๋ก๋๊ฐ ๋๋ ์์ ์ ํธ์ถํ๋ loadedmetadata ์ด๋ฒคํธ๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋น๋์ค ๊ธธ์ด๋ฅผ ์ ์์ ์ผ๋ก ๊ฐ์ ธ์ฌ ์ ์๋ค.
const video = document.querySelector('video');
console.log(video.duration); // NaN
video.addEventListener('loadedmetadata', function() {
console.log(video.duration); // 8.106
})
ํฌ๋กฌ์์๋ ์์๊ฑฐ๋ ๊ฒฝ์ฐ์ ๋น๋์ค ์๋ ์ฌ์์ ํ์ฉํ๋ค๊ณ ๋ช
์๋์ด ์๋ค.
๋ฐ๋ผ์ video
ํ๊ทธ์ autoplay ์์ฑ๊ณผ muted๋ฅผ ํจ๊ป ์ง์ ํด ์ฃผ์ด์ผ ์ ์์ ์ผ๋ก ์๋ ์ฌ์์ด ๋๋ค.
<video autoplay muted>
<source src="./assets/videos/section-home.mp4" type="video/mp4" />
</video>
const video = document.querySelector('video');
ScrollTrigger.create({
trigger: 'video',
start: 'top top',
end: '+=3000',
pin: true,
scrub: 0,
onUpdate: function(self) {
duration = 6;
video.currentTime = duration * self.progress; // ๋น๋์ค ํ์ฌ ์ฌ์์์ = ์ ์ฒด ๊ธธ์ด * ์ด๋ฒคํธ ์งํ๋ฅ
}
})
๐ ์์ฑ์ฝ๋
์๋๋ MDN ๊ณต์ ๋ฌธ์์ ๋์ ์๋ fixed ์์ฑ์ ๋ํ ์ค๋ช ์ด๋ค.
์์๋ฅผ ์ผ๋ฐ์ ์ธ ๋ฌธ์ ํ๋ฆ์์ ์ ๊ฑฐํ๊ณ , ํ์ด์ง ๋ ์ด์์์ ๊ณต๊ฐ๋ ๋ฐฐ์ ํ์ง ์์ต๋๋ค. ๋์ ๋ทฐํฌํธ์ ์ด๊ธฐ ์ปจํ ์ด๋ ๋ธ๋ก์ ๊ธฐ์ค์ผ๋ก ์ผ์ ๋ฐฐ์นํฉ๋๋ค.
๋จ, ์์์ ์กฐ์ ์ค ํ๋๊ฐ transform, perspective, filter ์์ฑ ์ค ์ด๋ ํ๋๋ผ๋ none์ด ์๋๋ผ๋ฉด ๋ทฐํฌํธ ๋์ ๊ทธ ์กฐ์์ ์ปจํ ์ด๋ ๋ธ๋ก์ผ๋ก ์ผ์ต๋๋ค. - MDN Web Docs
์ด๋ฒ์ ํฌํธํด๋ฆฌ์ค ์์ ์ ํ๋ฉด์, transform ์์ฑ์ด ์ ์ฉ๋์ด ์๋ ๋ถ๋ชจ ์ปจํ ์ด๋ ์์ ์๋ ์์ ์์์ position: fixed๋ฅผ ์ฃผ์๋๋ฐ ์ ๋๋ก ๋์ํ์ง ์์ ์์ธ์ ์ฐพ์ ๋ณด๋ค ์๋์ ๊ฐ์ ์ฌ์ค์ ์๊ฒ ๋์๋ค.
fixed ์์ฑ์ ๋ทฐํฌํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์์๋ฅผ ๋ฐฐ์นํ๋ ์์ฑ์ด๋ค. ๋ฐ๋ผ์, ํ์ด์ง์ ์คํฌ๋กค์ ์์ง์ฌ๋ ๊ณ ์ ๋ ์์น์ ์ถ๋ ฅ์ด ๋๋ค.
ํ์ง๋ง ๋ถ๋ชจ ์์์ transform ์์ฑ์ ์ ์ฉํ๋ฉด ์ด์ผ๊ธฐ๊ฐ ๋ฌ๋ผ์ง๊ฒ ๋๋ค. transform์ด ์ ์ฉ๋ ์ปดํฌ๋ํธ๋ ์๋ก์ด ๋ทฐํฌํธ๋ก ์ค์ ์ด ๋๋๋ฐ, ์ด ๋ ์์ ์์์ ์คํ์ผ์ fixed ์์ฑ์ด ์ ์ฉ๋์ด ์์ผ๋ฉด ์๋กญ๊ฒ ์ค์ ๋ ๋ทฐํฌํธ๊ฐ ์์์๊ฒ๋ ์ํฅ์ ๋ฏธ์น๊ฒ ๋๋ค.
๋ฐ๋ผ์ ์คํฌ๋กค์ ์์ง์ด๋ฉด ๋ถ๋ชจ ์์๋ฅผ ๋ฐ๋ผ fixed ์์ฑ์ด ์ ์ฉ๋ ์์๋ ๋ฐ๋ผ์ ์ค๊ฒ ๋๋ ๋ฒ๊ทธ๊ฐ ๋ฐ์ํ๋ค.
์ฌ๊ธฐ์ fixed ์์ฑ์ ์ ์ฉ ์ํค๊ธฐ ์ํ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ด ์๋ค.
1) ๋ถ๋ชจ์ transform์ ์ ๊ฑฐํ๋ ๊ฒ
2) position: sticky๋ก ์ ์ฉํ๋ ๊ฒ
sticky๋ fixed์ ๋ฌ๋ฆฌ ๊ณต๊ฐ์ ์ฐจ์งํ๋ค๋ ์ฐจ์ด์ ์ด ์์ง๋ง, ์คํ์ผ์ ์ด์ฉํ๋ค๋ฉด ์ด๋ ต์ง ์๊ฒ ๊ทธ๋ถ๋ถ์ ํด๊ฒฐํ ์ ์๋ค.
GSAP์ TextPlugin์ผ๋ก ํ์ดํ ํจ๊ณผ๋ฅผ ๋ง๋ค ์ ์๋ค.
gsap.to('.text', {
duration: 3,
ease: "none",
text: "ํ์ดํ ํจ๊ณผ๋ฅผ ๋ผ ์ ์์ด์!",
repeat: -1 // ๋ฌดํ ๋ฐ๋ณต
});
๐ก ์ค์ ํ๋ฉด ๋ณด๊ธฐ
์ฐธ๊ณ ์ฌ์ดํธ
https://lpla.tistory.com/136
https://im-developer.tistory.com/53
https://shawnkim.tistory.com/23
https://lpla.tistory.com/166
https://blog.pumpkin-raccoon.com/120