- ๋ฐฐํฌ URL : https://to-sjy.netlify.app/
- ๊ฐ๋ฐ์ฉ ๋ ํฌ์งํ ๋ฆฌ : https://github.com/Plush777/HBD-SJY-dev
- ๊ธฐ์ : HTML5, SCSS, Javascript (with jQuery)
- ๊ฐ๋ฐ๋๊ตฌ : VS code, gulp.js
- ๋ผ์ด๋ธ๋ฌ๋ฆฌ : lottie, confetti.js by CoderZ90, KAKAO API, Disqus, Google analytics
- ๋ฐฐํฌ : netlify
- ๊ธฐ๊ฐ : 2023.12.23 ~ 2023.12.31 (์ฝ 8์ผ)
- ์ฐธ๊ณ ์ฌ์ดํธ๋ค : 4์๊ฐ ์์ ๋์ ์์ผ๊ธฐ๋ ๐ ์น์ฌ์ดํธ ๋ง๋ค๊ธฐ ๋์์ ! , HTML5 birthday by ayusharma , ๋ค์ด๋ฒ์ฝ๋
- ํ๊ธฐ : Velog - ๐ฅณ๋์์ 15๋ฒ์งธ ์์ผ์ ์ถํํ๋ ์น์ฌ์ดํธ๐ฅณ
2024๋
2์ 25์ผ์ ์ ๋์์ 15๋ฒ์งธ ์์ผ์ด ๋๋ ๋ ์
๋๋ค!
๋์๊ณผ ๋์ด ์ฐจ์ด๊ฐ ๋ง์ด ๋์ ๊ทธ๋ฐ์ง, ์๋ก ์ธ์ฌํ๋ ๊ฒ๋ ์๋จนํ ์ฌ์ด์๊ธฐ ๋๋ฌธ์ ์ด์ ๋ถํฐ๋ผ๋ ์นํด์ง๊ณ ์(??) ์ ์ฑ๊ณผ ๋ง์์ด ๋ด๊ธด ์ํธ์ง์ ํ์ ๊ฐ์งํ ์ ์๋ ์น ์ฌ์ดํธ๋ฅผ ์ฃผ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๊ตฌ๊ธ์ ์ ๋ฌผ๋ก ์์ผ ์ถํ ์ฌ์ดํธ๋ฅผ ๋ง๋ ์ฌ๋์ด ์์๊น? ํ๊ณ ์ฐพ์๋ดค๋๋ฐ ๊ทธ๋ฐ ์ฌ๋ก๊ฐ ์๊ฐ๋ณด๋ค ๋ง์์ ์ฐธ๊ณ ๋ ๋ง์ด ํ์ด์ ๐คฃ๐คฃ
์ฌ์ค ์์ฆ ๋์ธ์ธ ๊ธฐ์ ์ React, Vue ๊ฐ์ SPA ํ๋ ์์ํฌ ์๋๋ฉด ์์ ๋ฐ๋๋ผ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๊ฐ๋ ์ถ์ธ์ง๋ง,
์ ํํ๊ฒ ์๊ณ ์ฐ๋ ๋๋๋ ์๋๊ณ ๋์กฐ์์ด ๋ ์ฌ์์ ์ ์ด์ฟผ๋ฆฌ๋ฅผ ์ ํํ์ต๋๋ค.
ํด๋๊ตฌ์กฐ๋ ๋ฃจํธ์ index.html์ด ์๊ณ , images , scss , js ํด๋๋ก ๊ฐ๊ฐ ๋๋ ์ฃผ์์ต๋๋ค.
import { hash } from '../js/modules/hash.js';
import { view } from '../js/modules/view.js';
import { favi } from '../js/modules/favi.js';
import { kakao } from '../js/modules/config/kakao.js';
$(function () {
kakao();
hash();
view();
favi();
});
ํ์์ ๋ค๋ฅธ ์ ์ด์๋ค๋ฉด, ๊ถ๊ธํด์ script module ํ์์ผ๋ก ์์
ํด๋ณด์์ต๋๋ค.
๊ธฐ์กด์ ํ js ํ์ผ์ ๋ค ๋๋ ค๋ฐ์๋๋ฐ (...) ๋ฆฌ์กํธ์ฒ๋ผ ์ญํ ๋ณ๋ก ๋ถ๋ฆฌ ์์ผ๋์ผ๋๊น
๊ฐ๋
์ฑ ์ธก๋ฉด์์ ์ด ๋ฐฉ๋ฒ์ด ๋ ๊ด์ฐฎ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
ํ์ด์ง๋ ๋ค์๊ณผ ๊ฐ์ด ์ด 4๊ฐ๋ก ๊ตฌ์ฑํ์ต๋๋ค.
- ๋ฉ์ธ : ์์ผ๊น์ง ๋จ์ ์๊ฐ์ ํ์ด๋จธ๋ก ๋ณด์ฌ์ค๋๋ค.
- ํธ์ง : ์ง์ ์ด ์์ผ ํธ์ง๋ฅผ ๋ณผ ์ ์์ต๋๋ค. (์์ผ ๋น์ฌ์๋ง)
- ๋์๊ฒ ๋ณด๋ด๋ ๋ฉ์์ง : ๋ฒํผ์ ๋๋ฅด๋ฉด ๋ ธ๋๊ฐ ์ฌ์๋จ๊ณผ ํจ๊ป ๋ฉ์์ง๋ฅผ ์์ฐจ์ ์ผ๋ก ๋ณด์ฌ์ค๋๋ค.
- ๊ณต์ ๋ฐ ๋๊ธ : ํด๋น ํ์ด์ง๋ฅผ SNS (์นดํก, ํ์ด์ค๋ถ, ํธ์ํฐ) ์ ๊ณต์ ํ ์ ์๊ณ , ์์ผ ์ถํ ๋๊ธ์ ๋ฌ ์ ์์ต๋๋ค.
๋๋ฐ์ด ๊ณ์ฐ ํ์ด๋จธ๋ ์ด ๊ฒ์๊ธ ์ ์ฐธ๊ณ ํ์ต๋๋ค!
์์ผ ์ , ์์ผ ๋น์ผ, ์์ผ ์ดํ๋ฅผ ๊ตฌํ์ฌ ๋ฌธ๊ตฌ์ ๋ฒํผ ์ํ๋ฅผ ๊ฐ๊ฐ ๋ณ๊ฒฝํด์ฃผ์์ต๋๋ค.
const dDayDate = new Date("Feb 25, 2024, 0:00:00").getTime();
//setInterval ์์์๋ timeDifference ๋ณ์๋ฅผ ์ ์ญ๋ณ์๋ก
let globalDifference;
// let globalDays;
setInterval(() => {
// ํ์ฌ ๋ ์ง์ ๋๋ฐ์ด ๋ ์ง์ ์ฐจ์ด ๊ณ์ฐ
let currentDate = new Date().getTime();
const timeDifference = dDayDate - currentDate;
globalDifference = timeDifference;
// ๋จ์ ์ผ์, ์๊ฐ, ๋ถ, ์ด ๊ณ์ฐ
let days = Math.ceil(timeDifference / (1000 * 60 * 60 * 24));
let hours = Math.ceil((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.ceil((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
let seconds = Math.ceil((timeDifference % (1000 * 60)) / 1000);
hours = (hours < 10) ? `0${hours}` : `${hours}`;
minutes = (minutes < 10) ? `0${minutes}` : `${minutes}`;
seconds = (seconds < 10) ? `0${seconds}` : `${seconds}`;
$('#dDay').html(`D-${days}`);
$('#time').html(`${hours}:${minutes}:${seconds}`);
days = Math.abs(days);
// globalDays = days;
// ๋๋ฐ์ด๊ฐ ์ง๋ฌ์ ๊ฒฝ์ฐ
if (timeDifference < 0) {
$('#dDay').html(`์์ผ์ด ์ง๋ฌ๋ค์!<br/>D+${days}`);
$('#dayCountPage #desc').text('์ด์ ์ ๋ฌผ์ ์ด์ด๋ด์!');
$('#time').remove();
$btnGift.removeClass('disabled');
} else {
$('#dayCountPage #desc').text('์์ผ์ ๋ฌผ ์คํ๊น์ง...');
}
//๋๋ฐ์ด ์ผ๊ฒฝ์ฐ
if (days === 0) {
$('#dDay').html(`๋๋์ด ์ค๋์ด๋ค์! ์์ผ ์ถํํด์<br/>D-day`);
}
}, 1000);
timeDifference ๊ฐ์ setInterval ๊ตฌ๋ฌธ ๋ฐ์์ ์ฌ์ฉํด์ผํ๊ธฐ ๋๋ฌธ์, ์ ์ญ ๋ณ์ (globalDifference) ๋ฅผ ๋ฐ๋ก ์ ์ธํด์
๊ฐ์ ์ ์ญ ๋ณ์์ ๊ทธ๋๋ก ๋ฃ์ด์ฃผ์์ต๋๋ค.
์๋ ์ฝ๋๋ ๋ธ๋ผ์ฐ์ ์/๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ์ ๋๋ ์ ๋์ btnGift ๋ฒํผ์ ๋๋ ์ ๋์ ์ด๋ฒคํธ ์ฒ๋ฆฌ๋ฅผ ๊ฐ๊ฐ ํด์ฃผ์์ต๋๋ค.
setTimeout์ ์ค ์ด์ ๋, ํ์ด์ง๊ฐ ๋ฐ๋ ๋ ๊ธฐ์กด ์ฝํ
์ธ ๋ ์ง์์ง๊ณ ์๋ก์ด ์ฝํ
์ธ ๊ฐ ์์ฑ๋๋๋ฐ,
๊ทธ ๊ณผ์ ์์ #btnGift ์
๋ ํฐ๋ฅผ ์ฆ์ ๋ชป์ฐพ๋ ๊ฒ ๊ฐ์์ ์ฝ๊ฐ์ ๋๋ ์ด๋ฅผ ์ฃผ์์ต๋๋ค.
window.addEventListener('popstate', function() {
// ๋๋ฐ์ด๊ฐ ์ง๋๊ฒฝ์ฐ
if (globalDifference < 0) {
setTimeout(() => {
$('#btnGift').removeClass('disabled');
}, 1);
}
});
$(document).on('click', '#btnGift', function(e) {
// ๋๋ฐ์ด๊ฐ ์ง๋์ง ์์์ ๊ฒฝ์ฐ
if (globalDifference > 0) {
alert('2024๋
2์ 25์ผ์ ์คํํ ์ ์์ด์.');
e.preventDefault();
}
});
ํธ์ง ์ ๋๋ฉ์ด์
์ dribble envelope open ๊ธ์ ์ฐธ๊ณ ํ์ต๋๋ค.
ํธ์ง๋ฅผ ํด๋ฆญํ๋ฉด ์ฃผ์ ํ์
์ด ๋จ๊ณ , ์์์ด์ ๋ฒํผ์ ๋๋ฅด๋ฉด ํด๋น ๋งํฌ๋ก ์ด๋ํฉ๋๋ค.
์์ผ ํธ์ง๋ฅผ ๊ตฌ๊ธ๋๋ผ์ด๋ธ์ pdf ํ์์ผ๋ก ์
๋ก๋ํ๊ณ , ์๋ฌด๋ ์ด๋ํ๋ฉด ์๋๊ธฐ ๋๋ฌธ์ ๊ณต์ URL์
LOCK.PUB - URL ๋จ์ถ ์ํธํ ์๋น์ค ๋ก ์ ํด์ง ํจ์ค์๋๋ฅผ ์
๋ ฅํด์ผ๋ง ๊ตฌ๊ธ ๋๋ผ์ด๋ธ๋ก ๊ฐ์ ๋ณผ ์ ์๊ฒ ํด์ฃผ์์ต๋๋ค.
<div class="lyricsWrapper">
<div class="lyricsRow">
<p>์ ์ ๋์ด์ก์ง ๊ด์ฐฎ์ ์ก์์ค๊ฒ ๋ ๋ง์ด ๊ฑฑ์ ํ๋</p>
<p>No no no ์์ง ์ฒ์์ด์์<br />
๊ทธ๊ฒ์ฏค์ ๋ค ๊ด์ฐฎ์ ๋ค ๊ทธ๋ฐ ๊ฑฐ์ง</p>
<p>์๋ ๊ทธ๋ ๋ค ์ด๋ฅธ๋ค๋ ์ฐ๋ฆฌ ๋์ด ๋ ๋ค ์ค์ํ๊ณ ์ฐ์ตํ๋ฉฐ ์ฑ์ฅํ์๋</p>
<p>์ฐ๋ฆฐ ์์ง ์ฒ์์ธ ๊ฒ๋ค์ด ๋ง์์ <br />
๊ด์ฐฎ์ ์ฐ๋ฆฌ๋ ๊ฒช์ด๋ณด๋ฉฐ ํฌ๋ฉด ๋์์ ์ธ์ง๋ง</p>
<p>์ ์ ๋ค์ฒ์ง๋ฉด ์กฐ๊ธ ์ฌ์ด๊ฐ๋ฉด ๋ผ <br />
๋๋ ์ ํ๊ณ ์์ด ๋ ์ ์ ํ๋ค ๋</p>
<p>๋ด๊ฐ ๊ฐ์ด ๋ฐ์ด์ค๊ฒ ๊ฑฑ์ ์ ๊ณ <br />
์ผ์ด๋ ํ์ ๊ฑท์ด ์ฌ๋ ค ํฌ๊ธฐ ๋ฐ์ ์ ์ด</p>
<p>๋ ์ ํ๊ณ ์์ด oh</p>
<p>๋ ์ ํ๊ณ ์์ด yeah</p>
<p>ํ๋ด ์ข ์ฐธ์ผ๋ฉด ๋ผ ๋ด๊ฐ ๊ณ์ ์์๊ฒ</p>
<p>๋ ์ ํ๊ณ ์์ด oh, ๋ ์ ํ๊ณ ์์ด</p>
<p>You gotta take your time ํ ์ ์์์<br />
๋๋ ์ ํ ์ ์์ด
</p>
</div>
</div>
html์์ ๋ณด์ฌ์ค ๋
ธ๋ ๊ฐ์ฌ๋ค์ ๋จผ์ ์์ฑํ๊ณ , js์์ ๊ฐ์๋ ์๊ฐ์ ๋ฐฐ์ด๋ก ๋ด์์
for๋ฌธ๊ณผ setTimeout์ ํตํด ์ง์ ํ ์๊ฐ๋๋ก ๋ณด์ฌ์ค ์ ์๋๋ก ํด์ฃผ์์ต๋๋ค.
์๊ฐ ๊ตฌํ๋๊ฑด ๋ ธ๋ ํ์ด๋ฐ์ ๋ง์ถฐ์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ ธ๋ ๋ค์ผ๋ฉด์ ์ง์ ๋ง์ท์ต๋๋ค... ๐๐
const timerIndexArr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
const timerMsArr = [24500, 29100, 34500, 39800, 46300, 51500, 57500, 60200, 62800, 68800, 74500];
setTimeout(() => {
$('#musicLoader').addClass('active');
}, 1500);
setTimeout(() => {
$('#musicLoader').removeClass('active');
}, 23500);
setTimeout(() => {
handleOpacity('#btnNext', 1, 1);
}, 84000);
for (let i = 0; i < timerIndexArr.length; i++) {
const index = timerIndexArr[i];
const ms = timerMsArr[i];
setTimeout(() => {
$(`.lyricsRow p:nth-child(${index})`).addClass('active');
}, ms);
}
sns ๊ณต์ ๋ ์นด์นด์ค ๊ณต์ api๋ฅผ ์ฌ์ฉํ์๊ณ ํ์ด์ค๋ถ์ด๋ ํธ์ํฐ๋ ๊ณต์ url์ ๋ฐ๋ก ์ ๊ณตํ๊ธธ๋
์๋์ฒ๋ผ ์์ฑํ์ต๋๋ค~
๋๊ธ์ ๊ฒฝ์ฐ๋ ์ง์ ๋ง๋ค ์์ ์ด ์์ด์ Disqus ๋ผ๋ ํด์ธ ๋ฌด๋ฃ ๋๊ธ ์๋น์ค๊ฐ
์๊ธธ๋ ์ด ์น๊ตฌ๋ฅผ ์ฌ์ฉํ์ต๋๋ค ๐
function sendTwitter() {
const text = 'blabla';
const sendUrl = `https://twitter.com/intent/tweet?text=${text}&url=${location.href}`;
window.open(sendUrl, "_blank");
}
function sendFacebook() {
const sendUrl = `https://www.facebook.com/sharer/sharer.php?u=${location.href}`;
window.open(sendUrl, "_blank");
}
๋ค์ด๋ฒ์ฝ๋ ์ฌ์ดํธ ๊ฐ๋ณด๋, ํ๋น์ฝ์ด ์ผ์ ์๊ฐ๋ง๋ค ๋ฐ๋๊ธธ๋ ์ข์ ์์ด๋์ด์ธ ๊ฒ ๊ฐ์์ ์ ๋ ๋ฐ๋ผํด๋ดค์ต๋๋ค (?)
๋ค์ด๋ฒ ์ฝ๋์์๋ svg ์ฝ๋๋ฅผ data URI ํ์์ผ๋ก ๋ฐ๊ฟ์ ์ฐ๋ ๊ฒ ๊ฐ์๋ฐ, ์๋ฌด๋ฆฌ ํด๋ด๋ ์๋์ ๊ทธ๋ฅ png๋ก ํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ชจ๋ฐ์ผ ๊ธฐ๊ธฐ์์๋ ํ๋น์ฝ ๋๋ฌธ์ธ์ง๋ ๋ชจ๋ฅด๊ฒ ์ผ๋, ์ฌ์ดํธ ์์ฒด๊ฐ ๋๋ ค์ง๋ ๊ฒ ๊ฐ์์
ํด์๋๊ฐ 768 ์ด์์ผ๋๋ง ํ๋น์ฝ์ ๋ฐ๊พธ๋๋ก ์์
ํ์ต๋๋ค.
<link rel="shortcut icon" id="favi" href="./images/ico/ico-favicon01.png" />
if (window.matchMedia('(max-width: 768px)').matches) {
return;
} else {
const f = document.getElementById('favi');
let i = 0;
setInterval(() => {
i = (i + 1) % 4;
f.href = `../images/ico/ico-favicon0${i + 1}.png`;
}, 2000);
}
๊ฐ๋ฐ ๊ธฐ๊ฐ 8์ผ ์ค ์ ๋ฐ ์ด์์ ๋ด์ฉ ๊ตฌ์๊ณผ ๋์์ธ ๊ณ ๋ฏผ๋ง ๋ ํ๋ ๊ฒ ๊ฐ๋ค์ ๐
๐
๋ค ๋ง๋ค๊ณ ๋ฐฐํฌ ํ ์ญ ๋๋ฌ๋ณด๋๊น ๋ฟ๋ฏํ๊ณ , ์๋ค๋ฅธ ๊ฒฝํ์ ํ๋ ๊ฒ ๊ฐ์ต๋๋ค.
ํ๋ ์์ฌ์ด์ ์, ๊ทธ๋ฅ ์ฒ์๋ถํฐ ๋ฆฌ์กํธ๋ก ํ ๊ฑธ? ์ด๋ ์๊ฐ์ด ๋ค์์ด์.
์ฌ๋ฌ ๊ฐ์ HTML์ ๋ง๋ค์ด์ ํ๋ํ๋ ๋งํฌ ์ํค์ง ์๊ณ , ํ์ด์ง ์ด๋์ ํด์ฌ (#) ๋ก ์ง์ ํ ๋ค์ ๋ฒํผ์ ํด๋ฆญํ์ ๋
ํน์ hash๋ก ์ด๋ํ๋ฉด ํด๋น div๋ฅผ ๋ณด์ฌ์ฃผ๋ ํ์์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๋๋ฐ,
ex)
localhost:3000/#main => 1๋ฒ div ๋ณด์ฌ์ค
localhost:3000/#intro => 1๋ฒ div๋ ์์ ๊ณ 2๋ฒ div ๋ณด์ฌ์ค
์ด๋ฐ๊ฑฐ ์ง์ ๊ตฌํ ํ ์๊ฐ์ ๊ทธ๋ฅ SPA๋ก ํ๋๊ฒ ๋ ๊น๋ํ์ง ์์์๊น.. ์ถ์์ด์.
๊ทธ๋๋ ์ด ๊ณผ์ ์์ ๋ฐฐ์ด๊ฑด ์์์ต๋๋ค.
์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ค์ popstate
์ onhashchange
๋ผ๋ ๊ฒ๋ ์๋ค๋๊ฑธ ์๊ฒ๋์๊ณ
์คํฌ๋ฆฝํธ๋ฅผ ๋ชจ๋๋ก ๋๋ ์ ๊ฐ๋ฐํ๋ ๊ฒ๋ ๋์์ง ์๋ค! ๋ผ๋ ๊ฑธ ๋๋ ๊ฒ ๊ฐ์์.
์๋ฌดํผ, ๊ธํ๊ฒ ๊ธฐํํด์ ๋ฐฐํฌ๊น์ง ํด๋จ๋๋ฐ, ์์ผ๋ ๋์์ด ์ข์ํ์ผ๋ฉด ์ข๊ฒ ์ด์ ๐๐
- ๋ ธ๋ : ์คํธ๋ ์ดํค์ฆ (StrayKids) - ์ํ๊ณ ์์ด
- ํฐํธ : ๋๋์๊ธ์จ ์คํ์
- ํ๋น์ฝ : Free Favicon Maker