A Pen by kiimsumiin on CodePen.
Created
June 16, 2025 14:52
-
-
Save kiimsumiin/80b384edf025c2b87233a679440a902a to your computer and use it in GitHub Desktop.
interactivetypography
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ko"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>인터랙티브 북</title> | |
<link rel="stylesheet" href="style.css" /> | |
</head> | |
<body> | |
<audio id="bg-music" src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/videoplayback_0_to_10min.mp3" loop preload="auto"></audio> | |
<audio id="flip-sound" src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/book-opening-345808.mp3" preload="auto"></audio> | |
<div class="orientation-warning"> | |
이 웹사이트는 가로 모드에서만 사용 가능합니다. | |
</div> | |
<div class="intro-screen"> | |
<div class="intro-scaler"> | |
<div class="type-area"> | |
<span id="text"></span> | |
<img id="turtle" src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/turtle.svg" alt="turtle" /> | |
</div> | |
</div> | |
</div> | |
<!-- 책 컨테이너 --> | |
<div class="book-wrapper"> | |
<div class="book" id="book" style="display: none;"> | |
<!-- 책 페이지들 (기존 코드 유지) --> | |
<div class="page cover"> | |
<div class="page-face front"> | |
<div class="cover-page"> | |
<!-- 중앙 타이틀 SVG 삽입 --> | |
<img src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/title4.svg" class="cover-title-svg" /> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<div class="page"> | |
<div class="page-face front"> | |
<img src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/page1%2B.svg" | |
class="svg-page1-background" /> | |
<div class="left-page"> | |
<div class="page-num left-page-num">001</div> | |
<!-- 기존 상단 SVG --> | |
<img src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/page1.svg" | |
class="svg-img" /> | |
<div class="caption left-align-caption"></div> | |
</div> | |
<div class="right-page"> | |
<p> 중국 신화에 따르면,</p> | |
<p>거북은 단순한 동물이 아닌 세상의 시작과 창조에 깊이 관여한 존재이다.</p> | |
<div class="visual-block"></div> | |
<p> 이 신비로운 존재는 혼돈으로 가득 찬 초기 우주의 균형을 잡기 위한 하나의 기둥이었으며, 창조의 모든 순간에 조용하지만 강인한 모습으로 등장한다.</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 2페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<div class="left-page"> | |
<div class="page-num left-page-num">002</div> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page2.svg" class="svg-page2-background" /> | |
<div class="caption left-align-caption"></div> | |
</div> | |
<div class="right-page"> | |
<p> | |
천황씨(天皇氏) 이전의 세계는<br> | |
형체도 방향도 없는,<br> | |
어둠과 소용돌이로 가득한 대혼돈의 상태였다.<br> | |
시간도 없고 공간도 정의되지 않았던 그곳은<br> | |
회전하고 응축되어 하나의 우주알로 변화했다. | |
</p> | |
<p> | |
이 알 속에는 무수한 가능성과 아직 태어나지 않은 생명,<br> | |
세상의 구조와 이치를 구성할 수 있는 잠재력이 농축되어 있었다.<br><br> | |
그리고 그 알의 중심에서,<br> | |
인간과 신의 중간자라 불릴 수 있는 존재,<br> | |
<strong>반고씨(盤古氏)</strong>가 깨어났다. | |
</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<div class="page"> | |
<div class="page-face front"> | |
<!-- 표현적 SVG 자유 배치 --> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page33.svg" | |
class="svg-page3-background" /> | |
<div class="left-page"> | |
<div class="page-num left-page-num">003</div> | |
<!-- 왼쪽 콘텐츠 비움 --> | |
<div class="caption left-align-caption"></div> | |
</div> | |
<div class="right-page"> | |
<p>그는 눈을 떴다.</p> | |
<p> | |
자신이 어두운 공간 안에 갇혀 있다는 사실을 깨달았다.<br> | |
반고씨는 인간보다 훨씬 더 위엄 있는 존재였다.<br> | |
뿔, 푸른 털, 태양과 달처럼 균형을 이룬 눈동자.<br><br> | |
처음엔 방황했지만, 곧 그는 자신이 존재해야 할 이유를 알았다. <br> <Br> <strong> 그는 혼돈을 </strong> | |
</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 4페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<div class="left-page"> | |
<div class="page-num left-page-num">004</div> | |
<div class="caption left-align-caption"></div> | |
</div> | |
<!-- 오른쪽 페이지 --> | |
<div class="right-page"> | |
<p>그의 두 손에 망치와 끌이 나타났고, 그는 그것들을 들고 어둠의 심연을 향해 내리치기 시작했다. ‘딱! 쾅! 퉁!’ 음과 양의 기운이 충돌하며 서로 분리되었고, 그 가운데에서 하늘과 땅이 태어났다.</p> | |
<p>하늘은 가벼운 기운(양기)이 되어 위로 솟았고, 땅은 무거운 기운(음기)이 되어 아래로 가라앉았다. 하지만 음양은 다시 합쳐지려는 본성을 가지고 있었기에, 반고는 그 사이에서 스스로를 기둥 삼아 버텼다. 그의 다리는 땅을 딛고 있었고, 양팔은 하늘을 향해 뻗어 있었다.</p> | |
<p>이러한 상태로 1만 8천년 동안 그는 고통과 외로움을 견뎠다. 그동안 하늘은 매일 3미터씩 높아졌고, 땅은 3미터씩 넓어졌다. 그에 따라 반고의 키 역시 매일 3미터씩 자라났다. 그는 점점 거인이 되었고, 마침내 그의 키는 천지 사이를 완전히 가로 지르게 되었다.</p> | |
</div> | |
<!-- 땅 SVG는 가장 마지막에 위치 --> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page4%2B.svg" | |
class="svg-page4-ground" /> | |
<!-- 구름 SVG 2개 --> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page4%2B%2B.svg" | |
class="svg-page4-cloud cloud1" /> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page4%2B%2B%2B.svg" | |
class="svg-page4-cloud cloud2" /> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 5페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<div class="left-page"> | |
<div class="big-char left-align"></div> | |
<div class="caption left-align-caption"></div> | |
<div class="page-num left-page-num">005</div> | |
</div> | |
<div class="right-page"> | |
<p>그의 숨결은 바람이 되었고, 그의 목소리는 천둥이 되었으며, 왼쪽 눈은 태양, 오른쪽 눈은 달이 되었다. 그의 피는 강이 되어 흐르고, 근육은 대지를 이루며 비옥한 땅을 만들어냈다.</p> | |
<p>그의 뼈는 단단한 바위와 광물이 되었고, 골수는 신성한 보석(다이아몬드)으로 남았다. 털은 숲이 되고, 그의 땀은 비가 되어 세상에 내렸다. 그가 품었던 벼룩, 진드기 같은 작은 생물들은 변형되어 물고기와 각종 동물이 되었고, 그의 목덜미에 붙어 있던 가장 영리한 존재는 인간이 되었다.</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 6페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<!-- 뱀 SVG: 전체 하단 이동 --> | |
<img src="https://raw.githubusercontent.com/kiimsumiin/typography-book/main/page66.svg" | |
class="svg-page6-snake" /> | |
<div class="left-page"> | |
<div class="caption left-align-caption"></div> | |
<div class="page-num left-page-num">006</div> | |
</div> | |
<div class="right-page"> | |
<p>그의 창조물 중에서 가장 신비로운 존재는 인간의 원형이었다. 복희씨(伏羲氏)와 여와(女媧)는 그의 마지막 숨결 속에서 태어났다. 이들은 인간과 비슷했지만, 하체는 뱀처럼 길고 부드러웠다.</p> | |
<p>복희와 여와는 부부가 되어 진흙을 빚었고, 그 안에 신성한 숨결을 불어넣었다. 이 진흙 형상들은 하나씩 깨어나 인간이 되었다.</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 7페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<!-- 흐릿한 배경 SVG 추가 --> | |
<img src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/page1%2B.svg" | |
class="svg-page1-background2" /> | |
<div class="full-page-center-text"> | |
그들은 최초의 인간이었다. | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 8페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<div class="left-page"> | |
<img src="https://cdn.jsdelivr.net/gh/kiimsumiin/typography-book/page8.svg | |
" class="svg-img left-align" /> | |
<div class="caption left-align-caption"></div> | |
<div class="page-num left-page-num">008</div> | |
</div> | |
<div class="right-page"> | |
<p>그러나 이 창조는 결코 완벽하지 않았다.</p> | |
<p>혼돈은 사라지지 않고 여전히 세계 어딘가에 도사리고 있었다. </p> | |
<p>그러자 공공(共工)이라는 신이 나타나 홍수를 일으키고, 하늘을 무너뜨리고, 산을 가루로 만들었다.</p> | |
<p>세상은 다시 붕괴되려 했다.</p> | |
<p>이때 여와는 바다거북의 네 다리를 잘라 하늘 네 방향을 지탱하게 했고, 지푸라기와 재로 물을 빨아들여 땅을 회복시켰다.</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
<!-- 9페이지 --> | |
<div class="page"> | |
<div class="page-face front"> | |
<div class="left-page"> | |
<div class="big-char left-align">끝</div> | |
<div class="caption left-align-caption"></div> | |
<div class="page-num left-page-num">009</div> | |
</div> | |
<div class="right-page"> | |
<p>여와는 대지의 어머니가 되었고, 복희는 인간의 문명을 기록하고 전파한 아버지가 되었다.</p> | |
<p>이렇게 하여 인간 세계는 유지되었고, 지금 우리가 아는 천지 만물이 유지되고 있는 것이다.</p> | |
</div> | |
</div> | |
<div class="page-face back"></div> | |
</div> | |
</div> | |
</div> | |
<script src="script.js"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function isMobile() { | |
return /Mobi|Android|iPhone|iPad|iPod/i.test(navigator.userAgent); | |
} | |
function handleOrientationChange() { | |
const warning = document.querySelector('.orientation-warning'); | |
const bookEl = document.getElementById('book'); | |
const introEl = document.querySelector('.intro-screen'); | |
if (isMobile() && window.innerHeight > window.innerWidth) { | |
warning.style.display = 'flex'; | |
bookEl.style.display = 'none'; | |
introEl.style.display = 'none'; | |
} else { | |
warning.style.display = 'none'; | |
if (!bookEl.classList.contains('visible')) { | |
introEl.style.display = 'flex'; | |
} | |
} | |
} | |
// ✅ 화면 크기에 맞게 책을 축소(scale) | |
function scaleBookToFit() { | |
const book = document.getElementById("book"); | |
if (!book) return; | |
const vw = window.innerWidth; | |
const vh = window.innerHeight; | |
const scaleX = vw / 900; | |
const scaleY = vh / 600; | |
const scale = Math.min(scaleX, scaleY, 1); // 1 이상 확대 방지 | |
book.style.setProperty('--book-scale', scale); | |
} | |
window.addEventListener('load', () => { | |
handleOrientationChange(); | |
scaleBookToFit(); | |
}); | |
window.addEventListener('resize', () => { | |
handleOrientationChange(); | |
scaleBookToFit(); | |
}); | |
document.addEventListener("DOMContentLoaded", () => { | |
const textEl = document.getElementById("text"); | |
const turtleEl = document.getElementById("turtle"); | |
const introEl = document.querySelector(".intro-screen"); | |
const bookEl = document.getElementById("book"); | |
const bgMusic = document.getElementById("bg-music"); | |
const flipSound = document.getElementById("flip-sound"); | |
const pages = document.querySelectorAll(".page"); | |
const message = "“천황씨(天皇氏) 이전 우주에는 형상이 없는 혼돈만이 존재하고 있었다.”"; | |
let i = 0; | |
function initializeBook() { | |
let flippedCount = 0; | |
let bookClosed = false; | |
pages.forEach((page, index) => { | |
page.style.zIndex = pages.length - index; | |
page.classList.remove("flipped"); | |
page.addEventListener("click", () => { | |
const isLastPage = index === pages.length - 1; | |
if (flipSound) { | |
flipSound.currentTime = 0; | |
flipSound.play().catch(() => {}); | |
} | |
if (!bookClosed && !page.classList.contains("flipped")) { | |
page.classList.add("flipped"); | |
flippedCount++; | |
if (flippedCount === pages.length - 1 && isLastPage) bookClosed = true; | |
} else if (bookClosed && isLastPage) { | |
pages.forEach(p => p.classList.remove("flipped")); | |
flippedCount = 0; | |
bookClosed = false; | |
} | |
}); | |
}); | |
} | |
function playBackgroundMusic() { | |
if (!bgMusic) return; | |
bgMusic.volume = 0.2; | |
bgMusic.play().catch(() => { | |
document.body.addEventListener("click", () => { | |
bgMusic.play().catch(err => console.log("음악 재생 실패:", err)); | |
}, { once: true }); | |
}); | |
} | |
function typeChar() { | |
if (i < message.length) { | |
textEl.textContent += message[i]; | |
i++; | |
turtleEl.style.transform = `translateX(${textEl.offsetWidth}px)`; | |
setTimeout(typeChar, 120); | |
} else { | |
setTimeout(() => { | |
introEl.style.opacity = '0'; | |
setTimeout(() => { | |
introEl.style.display = 'none'; | |
bookEl.style.display = 'block'; | |
bookEl.style.opacity = '0'; | |
bookEl.style.transition = 'opacity 1s ease'; | |
playBackgroundMusic(); | |
initializeBook(); | |
scaleBookToFit(); // ✅ 책 등장 시에도 비율 맞추기 | |
requestAnimationFrame(() => { | |
requestAnimationFrame(() => { | |
bookEl.style.opacity = '1'; | |
}); | |
}); | |
}, 1000); | |
}, 2000); | |
} | |
} | |
setTimeout(typeChar, 500); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin: 0; | |
background: #fff; | |
font-family: 'Pretendard', sans-serif; | |
height: 100vh; | |
overflow: hidden; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
.book-wrapper { | |
width: 100vw; | |
height: 100vh; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
overflow: hidden; | |
} | |
.book { | |
width: 900px; | |
height: 600px; | |
perspective: 2000px; | |
transform-style: preserve-3d; | |
opacity: 1; | |
transition: opacity 1s ease; | |
transform: scale(var(--book-scale, 1)); /* 추가 */ | |
transform-origin: center center; /* 또는 center center */ | |
} | |
.intro-screen { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100vw; | |
height: 100vh; | |
background: #111; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
z-index: 9999; | |
transition: opacity 1s ease; | |
overflow: hidden; | |
} | |
.intro-scaler { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
width: 100%; | |
max-width: 100vw; | |
height: 100vh; | |
text-align: center; | |
} | |
/* 화면이 작아질수록 축소 */ | |
@media (max-width: 1024px) { | |
.intro-wrapper { | |
transform: scale(0.85); | |
} | |
} | |
@media (max-width: 768px) { | |
.intro-wrapper { | |
transform: scale(0.7); | |
} | |
} | |
@media (max-width: 480px) { | |
.intro-wrapper { | |
transform: scale(0.5); | |
} | |
} | |
.cover-page { | |
width: 100%; | |
height: 100%; | |
background-color: #111; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
position: relative; | |
} | |
.cover-title-svg { | |
width: 50%; | |
max-width: 700px; | |
height: auto; | |
opacity: 1; | |
z-index: 2; | |
pointer-events: none; | |
} | |
.book-rotate { | |
transform: rotateY(180deg); | |
} | |
.page { | |
width: 100%; | |
height: 100%; | |
position: absolute; | |
transform-style: preserve-3d; | |
transform-origin: left; | |
transition: transform 1s ease; | |
} | |
.page.flipped { | |
transform: rotateY(-180deg); | |
z-index: 10; | |
} | |
.page-face { | |
width: 100%; | |
height: 100%; | |
position: absolute; | |
top: 0; | |
left: 0; | |
backface-visibility: hidden; | |
} | |
.page-face.front { | |
display: flex; | |
background: #111; | |
color: #fff; | |
position: relative; | |
overflow: hidden; | |
} | |
.page-face.back { | |
background: #111; | |
transform: rotateY(180deg); | |
} | |
.left-page, .right-page { | |
width: 50%; | |
padding: 40px; | |
box-sizing: border-box; | |
background: #111; | |
color: #fff; | |
position: relative; | |
} | |
.left-page { | |
display: flex; | |
flex-direction: column; | |
justify-content: flex-start; | |
align-items: flex-start; | |
} | |
.left-align { | |
align-self: flex-start; | |
margin-left: 0; | |
} | |
.left-page-num { | |
position: absolute; | |
top: 20px; | |
left: 100px; | |
font-size: 0.8rem; | |
color: #888; | |
} | |
.page-num { | |
position: absolute; | |
top: 20px; | |
left: 400px; | |
font-size: 0.8rem; | |
color: #888; | |
} | |
.svg-img { | |
display: block; | |
max-width: 80%; | |
margin: 0 auto; | |
} | |
/* 상단은 기존 위치 유지 */ | |
.svg-top { | |
margin-top: 80px; | |
} | |
.svg-page2-background { | |
position: absolute; | |
top: 30px; | |
right: -5px; | |
transform: scale(1) rotate(10deg); | |
pointer-events: none; | |
z-index: 0; | |
opacity:80%; | |
} | |
.svg-page1-background { | |
position: absolute; | |
top: 60px; | |
left: 50px; | |
width: 90%; | |
transform: scale(1.8); | |
opacity: 0.02; | |
z-index: 1; | |
pointer-events: none; | |
} | |
.svg-page1-background2 { | |
position: absolute; | |
top: 45px; | |
left: 80px; | |
width: 80%; | |
transform: scale(1.2); | |
opacity: 60%; | |
z-index: 1; | |
pointer-events: none; | |
} | |
.svg-page3-background { | |
position: absolute; | |
top: 270px; | |
left: -22%; | |
width: 140%; | |
transform: scale(1.3); | |
z-index: 1; /* 높여줍니다 */ | |
pointer-events: none; | |
} | |
.svg-page4-ground { | |
position: absolute; | |
bottom: 0; | |
left: 240px; | |
right: 0; | |
width: 60%; | |
height: auto; | |
z-index: 0; | |
pointer-events: none; | |
} | |
.svg-page4-cloud { | |
position: absolute; | |
width: 25%; | |
animation: floatCloud 12s ease-in-out infinite; | |
opacity: 90%; | |
pointer-events: none; | |
z-index: 1; | |
} | |
.cloud1 { | |
top: 30%; | |
left: 10%; | |
animation-delay: 0s; | |
width: 35%; | |
opacity:90%; | |
} | |
.cloud2 { | |
top: 60%; | |
right: 5%; | |
animation-delay: 0s; | |
opacity:30%; | |
width: 50%; | |
} | |
@keyframes floatCloud { | |
0%, 100% { | |
transform: translateY(0) translateX(0); | |
} | |
50% { | |
transform: translateY(-40px) translateX(30px); | |
} | |
} | |
.svg-page6-snake { | |
position: absolute; | |
bottom: 10px; | |
left: 100%; | |
width: 20%; | |
height: auto; | |
pointer-events: none; | |
z-index: 1; | |
animation: snakeSlide 10s linear infinite; | |
} | |
@keyframes snakeSlide { | |
0% { | |
transform: translateX(0); | |
} | |
100% { | |
transform: translateX(-300%); | |
} | |
} | |
.big-char { | |
font-size: 7rem; | |
font-weight: bold; | |
color: #fff; | |
align-self: flex-start; | |
margin-top: 25px; | |
margin: 0 auto; | |
} | |
.right-page { | |
overflow-y: auto; | |
font-size: 0.8rem; | |
line-height: 1.7; | |
position: relative; | |
padding-top: 25px; | |
text-align: justify; | |
} | |
.right-page p { | |
margin-bottom: 16px; | |
} | |
.highlight { | |
font-weight: bold; | |
font-size: 1.1rem; | |
color: #0ff; | |
} | |
.bold { | |
font-weight: bold; | |
font-size: 1.05rem; | |
margin-bottom: 0.5rem; | |
} | |
.poetic { | |
font-style: italic; | |
line-height: 1.8; | |
white-space: pre-line; | |
} | |
.full-page-center-text { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%, -50%); | |
font-size: 2.8rem; | |
font-weight: bold; | |
color: #fff; | |
text-align: center; | |
width: 100%; | |
z-index: 2; | |
pointer-events: none; | |
} | |
.type-area { | |
position: relative; | |
font-size: 2vw; /* 화면 너비에 비례한 글자 크기 */ | |
font-weight: bold; | |
color: white; | |
white-space: nowrap; | |
display: inline-block; | |
width: max-content; | |
text-align: center; | |
} | |
#text { | |
display: inline-block; | |
} | |
#turtle { | |
position: absolute; | |
top: 0.5px; | |
left: 0; | |
width: 3em; /* 텍스트 크기 비례 */ | |
height: auto; | |
transform: translateX(0); | |
transition: transform 0.1s linear; | |
pointer-events: none; | |
} | |
.orientation-warning { | |
display: none; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100vw; | |
height: 100vh; | |
background: #111; | |
color: white; | |
font-size: 1.8rem; | |
font-weight: bold; | |
z-index: 10000; | |
justify-content: center; | |
align-items: center; | |
text-align: center; | |
padding: 20px; | |
} | |
@media (min-width: 768px) { | |
.orientation-warning { | |
display: none !important; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment