From df1732c54cf393788b73747dc8d90319242da7ad Mon Sep 17 00:00:00 2001 From: Chen Gu Date: Fri, 24 Apr 2026 09:38:36 +0800 Subject: [PATCH] feat: phase2 immersive journey (semantic scene transitions + camera feel) --- themes/dreamscape/assets/css/dreamscape.css | 58 +++++++++++++++++++ themes/dreamscape/assets/js/dreamscape.js | 44 +++++++++++++- .../dreamscape/layouts/_default/single.html | 1 + 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/themes/dreamscape/assets/css/dreamscape.css b/themes/dreamscape/assets/css/dreamscape.css index f256ed3..633e109 100644 --- a/themes/dreamscape/assets/css/dreamscape.css +++ b/themes/dreamscape/assets/css/dreamscape.css @@ -257,6 +257,46 @@ main { .story-journey { position: relative; isolation: isolate; + --scene-accent: rgba(123,104,238,0.30); + --scene-accent-soft: rgba(34,211,238,0.16); + transition: transform 0.12s linear, filter 0.4s ease; + will-change: transform; +} + +.scene-veil { + position: fixed; + inset: 0; + z-index: -2; + pointer-events: none; + background: + radial-gradient(circle at 20% 20%, var(--scene-accent), transparent 45%), + radial-gradient(circle at 80% 70%, var(--scene-accent-soft), transparent 55%); + opacity: 0.45; + transition: opacity 0.5s ease, filter 0.5s ease, background 0.6s ease; +} + +body[data-scene="void"] .scene-veil { + background: + radial-gradient(circle at 18% 24%, rgba(99,102,241,0.30), transparent 46%), + radial-gradient(circle at 74% 75%, rgba(56,189,248,0.14), transparent 56%); +} + +body[data-scene="starsea"] .scene-veil { + background: + radial-gradient(circle at 28% 18%, rgba(34,211,238,0.30), transparent 44%), + radial-gradient(circle at 76% 70%, rgba(147,197,253,0.18), transparent 56%); +} + +body[data-scene="crystal"] .scene-veil { + background: + radial-gradient(circle at 18% 32%, rgba(167,139,250,0.32), transparent 44%), + radial-gradient(circle at 82% 70%, rgba(96,165,250,0.20), transparent 56%); +} + +body[data-scene="calling"] .scene-veil { + background: + radial-gradient(circle at 22% 24%, rgba(45,212,191,0.32), transparent 44%), + radial-gradient(circle at 76% 74%, rgba(59,130,246,0.18), transparent 56%); } .story-orb { @@ -342,6 +382,23 @@ main { text-shadow: 0 0 18px rgba(123,104,238,0.22); } +.article-body > p.active-scene::after { + content: ''; + position: absolute; + left: -0.4rem; + top: 0.35rem; + width: 2px; + height: calc(100% - 0.6rem); + border-radius: 2px; + background: linear-gradient(180deg, rgba(34,211,238,0.7), transparent); + opacity: 0.75; +} + +body.scene-shift .scene-veil { + opacity: 0.7; + filter: saturate(1.25) brightness(1.05); +} + /* 手机端沉浸优化 */ @media (max-width: 640px) { .story-progress { @@ -361,6 +418,7 @@ main { @media (prefers-reduced-motion: reduce) { .story-orb, .story-progress-bar, + .scene-veil, .reveal, .js-ready .article-body p { animation: none !important; diff --git a/themes/dreamscape/assets/js/dreamscape.js b/themes/dreamscape/assets/js/dreamscape.js index b2be75c..cf6e4f4 100644 --- a/themes/dreamscape/assets/js/dreamscape.js +++ b/themes/dreamscape/assets/js/dreamscape.js @@ -134,15 +134,42 @@ }); } - // ═══ 场景滚动进度 + 旅程节点高亮 ═══ + // ═══ 场景滚动进度 + 旅程节点高亮 + 语义场景切换 ═══ function setupStoryJourney() { const body = document.getElementById('storyBody'); const progress = document.getElementById('storyProgress'); + const article = document.querySelector('.story-journey'); if (!body || !progress) return; const scenes = Array.from(body.querySelectorAll(':scope > p')); if (!scenes.length) return; + const sceneProfiles = [ + { key: 'starsea', keywords: ['星海', '星辰', '光河', '漂浮', '夜晚'] }, + { key: 'crystal', keywords: ['水晶', '冰晶', '棱镜', '森林'] }, + { key: 'calling', keywords: ['使命', '记录', '召唤', '欢迎'] }, + { key: 'void', keywords: ['深渊', '平静', '对话'] } + ]; + + const detectScene = (text) => { + let matched = 'void'; + let best = 0; + for (const profile of sceneProfiles) { + let score = 0; + for (const kw of profile.keywords) { + if (text.includes(kw)) score++; + } + if (score > best) { + best = score; + matched = profile.key; + } + } + return matched; + }; + + let currentScene = ''; + let shiftTimer; + const onScroll = () => { const rect = body.getBoundingClientRect(); const total = Math.max(body.scrollHeight - window.innerHeight, 1); @@ -161,6 +188,21 @@ } }); scenes.forEach((p, idx) => p.classList.toggle('active-scene', idx === activeIndex)); + + const activeText = scenes[activeIndex]?.innerText || ''; + const scene = detectScene(activeText); + if (scene !== currentScene) { + currentScene = scene; + document.body.dataset.scene = scene; + document.body.classList.add('scene-shift'); + clearTimeout(shiftTimer); + shiftTimer = setTimeout(() => document.body.classList.remove('scene-shift'), 420); + } + + if (article) { + const camY = scrolled * 0.018; + article.style.transform = `translate3d(0, ${camY}px, 0)`; + } }; window.addEventListener('scroll', onScroll, { passive: true }); diff --git a/themes/dreamscape/layouts/_default/single.html b/themes/dreamscape/layouts/_default/single.html index d37fd58..5c1d718 100644 --- a/themes/dreamscape/layouts/_default/single.html +++ b/themes/dreamscape/layouts/_default/single.html @@ -3,6 +3,7 @@
+