๊นํ๋ธ ๋ธ๋ก๊ทธ๋ฅผ ๊ตฌํํ๋ ์ค. ๋ค๋ฅธ ๋ธ๋ก๊ทธ๋ ํ์ด์ง์์ ํํ๊ฒ ๋ณผ ์ ์๋ โํ๋ฒํผโ์ ๊ตฌํํด๋ณด๊ธฐ๋ก ํ์ต๋๋ค.
์ ๋ ๊ธฐ์กด์ ๋ค๋ฅธ ํํ์ด์ง๋ฅผ ํด๋ก ์ฝ๋ฉํ๋ฉด์ ๊ตฌํํด ๋์ ์๋ฐ์คํฌ๋ฆฝํธ, ์ ์ด์ฟผ๋ฆฌ ์ฝ๋๋ฅผ ๊ฐ์ง๊ณ ์์์ต๋๋ค.
1. ๊ธฐ์กด์ ์ฝ๋ (jQuery)
$(document).ready(function() {
// main2์ ๋ด๋ ค๊ฐ๊ธฐ์ ๊น์ง ๋ฒํผ ์จ๊ธฐ๊ธฐ
$('.t-btn').hide();
// ์คํฌ๋กค ์ด๋ฒคํธ ๊ฐ์ง
$(window).scroll(function() {
// main2์ ์์น๋ฅผ ํ์ธํ์ฌ ๋ฒํผ ๋ณด์ด๊ธฐ/์จ๊ธฐ๊ธฐ
var section2Offset = $('.main2').offset().top;
if ($(window).scrollTop() > section2Offset) {
$('.t-btn').fadeIn();
} else {
$('.t-btn').fadeOut();
}
});
// ๋ฒํผ ํด๋ฆญ ์ ์๋จ์ผ๋ก ์คํฌ๋กค
$('.t-btn').click(function() {
$('html, body').animate({ scrollTop: 0 }, 'slow');
});
}
๊ธฐ์กด์ ์ฝ๋๋ฅผ ๊ฐ๋ณ๊ฒ ์ดํด๋ณด๋ฉด, ์คํฌ๋กค ์ด๋ฒคํธ๋ฅผ ์ฌ์ฉํ์ฌ ํ์ด์ง์ ์คํฌ๋กค ์์น๋ฅผ ๊ฐ์งํ๊ณ , ํน์ ์น์ (main2 ํด๋์ค)์ ๋๋ฌํ๋ฉด ๋ฒํผ์ ํ์ํ๊ณ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํ์ด์ง ์๋จ์ผ๋ก ์คํฌ๋กค์ก์ ํ๊ณ ์์ต๋๋ค.
ํ์ฌ ์ ๋ธ๋ก๊ทธ์์๋ Gatsby JS์ TypeScript๋ฅผ ์ฌ์ฉํ๊ธฐ์ ์๋ด์ผํ ๋ถ๋ถ์ด ์กฐ๊ธ ์์ต๋๋ค.
2. 1์ฐจ ์์ ์ฝ๋ (typescript)
document.addEventListener("DOMContentLoaded", function () {
// main2์ ๋ด๋ ค๊ฐ๊ธฐ์ ๊น์ง ๋ฒํผ ์จ๊ธฐ๊ธฐ
const tBtn = document.querySelector('.t-btn');
if (tBtn) {
tBtn.style.display = 'none';
}
// ์คํฌ๋กค ์ด๋ฒคํธ ๊ฐ์ง
window.addEventListener("scroll", function () {
// main2์ ์์น๋ฅผ ํ์ธํ์ฌ ๋ฒํผ ๋ณด์ด๊ธฐ/์จ๊ธฐ๊ธฐ
const main2 = document.querySelector('.main2');
if (main2) {
const section2Offset = main2.getBoundingClientRect().top;
if (window.scrollY > section2Offset) {
if (tBtn) {
tBtn.style.display = 'block';
}
} else {
if (tBtn) {
tBtn.style.display = 'none';
}
}
}
});
// ๋ฒํผ ํด๋ฆญ ์ ์๋จ์ผ๋ก ์คํฌ๋กค
if (tBtn) {
tBtn.addEventListener("click", function () {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
}
});
๊ธฐ์กด์ ๊ธฐ๋ฅ๊ณผ ๋์ผํ๊ฒ ๊ทธ๋๋ก Typescriptํ์์ผ๋ก๋ง ๋ฐ๊พธ์์ต๋๋ค. ์ฌ๊ธฐ์ ์ถ๊ฐ์ ์ผ๋ก ์์ ์ด ํ์ํฉ๋๋ค.
- main2 ํด๋์ค์ ์ฐ๊ฒฐ๋ ์คํฌ๋กค ์ด๋ฒคํธ๋ฅผ scrollY ๋ฅผ ์ด์ฉํ ์คํฌ๋กค ์ด๋ฒคํธ๋ก ์์
- ์ฌ๋ฌ querySeletor๋ฅผ ์ ๊ฑฐํ๊ณ ํจ์ํ ์ปดํฌ๋ํธ๋ก ๋ณํ
ํฌ๊ฒ ๋ณด๋ฉด ๋ ๊ฐ์ง์ธ๋ฐ, ์ ๊ฐ ์ค์ ๋ก ๊ฑฐ์ณ๊ฐ ๊ณผ์ ์ ์กฐ๊ธ ๋ณต์กํ์ต๋๋ค.
3. 2์ฐจ ์์ ์ฝ๋
// ์คํฌ๋กค ์ด๋ฒคํธ ๊ฐ์งํ์ฌ ๋ฒํผ ๋ณด์ด๊ธฐ/์จ๊ธฐ๊ธฐ
function handleScroll() {
const tBtn = document.querySelector('.tBtn')
if (tBtn instanceof HTMLElement) {
const scrollPosition = window.scrollY
if (scrollPosition > 500) {
tBtn.style.display = 'block'
} else {
tBtn.style.display = 'none'
}
}
}
// ๋ฒํผ ํด๋ฆญ ์ ์๋จ์ผ๋ก ์คํฌ๋กค
function scrollToTop() {
const tBtn = document.querySelector('.t-btn')
if (!tBtn) return
tBtn.addEventListener('click', function () {
window.scrollTo({ top: 0, behavior: 'smooth' })
})
}
// ํ์ด์ง ๋ก๋ ์ ์ด๊ธฐํ ๋ฐ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก
document.addEventListener('DOMContentLoaded', function () {
handleScroll()
scrollToTop()
// ์คํฌ๋กค ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก
window.addEventListener('scroll', handleScroll)
})
์ฒ์์๋ ESLint ์ค๋ฅ๊ฐ ๋ด์์ต๋๋ค. tBtn์ด โanyโํ์ ์ผ๋ก ๊ฐ์ฃผ๋์ด display์ ๊ฐ์ ์์ฑ์ ๋ํ ์์ ํ์ง ์์ ๋ฉค๋ฒ ์ก์ธ์ค๋ฅผ ์ํํ๊ณ ์๋ค๊ณ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๊ทธ๋์ tBtn์ HTMLElement ๋๋ null๋ก ์บ์คํ ํ์ฌ ํ์ ์์ ์ฑ์ ํ๋ณดํ๋๊ฒ ํ์ํ์ต๋๋ค.
๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ์ง์์ ์ผ๋ก ๋ฉค๋ฒ ์ก์ธ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ฌ querySelector๋ก ์ฐพ์ ์์๊ฐ ์ค์ ๋ก HTMLElement์์ Typescript์ ์๋ ค์ฃผ์ด์ผํ์ต๋๋ค. ์ด๋ฅผ ์ํด์ if (tBtn instanceof HTMLElement){}
๋ฅผ ํตํด ์ค๋ฅ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.
4. ํจ์ํ ์ปดํฌ๋ํธ
import React, { useState, useEffect } from 'react';
function TopButton() {
const [isVisible, setIsVisible] = useState(false);
useEffect(() => {
// ์คํฌ๋กค ์ด๋ฒคํธ ํธ๋ค๋ฌ
function handleScroll() {
const scrollPosition = window.scrollY;
setIsVisible(scrollPosition > 500);
}
// ์คํฌ๋กค ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก
window.addEventListener('scroll', handleScroll);
// ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋์์ ๋ ์ด๊ธฐ ์คํฌ๋กค ์์น์ ๋ฐ๋ผ ๋ฒํผ ๋ณด์ด๊ธฐ/์จ๊ธฐ๊ธฐ ์ค์
handleScroll();
// ์ปดํฌ๋ํธ ์ธ๋ง์ดํธ ์ ์คํฌ๋กค ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ ๊ฑฐ
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return (
<button
className="t-btn"
style={{ display: isVisible ? 'block' : 'none' }}
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
>
Top
</button>
);
}
export default TopButton;
TopButton ์ ํจ์ํ ์ปดํฌ๋ํธ๋ก ๋ณํํ์ต๋๋ค. ์ฝ๋๋ฅผ ํ ๋ฒ ๋ฆฌ๋ทฐํด๋ณด์๋ฉด,
import React, {useEffect} from โreactโ
์์ React์ useEffect๋ฅผ ์ํฌํธ ํ์ต๋๋ค. ํจ์ํ ์ปดํฌ๋ํธ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ์ ์ถ๊ฐํ ๋ ํ์ํ ๊ตฌ๋ฌธ์ ๋๋ค.funtion TopButton(){}
ํจ์ ์ปดํฌ๋ํธ๋ฅผ ์ ์ํ์ต๋๋ค.useEffect(() โ {โฆ}, [])
useEffect ํ ์ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ๋ ๋ ์คํํ ํจ์๋ฅผ ์ ์ ํ์ต๋๋ค. ๋น๋ฐฐ์ด์ ์ถ๊ฐํ์ฌ ์์กด์ฑ์ ๋์ํ์ต๋๋ค. ๊ทธ๋์ ๋ฐฐ์ด์ ํฌํจ๋ ๋ณ์๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง ํจ์๊ฐ ์คํ๋๋๋ก ํ์ต๋๋ค.funtion handleScroll() {}
์คํฌ๋กค ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์์ ๋๋ค.funtion scrollToTop() {}
ํ์ด์ง ์๋จ์ผ๋ก ์คํฌ๋กคํ๋ ๋ฒํผ ํด๋ฆญ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ํจ์์ ๋๋ค.
๊ฐ๋ตํ๊ฒ ์์ ๊ฐ์ ์ฝ๋๋ฅผ ํตํด Top Button์ ๊ตฌํํ์ต๋๋ค. ์ด์ ๋ฒํผ์ ํด๋ฆญํ๋ฉด ํ์ด์ง์ ์๋จ์ผ๋ก ์คํฌ๋กค ํ๋ ์ฝ๋๊ฐ ๋ง๋ค์ด์ก์ต๋๋ค.
์ด์ ์คํ์ผ๋ง ์ ํ์ฃผ๋ฉด ์ ๊ฐ ๊ณ ๋ฏผํ๊ฒ์ ๋์ด๋ฉ๋๋ค.
5. ์คํ์ผ ๊ฐ์ฒด๋ฅผ ์์ฑ
import React, { useState, useEffect } from 'react'
import '../styles/themeMode.css'
function TopButton() {
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
// ์คํฌ๋กค ์ด๋ฒคํธ ํธ๋ค๋ฌ
function handleScroll() {
const scrollPosition = window.scrollY
setIsVisible(scrollPosition > 500)
}
// ์คํฌ๋กค ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก
window.addEventListener('scroll', handleScroll)
// ์ปดํฌ๋ํธ๊ฐ ๋ง์ดํธ ๋์์ ๋ ์ด๊ธฐ ์คํฌ๋กค ์์น์ ๋ฐ๋ผ ๋ฒํผ ๋ณด์ด๊ธฐ/์จ๊ธฐ๊ธฐ ์ค์
handleScroll()
// ์ปดํฌ๋ํธ ์ธ๋ง์ดํธ ์ ์คํฌ๋กค ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ ๊ฑฐ
return () => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
// ์คํ์ผ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ํจ์
const buttonStyle: React.CSSProperties = {
position: 'fixed',
bottom: '110px',
right: '25px',
border: 'none',
borderRadius: '50%',
width: '50px',
height: '50px',
fontSize: '24px',
cursor: 'pointer',
display: isVisible ? 'block' : 'none', // isVisible ์ํ์ ๋ฐ๋ผ ๋์ ์ผ๋ก ์ค์
}
return (
<button
style={buttonStyle}
className="tBtn"
onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
>
๐
</button>
)
}
export default TopButton
cssํ์ผ์ ๋ฐ๋ก ๋ง๋ค์๋ ์์์ง๋ง, ๊ธฐ์กด์ ๋ค๋ฅธ ๊ธฐ๋ฅ๋ค๋ ์๋น๋ถ๋ถ ํจ์๋ฅผ ์ฌ์ฉํ์ฌ ์ปดํฌ๋ํธ ์คํ์ผ์ ๋์ ์ผ๋ก ์ค์ ํด์์์ต๋๋ค. ํต์ผ์ฑ์ ์ํด์ ์ปดํฌ๋ํธ ์คํ์ผ ํจ์๋ฅผ ์์ฑํ์ต๋๋ค.
์ถํ ๋ฆฌํฉํ ๋ง์ ํ๋ฉด์ CSS๋ฅผ ํ๋ฒ์ ๋บ์ง๋ ๋ค์ํ ๋ฒ ๊ณ ๋ฏผํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ ๊ฒ ํด์ TopButton.tsx ์ปดํฌ๋ํธ๋ ์์ฑ๋์์ต๋๋ค. ์์ง ์ต์ํ์ง ์์ Typescript๋ผ ๊ณผ์ ๋ ๋งค๋๋ฝ์ง ์๊ณ ์ฌ์ ์ด ๊ธธ์์ง๋ง ๊ธฐ์กด์ QuerrySelector ์ ์คํฌ๋กค ์ด๋ฒคํธ๋ฅผ ํจ์ํ ์ปดํฌ๋ํธ๋ก ์์ ํด๋ณผ ์ ์๋ ๊ฒฝํ์ ๊ฐ์ง์์์ด์ ๋ฟ๋ฏํ์ต๋๋ค.