์ด๋ฒ ํ๋ก์ ํธ ์ค ๊ฐ์ฅ ์ ๋ฅผ ๋จน์๋ ์ค๋์ค ๋ฐ ๋น๋์ค์ ์ค์ฒฉ์ ๋ง๊ณ ์ํ๋ ๊ธฐ๋ฅ์ ๋ํด ์ด์ผ๊ธฐ ํด๋ณด๊ณ ์ ํ๋ค.
์ค๋์ค, ๋น๋์ค, ์ด๋ฏธ์ง ์ฌ๋ฌ๊ฐ ๋ฑ ๋ค์ํ ์ฝํ ์ธ ๋ค์ด ๋์ด๋์ด ์๋ ์ํ์์ ์ฌ๋ฌ๊ฐ๋ฅผ ์คํ์ํฌ ์ ์๊ฒ๋ ์์ ์ ํด์ผํ๋ค. ์ด๋ ค์ธ๊ฑฐ๋ผ๊ณ ์๊ฐํด ๊ธฐํ์๋๊ณผ ํจ๊ป ์ด์ผ๊ธฐ ํ๋ฉฐ ์ํํ ๋ฐฉ๋ฒ์ ์ฐพ์๋ณด๊ณ ์ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ์๋ค์ ๋ง๋ค์ด๋ณด์๋๋ฐ
1. ํ๋ ์ด๋ฅผ ์ปจํธ๋กคํ๋ ๋ณด์ด์ง ์๋ player๋ฅผ ๋ง๋ค์ด์, ๊ทธ ๊ฐ์ฒด ํ๋๋ก์๋ง ์๋ ์ํจ๋ค.
-> ์ค๋์ค๋ ์ฌ์์ด ๋์ง๋ง ๋น๋์ค์ ์์์ด ๋ณด์ด์ง ์๋ ์ด์
2. ์ฌ๋ฌ๊ฐ์ ํ๋ ์ด๋ค์ ์ฌ์์ ๊ฐ์งํ๊ณ ์๋ค๊ฐ current Player์ด์ธ์ ๊ฒ๋ค์ ๋ชจ๋ pause ์ํด
-> ์ค์ ๋ก 1000๊ฑด์ด ๋๋ ์ฝํ
์ธ ๋ค๋ก ๋์ณ๋๋ค๋ฉด? (๐ค) ํ๋ ๊ถ๊ธ์ฆ๊ณผ ์ํ์ฑ ๋ฐํ
๋๋ฌธ์ ๋ ๋ค๋ฅธ ์ฌ์ด ๋ฐฉ๋ฒ์ด ์๊ฒ ์ง๋ง ๊ธฐํ์๋์ ์ํํ ์ํต๊ณผ ํต์พํ ์น๋ฝ์ผ๋ก ๊ฒฐ๊ณผ์ ์ผ๋ก๋ ํ๋ฉด์ ๋ทฐํฌํธ์ ๋๋ฌํ์ ๋ ์ด๋ฒคํธ๋ฅผ ๋ฐ์์ํค๋ ๊ฒ์ด ๊ฐ์ฅ ๋์ ๋ฏ ํ๋ค.
ํน์ ์์(target)๊ฐ ๊ทธ ์์์ ๋ถ๋ชจ๋ ๋ทฐํฌํธ์ ๊ต์ฐจํ๋์ง๋ฅผ ๋น๋๊ธฐ์ ์ผ๋ก ๊ฐ์งํ์ฌ, ๊ต์ฐจํ ๋๋ง๋ค ์ฝ๋ฐฑํจ์๋ฅผ ํธ์ถํ๋ API์ด๋ค.
const observer = new Intersection Observer(**callbackFunction**, **options**) {
observer.observe(targetElement)
}
useEffect(() => {
// ์ต์
์ค์
const options = {
root: null,
rootMargin: '-200px', // ๋ธ๋ผ์ฐ์ ํ๋ฉด๋ณด๋ค ์๊ฒ ๋ง๋ค๊ธฐ ์ํจ
threshold: 0.5,
}
const intersectionObserver = new IntersectionObserver((entries, observer) => {
// ๊ด์ฐฐํ ๊ฐ์ฒด๊ฐ ์ฌ๋ฌ๊ฐ์ด๋ฏ๋ก forEach ์ฌ์ฉ
entries.forEach(entry => {
let type = entry.target.nodeName;
// ๋ทฐํฌํธ์์๋ target ์์๊ฐ true์ผ ๋
if (entry.isIntersecting) {
if (entry.intersectionRatio > 0) {
if (type === 'VIDEO') {
// ์ ์ฉ๋๋ video ์๋์ฌ์ event
entry.target.play();
entry.target.nextElementSibling.classList.remove(styles.videoPlayIcon);
entry.target.addEventListener('timeupdate', (e) => {
let progress = entry.target.nextElementSibling.nextElementSibling;
progress.max = Math.floor(entry.target.duration);
progress.value = Math.floor(entry.target.currentTime);
})
}
}
} else {
// ๋ทฐํฌํธ์ ์์ญ์์ ๋ฒ์ด๋ฌ์ ๋
if (type === 'VIDEO') {
entry.target.pause();
entry.target.nextElementSibling.classList.add(styles.videoPlayIcon);
} else if (type === 'DIV') {
// audio์ ๊ฒฝ์ฐ์๋ clickํด์ผ ๋ฐ์ํ๋ ์ด๋ฒคํธ์ด๊ธฐ์, pause ๊ธฐ๋ฅ๋ง ์ถ๊ฐํ๋ค.
let audio = entry.target.children[1];
audio.nextElementSibling.classList.remove(styles.active);
audio.nextElementSibling.nextElementSibling.classList.remove(styles.pause);
return audio.pause();
}
}
})
}, options);
// observing ๋ ๊ฐ์ฒด๋ค
const content = document.querySelectorAll('.observerItem');
content.forEach(target => {
intersectionObserver.observe(target);
})
}, [])
entries
observer
๋ฆฌ์กํธ ์์ฒด ๋ด์์ ์ง์ ์ ์ธ DOM(๊ฐ์ฒด)์กฐ์์ ํผํ๊ธฐ๋ฅผ ๊ถ์ฅํ๋ฉฐ,
( ๐๐ปโโ๏ธ ? ์ํ๊ด๋ฆฌ์ ๊ดํ์ฌ ์ง์ ์ ์ธ DOM ๋ด๋ถ์ React ๋ด๋ถ์ ์ํ๋ฅผ ํผํฉํ๋ฉด ์ถ๋ก ํ๊ธฐ๊ฐ ์ด๋ ต๊ณ , ํ
์คํธํ๊ธฐ๊ฐ ์ด๋ ค์์ง๋ฏ๋ก)
๋ฆฌ์กํธ์ ๊ด๋ จ๋ DOM Selector ์ฐธ๊ณ
๋ํ ๋ฆฌ์กํธ์์๋ ํน์ DOM์ ์ ๊ทผํ ๋์๋ useRef() ๋ผ๋ ํ
์ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์
querySelector ์ ์ต์ํด์๋ ๋๋
๋ ๋์ ๋ฐฉ๋ฒ์ ์ฐพ๋๋ฐ์ ๋์ฑ ์ด๋ ค์์ ๋๋๊ฒ ์๋๊ฐ ์ถ๋ค.
๋ถ๊ฐ์ ์ผ๋ก Intersection Observer๋ ๋ณดํต ๋ฌดํ์คํฌ๋กค๋ง ๊ธฐ๋ฅ์ ๊ตฌํํ ๋ ์์ฃผ ์ฐ์ด๊ธฐ ๋๋ฌธ์,
๋ฌดํ์คํฌ๋กค๋ง ๊ธฐ๋ฅ์ฒ๋ผ ํ๋จ์ ๋ทฐํฌํธ๋ฅผ ๋ฌ์๋๋ ๊ฒ์ด ์๋, ๋ธ๋ผ์ฐ์ ์ ์์ฒด์ ๋ทฐํฌํธ๋ฅผ ๊ณ ๋ คํ๋ ๋ฐฉ๋ฒ์ด ๋ง์ง ์์๋ค.
์ด ๊ฒ ์ด์ธ์๋ ๋ค์ํ ๊ณณ์ ํ์ฉ๋๊ฐ ์์ ๊ฒ ๊ฐ๋ค๋ผ๋ ์๊ฐ๊ณผ,
์ธ ์ค ์์์ผ ์์ด๋ค๋ผ๋ ์๊ฐ์ด ๋ค์ํ๋ฒ ๋ ๋ค.๐ !