Add 3D loose-leaf chronicle of human civilisation
A Three.js site presenting 20 world history milestones as double-sided loose-leaf pages, with three views: a leather binder with page-flip animation, a golden timeline, and a dotted globe with great-circle arcs. All textures (paper, leather, registration cards, and 18 hand-drawn sketches) are generated procedurally via Canvas 2D, so no external image assets are needed beyond the Earth map. Includes dev helper scripts for screenshots, ASCII previews, and headless verification.
This commit is contained in:
+141
@@ -0,0 +1,141 @@
|
||||
:root {
|
||||
--paper: #e6d8b6;
|
||||
--paper-dark: #cbb88d;
|
||||
--ink: #3a2d22;
|
||||
--ink-soft: #6b5740;
|
||||
--leather: #5a3d2b;
|
||||
--gold: #c9a227;
|
||||
--gold-soft: #e0c46a;
|
||||
--bg: #14100d;
|
||||
--red: #a03a2a;
|
||||
--blue: #2c4a6b;
|
||||
--green: #3f5c3a;
|
||||
--serif: "Noto Serif SC", "Songti SC", "STSong", "SimSun", Georgia, serif;
|
||||
--kai: "Kaiti SC", "STKaiti", "KaiTi", "Segoe Script", cursive;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
background: var(--bg);
|
||||
font-family: var(--serif);
|
||||
color: var(--paper);
|
||||
}
|
||||
|
||||
#app { position: fixed; inset: 0; }
|
||||
#scene { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
|
||||
|
||||
/* 气氛遮罩 */
|
||||
.vignette {
|
||||
position: absolute; inset: 0; pointer-events: none;
|
||||
background: radial-gradient(ellipse at 50% 42%, transparent 40%, rgba(8, 5, 3, 0.55) 100%);
|
||||
mix-blend-mode: multiply;
|
||||
}
|
||||
.grain {
|
||||
position: absolute; inset: 0; pointer-events: none; opacity: 0.06;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
|
||||
}
|
||||
#iris {
|
||||
position: absolute; inset: 0; pointer-events: none;
|
||||
background: #0c0906; opacity: 0; transition: opacity 0.45s ease;
|
||||
}
|
||||
|
||||
/* 顶部标题 */
|
||||
.hud { position: absolute; z-index: 5; }
|
||||
.top-left { top: 22px; left: 26px; }
|
||||
.title {
|
||||
font-size: clamp(20px, 2.4vw, 34px);
|
||||
letter-spacing: 0.12em; font-weight: 600; color: var(--gold-soft);
|
||||
text-shadow: 0 1px 12px rgba(0,0,0,0.7);
|
||||
}
|
||||
.subtitle {
|
||||
margin-top: 4px; font-size: 12px; letter-spacing: 0.18em;
|
||||
color: rgba(230,216,182,0.65); font-family: Georgia, serif;
|
||||
}
|
||||
|
||||
/* 视图切换 */
|
||||
.view-switch {
|
||||
top: 26px; right: 26px; display: flex; gap: 8px;
|
||||
}
|
||||
.view-btn {
|
||||
font-family: var(--serif); font-size: 14px; letter-spacing: 0.1em;
|
||||
padding: 8px 16px; color: var(--paper); cursor: pointer;
|
||||
background: rgba(20,14,10,0.55); border: 1px solid rgba(201,162,39,0.35);
|
||||
border-radius: 3px; backdrop-filter: blur(4px);
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
.view-btn:hover { border-color: var(--gold); color: #fff; }
|
||||
.view-btn.active {
|
||||
background: linear-gradient(180deg, rgba(201,162,39,0.85), rgba(150,115,20,0.85));
|
||||
color: #1c1308; border-color: var(--gold); font-weight: 600;
|
||||
}
|
||||
|
||||
/* 底部导航 */
|
||||
.bottom-bar {
|
||||
left: 50%; bottom: 22px; transform: translateX(-50%);
|
||||
display: flex; align-items: center; gap: 16px;
|
||||
padding: 10px 18px; border-radius: 4px;
|
||||
background: rgba(20,14,10,0.6); border: 1px solid rgba(201,162,39,0.25);
|
||||
backdrop-filter: blur(6px);
|
||||
}
|
||||
.nav-btn {
|
||||
font-family: var(--serif); font-size: 16px; line-height: 1;
|
||||
width: 38px; height: 38px; border-radius: 50%;
|
||||
color: var(--gold-soft); cursor: pointer;
|
||||
background: rgba(255,255,255,0.04); border: 1px solid rgba(201,162,39,0.4);
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.nav-btn:hover { background: rgba(201,162,39,0.25); color: #fff; transform: scale(1.06); }
|
||||
.nav-btn:active { transform: scale(0.96); }
|
||||
.flip-hint { width: auto; border-radius: 20px; padding: 0 18px; letter-spacing: 0.12em; font-size: 14px; }
|
||||
.page-indicator { display: flex; align-items: baseline; gap: 6px; min-width: 200px; justify-content: center; }
|
||||
#page-num { font-size: 24px; color: var(--gold-soft); font-family: Georgia, serif; }
|
||||
.sep { color: rgba(230,216,182,0.5); }
|
||||
#page-total { color: rgba(230,216,182,0.6); font-family: Georgia, serif; }
|
||||
.page-name { font-size: 14px; color: var(--paper); letter-spacing: 0.05em; margin-left: 10px; }
|
||||
|
||||
/* 登记卡详情 */
|
||||
.detail-card {
|
||||
right: 24px; bottom: 96px; width: min(320px, 82vw);
|
||||
padding: 18px 20px; border-radius: 4px;
|
||||
background: linear-gradient(180deg, rgba(232,216,182,0.96), rgba(214,196,156,0.96));
|
||||
color: var(--ink); box-shadow: 0 18px 50px rgba(0,0,0,0.55), inset 0 0 0 1px rgba(90,61,43,0.4);
|
||||
transform: translateY(0); transition: transform 0.35s ease, opacity 0.35s ease;
|
||||
}
|
||||
.detail-card.hidden { opacity: 0; pointer-events: none; transform: translateY(14px); }
|
||||
.detail-head { display: flex; justify-content: space-between; align-items: center; }
|
||||
.detail-no { font-family: Georgia, serif; font-size: 13px; letter-spacing: 0.14em; color: var(--ink-soft); }
|
||||
.detail-cat {
|
||||
font-size: 12px; padding: 2px 10px; border-radius: 2px;
|
||||
background: var(--leather); color: var(--gold-soft); letter-spacing: 0.2em;
|
||||
}
|
||||
.detail-name {
|
||||
margin: 8px 0 12px; font-size: 22px; letter-spacing: 0.06em; font-weight: 600;
|
||||
}
|
||||
.detail-fields { border-top: 1px solid rgba(90,61,43,0.3); padding-top: 8px; }
|
||||
.field { display: flex; gap: 12px; font-size: 13px; line-height: 1.9; }
|
||||
.field dt {
|
||||
flex: 0 0 34px; color: var(--ink-soft); letter-spacing: 0.1em;
|
||||
}
|
||||
.field dd { color: var(--ink); }
|
||||
.detail-desc {
|
||||
margin-top: 10px; font-size: 13.5px; line-height: 1.75; color: var(--ink);
|
||||
border-left: 3px solid var(--gold); padding-left: 10px;
|
||||
}
|
||||
.detail-sketch { margin-top: 12px; border-top: 1px dashed rgba(90,61,43,0.4); padding-top: 10px; }
|
||||
.detail-sketch canvas { width: 100%; height: auto; border-radius: 2px; opacity: 0.94; }
|
||||
|
||||
/* 提示 */
|
||||
.hint {
|
||||
left: 26px; bottom: 26px; font-size: 12px; letter-spacing: 0.06em;
|
||||
color: rgba(230,216,182,0.55);
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.detail-card { display: none; }
|
||||
.subtitle { display: none; }
|
||||
.page-name { display: none; }
|
||||
.hint { display: none; }
|
||||
}
|
||||
Reference in New Issue
Block a user