数字我 Digital Me:全量入库(大文件走 Git LFS)
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
nginx serve /uploads direct (audio speed) / patch-nginx (push) Failing after 1m34s
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,115 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>无字卷|若生于乱世,你会是谁?</title>
|
||||
<style>
|
||||
:root{--ink:#27261f;--red:#8b3c30;--paper:#e7d8b8;--gold:#d5ad6d}
|
||||
*{box-sizing:border-box}html,body{margin:0;width:100%;height:100%;overflow:hidden;background:#0a0e0e;color:var(--ink);font-family:"Noto Serif SC","Songti SC","STSong",serif}button{font:inherit}.app{position:relative;width:100%;height:100%;overflow:hidden;background:radial-gradient(circle at 50% 48%,#f1e4c9 0,#d6c19a 65%,#aa8d63 100%);isolation:isolate}.app:before{content:"";position:absolute;z-index:0;inset:-3%;background:url('assets/homepage-origin.png') center/cover no-repeat;opacity:.08;filter:grayscale(.55) blur(1px);transform:scale(1.04);transition:opacity .8s}.grain{position:absolute;z-index:90;inset:0;pointer-events:none;opacity:.13;mix-blend-mode:multiply;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence baseFrequency='.76' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.2'/%3E%3C/svg%3E")}
|
||||
.topbar{position:absolute;z-index:100;top:0;left:0;right:0;height:72px;padding:0 36px;display:flex;align-items:center;justify-content:space-between;color:#4d473b;transition:color .7s,opacity .5s}.brand{font-weight:700;letter-spacing:.34em}.brand small{font:10px Arial,sans-serif;letter-spacing:.18em;opacity:.55;margin-left:12px}.sound{width:39px;height:39px;border:1px solid rgba(61,54,43,.3);border-radius:50%;background:rgba(243,233,211,.18);color:inherit;cursor:pointer}
|
||||
.intro{position:absolute;z-index:10;inset:78px 5vw 34px;display:flex;flex-direction:column;align-items:center;text-align:center;transition:opacity .55s,transform .75s,filter .55s}.kicker{font:11px Arial,sans-serif;letter-spacing:.32em;color:var(--red);margin-top:1.5vh}.intro h1{font-size:clamp(44px,5.8vw,82px);font-weight:500;line-height:1.15;letter-spacing:.08em;margin:2vh 0 1.1vh}.intro h1 span{display:block}.intro p{margin:0;max-width:680px;font-size:15px;line-height:1.9;color:#645d50;letter-spacing:.035em}.scroll-zone{width:min(920px,87vw);margin:auto 0;position:relative;display:flex;flex-direction:column;align-items:center}.scroll-button{border:0;background:transparent;width:100%;padding:0;cursor:pointer;position:relative;filter:drop-shadow(0 22px 20px rgba(71,52,29,.2));transition:transform .5s,filter .5s}.scroll-button img{display:block;width:100%;height:auto}.scroll-button:after{content:"启卷";position:absolute;left:50%;top:58%;transform:translate(-50%,-50%);width:48px;height:48px;display:grid;place-items:center;color:#ead8bd;font-size:11px;letter-spacing:.1em;writing-mode:vertical-rl;opacity:.92}.scroll-button:hover{transform:translateY(-6px) scale(1.012);filter:drop-shadow(0 30px 25px rgba(71,52,29,.28))}.scroll-button:hover:before{content:"";position:absolute;left:50%;top:55%;width:54px;height:54px;border-radius:50%;transform:translate(-50%,-50%);box-shadow:0 0 0 12px rgba(143,62,49,.08),0 0 35px rgba(143,62,49,.2);animation:ring 1.5s infinite}.prompt{margin-top:-3.2%;font-size:12px;letter-spacing:.23em;color:#675e4d}.subprompt{font:10px Arial,sans-serif;letter-spacing:.08em;color:#8b806b;margin-top:8px}@keyframes ring{50%{box-shadow:0 0 0 19px rgba(143,62,49,0),0 0 45px rgba(143,62,49,.3)}}
|
||||
.app.is-opening{background:#080c0c}.app.is-opening:before{opacity:0}.app.is-opening .intro{opacity:0;transform:scale(.96);filter:blur(5px);pointer-events:none}.app.is-opening .topbar{color:#d9c8aa}.portal{position:absolute;z-index:30;inset:0;opacity:0;pointer-events:none;clip-path:inset(0 47% 0 47% round 44%);transform:scale(.76,.86);filter:blur(3px) brightness(.62);transform-origin:50% 53%;background:url('assets/homepage-open-scroll-cinematic.png') center/contain no-repeat;transition:clip-path 2.55s cubic-bezier(.5,.02,.14,1),opacity .25s,transform 3.15s cubic-bezier(.16,.75,.16,1),filter 2s}.app.portal-open .portal{opacity:1;clip-path:inset(0 0 0 0 round 0);transform:scale(1.035);filter:none;pointer-events:auto}
|
||||
.unfurl-roll{position:absolute;z-index:48;left:50%;top:52%;width:64px;height:min(58vh,590px);opacity:0;border-radius:35px;background:linear-gradient(90deg,#58391f 0,#b7894c 7%,#e2c388 22%,#f2dca7 46%,#c79a5b 72%,#6d4727 94%,#2a1a11);border:1px solid rgba(57,33,18,.8);box-shadow:0 18px 35px rgba(0,0,0,.45),0 0 26px rgba(226,155,67,.2);transform-origin:center}.unfurl-roll:before{content:"";position:absolute;inset:3px 7px;background:repeating-linear-gradient(90deg,rgba(73,43,23,.1) 0 1px,transparent 1px 5px);border-radius:30px;mix-blend-mode:multiply}.unfurl-roll i{position:absolute;left:50%;bottom:-11px;width:72px;height:29px;transform:translateX(-50%);border-radius:50%;background:repeating-radial-gradient(ellipse at center,#382115 0 4px,#c39659 5px 9px,#6b4328 10px 13px);border:2px solid #3d281a;box-shadow:0 5px 12px rgba(0,0,0,.45)}.app.is-opening .roll-left{animation:rollLeft 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRight 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}@keyframes rollLeft{0%{opacity:0;transform:translate(-108%,-50%) rotate(-1deg) scale(.92)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(-34vw - 50%),-50%) rotate(-8deg) scale(1.02)}}@keyframes rollRight{0%{opacity:0;transform:translate(8%,-50%) rotate(1deg) scale(.92)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(34vw - 50%),-50%) rotate(8deg) scale(1.02)}}
|
||||
.route-glow{position:absolute;z-index:3;left:29%;top:37%;width:53%;height:28%;overflow:visible;opacity:0;transform:rotate(-4deg);filter:drop-shadow(0 0 5px #ffc968) drop-shadow(0 0 13px rgba(240,147,36,.7));pointer-events:none}.route-glow path{fill:none;stroke:#ffd47d;stroke-width:2.2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:1120;stroke-dashoffset:1120}.route-glow circle{fill:#fff2b0;opacity:0}.app.portal-open .route-glow{animation:routeFade 3.25s .75s ease forwards}.app.portal-open .route-glow path{animation:traceRoute 2.25s .9s cubic-bezier(.38,.05,.18,1) forwards}.app.portal-open .route-glow circle{animation:nodeGlow .45s var(--delay) ease forwards}@keyframes traceRoute{to{stroke-dashoffset:0}}@keyframes nodeGlow{to{opacity:1}}@keyframes routeFade{0%{opacity:0}12%{opacity:.9}72%{opacity:.88}100%{opacity:0}}
|
||||
.origin-copy{position:absolute;z-index:5;left:19.5%;top:18%;width:min(475px,37vw);padding:18px 24px 20px;color:#211a13;text-shadow:0 1px 0 rgba(255,244,211,.78),0 0 12px rgba(245,225,181,.28);transform:translateY(13px);opacity:0;transition:opacity .8s .15s,transform .9s .15s}.origin-copy:before{content:"";position:absolute;z-index:-1;inset:-12px -34px -16px -24px;background:linear-gradient(90deg,rgba(231,211,171,.8) 0%,rgba(232,213,174,.58) 66%,rgba(232,213,174,0) 100%);filter:blur(7px);border-left:2px solid rgba(110,55,36,.35)}.app.story-visible .origin-copy{opacity:1;transform:none}.chapter{font:700 11px Arial,sans-serif;letter-spacing:.28em;color:#7e392c}.origin-copy h2{font-size:clamp(29px,3.2vw,50px);line-height:1.3;font-weight:700;letter-spacing:.045em;margin:12px 0 17px;max-width:9em;color:#241b13}.story-lines{font-size:clamp(14px,1.05vw,16px);font-weight:600;line-height:1.85;color:#3b2d20}.story-lines span{display:block;opacity:0;transform:translateY(7px);transition:.5s}.app.story-visible .story-lines span{opacity:1;transform:none}.story-lines span:nth-child(1){transition-delay:.6s}.story-lines span:nth-child(2){transition-delay:.9s}.story-lines span:nth-child(3){transition-delay:1.2s}.story-lines span:nth-child(4){transition-delay:1.55s;color:#7b261f;margin-top:5px;font-size:1.08em}.continue{position:relative;margin-top:20px;border:1px solid rgba(70,38,26,.72);background:rgba(228,199,145,.78);box-shadow:0 3px 12px rgba(60,34,20,.12);color:#3f2019;padding:12px 21px;font-weight:600;letter-spacing:.13em;opacity:0;transform:translateY(8px);transition:opacity .55s 1.8s,transform .55s 1.8s,background .25s,color .25s;cursor:pointer;overflow:hidden}.app.story-visible .continue{opacity:1;transform:none}.continue:before{content:"";position:absolute;inset:0;background:linear-gradient(100deg,transparent,rgba(255,245,207,.75),transparent);transform:translateX(-120%)}.continue:hover{background:#7d392e;color:#f5e8cf}.continue:hover:before{transition:transform .7s;transform:translateX(120%)}.chapter-mark{position:absolute;z-index:5;right:11%;bottom:10%;color:#d4b27b;font-size:11px;letter-spacing:.22em;opacity:0;transition:opacity .6s 1.3s}.app.story-visible .chapter-mark{opacity:.8}
|
||||
.next-module{position:absolute;z-index:4;inset:-6%;display:grid;place-items:center;background:linear-gradient(rgba(12,13,11,.43),rgba(7,8,7,.58)),url('assets/story-01-fire.png') center/cover no-repeat;opacity:0;transform:scale(.74);filter:blur(9px);transition:opacity 1.1s,transform 2.25s cubic-bezier(.16,.72,.18,1),filter 1.4s}.next-module:after{content:"";position:absolute;inset:0;background:radial-gradient(circle at center,transparent 30%,rgba(0,0,0,.58) 100%)}.next-copy{position:relative;z-index:2;text-align:center;color:#f0dfc3;text-shadow:0 3px 25px #000;opacity:0;transform:translateY(20px);transition:opacity .75s,transform .8s}.next-copy .chapter{color:#d9a767}.next-copy h2{font-weight:500;font-size:clamp(44px,7vw,94px);letter-spacing:.22em;margin:12px 0}.next-copy p{font-size:15px;letter-spacing:.13em;color:#d7c7ad}.app.revealing-next .next-module{opacity:1;transform:scale(1.06);filter:none}.app.leaving-origin .portal{opacity:0;transform:scale(1.28);filter:blur(11px) brightness(.58);transition:opacity 1.15s,transform 1.8s cubic-bezier(.2,.72,.2,1),filter 1.15s}.app.leaving-origin .origin-copy,.app.leaving-origin .chapter-mark{opacity:0!important;transition:opacity .3s!important}.app.next-entered .next-copy{opacity:1;transform:none}.app.next-entered .topbar{opacity:.72}
|
||||
@media(max-width:760px){.topbar{padding:0 18px}.brand small{display:none}.intro{inset:72px 18px 22px}.intro h1{font-size:42px;margin-top:2vh}.intro p{font-size:13px}.scroll-zone{width:98vw}.prompt{margin-top:-1%;font-size:11px}.portal{background-size:cover;background-position:56% center}.origin-copy{left:8%;top:17%;width:78vw;padding:15px 17px}.origin-copy:before{inset:-8px -22px -10px -13px}.origin-copy h2{font-size:30px}.story-lines{font-size:14px;line-height:1.7}.continue{margin-top:14px;padding:10px 14px}.chapter-mark{display:none}.next-copy p{font-size:12px;padding:0 24px}}@media(prefers-reduced-motion:reduce){*{animation-duration:.01ms!important;transition-duration:.01ms!important;transition-delay:0s!important}}
|
||||
@media(max-width:760px){.unfurl-roll{width:48px;height:48vh}.unfurl-roll i{width:55px;height:24px}.app.is-opening .roll-left{animation-name:rollLeftMobile}.app.is-opening .roll-right{animation-name:rollRightMobile}@keyframes rollLeftMobile{0%{opacity:0;transform:translate(-105%,-50%) scale(.9)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(-40vw - 50%),-50%) rotate(-5deg)}}@keyframes rollRightMobile{0%{opacity:0;transform:translate(5%,-50%) scale(.9)}8%{opacity:1}74%{opacity:1}100%{opacity:0;transform:translate(calc(40vw - 50%),-50%) rotate(5deg)}}.route-glow{left:12%;top:39%;width:78%;height:22%}}
|
||||
.unfurl-roll{pointer-events:none}
|
||||
.portal{clip-path:inset(0 47% 0 47% round 8px)}.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)}
|
||||
.unfurl-roll{width:285px;height:min(67vh,650px);border:0;border-radius:0;background:url('assets/unfurl-paper-roll-real.png') center/contain no-repeat;box-shadow:none;filter:drop-shadow(0 18px 18px rgba(0,0,0,.44))}.unfurl-roll:before,.unfurl-roll i{display:none}.app.is-opening .roll-left{animation:rollRealLeft 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRealRight 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards;filter:brightness(.9) drop-shadow(0 18px 18px rgba(0,0,0,.44))}@keyframes rollRealLeft{0%{opacity:0;transform:translate(-71%,-50%) rotate(-1deg) scale(.94)}8%{opacity:1}74%{opacity:.96}100%{opacity:0;transform:translate(calc(-34vw - 50%),-50%) rotate(-8deg) scale(.9)}}@keyframes rollRealRight{0%{opacity:0;transform:translate(-29%,-50%) rotate(1deg) scale(-.94,.94)}8%{opacity:1}74%{opacity:.94}100%{opacity:0;transform:translate(calc(34vw - 50%),-50%) rotate(8deg) scale(-.9,.9)}}
|
||||
@media(max-width:760px){.unfurl-roll{width:190px;height:53vh}.app.is-opening .roll-left{animation-name:rollRealLeftMobile}.app.is-opening .roll-right{animation-name:rollRealRightMobile}@keyframes rollRealLeftMobile{0%{opacity:0;transform:translate(-72%,-50%) scale(.9)}8%{opacity:1}74%{opacity:.95}100%{opacity:0;transform:translate(calc(-40vw - 50%),-50%) rotate(-5deg) scale(.86)}}@keyframes rollRealRightMobile{0%{opacity:0;transform:translate(-28%,-50%) scale(-.9,.9)}8%{opacity:1}74%{opacity:.92}100%{opacity:0;transform:translate(calc(40vw - 50%),-50%) rotate(5deg) scale(-.86,.86)}}}
|
||||
/* Horizontal paired rolls: unfold from the centre toward top and bottom. */
|
||||
.portal{clip-path:inset(47% 0 47% 0 round 8px)}.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)}
|
||||
.app.is-opening .roll-left{animation:rollRealTop 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}.app.is-opening .roll-right{animation:rollRealBottom 2.75s .18s cubic-bezier(.5,.02,.13,1) forwards}
|
||||
@keyframes rollRealTop{0%{opacity:0;transform:translate(-50%,-50%) translateY(-52px) rotate(90deg) scale(.94)}8%{opacity:1}74%{opacity:.96}100%{opacity:0;transform:translate(-50%,-50%) translateY(-31vh) rotate(84deg) scale(.9)}}
|
||||
@keyframes rollRealBottom{0%{opacity:0;transform:translate(-50%,-50%) translateY(52px) rotate(-90deg) scale(.94)}8%{opacity:1}74%{opacity:.94}100%{opacity:0;transform:translate(-50%,-50%) translateY(31vh) rotate(-84deg) scale(.9)}}
|
||||
@media(max-width:760px){.app.is-opening .roll-left{animation-name:rollRealTopMobile}.app.is-opening .roll-right{animation-name:rollRealBottomMobile}@keyframes rollRealTopMobile{0%{opacity:0;transform:translate(-50%,-50%) translateY(-38px) rotate(90deg) scale(.9)}8%{opacity:1}74%{opacity:.95}100%{opacity:0;transform:translate(-50%,-50%) translateY(-34vh) rotate(86deg) scale(.86)}}@keyframes rollRealBottomMobile{0%{opacity:0;transform:translate(-50%,-50%) translateY(38px) rotate(-90deg) scale(.9)}8%{opacity:1}74%{opacity:.92}100%{opacity:0;transform:translate(-50%,-50%) translateY(34vh) rotate(-86deg) scale(.86)}}}
|
||||
/* Simplified transition: no auxiliary scroll-roll animation. */
|
||||
.portal{clip-path:none!important;opacity:0;background-color:#080c0c!important;transform:scale(.9);filter:blur(8px) brightness(.62);transition:opacity 1s ease,transform 1.65s cubic-bezier(.18,.76,.18,1),filter 1.25s ease}.app.portal-open .portal{clip-path:none!important;opacity:1;transform:scale(1.02);filter:none}.app.leaving-origin .portal{opacity:0!important;transform:scale(.95)!important;filter:blur(10px) brightness(.45)!important;pointer-events:none!important;transition:opacity .62s ease,transform .72s ease,filter .62s ease!important}
|
||||
/* [版本 A 动效优化] 单一合成层完成旋转,不再逐帧计算大图模糊、亮度和双层浮动。 */
|
||||
.app.scroll-unfurling .scroll-button{pointer-events:none;animation:sealedScrollUnfurl 1100ms linear both;transition:opacity 620ms ease;transform-origin:50% 50%;filter:none;will-change:transform,opacity;backface-visibility:hidden;contain:paint}
|
||||
.app.scroll-unfurling .scroll-button img{animation:none;transform:translateZ(0);backface-visibility:hidden}
|
||||
.app.scroll-unfurling .scroll-zone:before{content:"";position:absolute;z-index:-1;left:50%;top:48%;width:42%;height:48%;border-radius:50%;background:radial-gradient(ellipse,rgba(255,239,195,.72),rgba(213,161,82,.24) 46%,transparent 73%);transform:translate3d(-50%,-50%,0) scale(.35);opacity:0;animation:unfurlHalo 1100ms cubic-bezier(.42,0,.2,1) both;will-change:transform,opacity;pointer-events:none}
|
||||
.app.scroll-unfurling .prompt,.app.scroll-unfurling .subprompt{animation:sealCopyOut .45s ease forwards}
|
||||
@keyframes sealedScrollUnfurl{0%{transform:translate3d(0,0,0) rotate(0deg) scale(.88);opacity:1;animation-timing-function:cubic-bezier(.42,0,.16,1)}84%{transform:translate3d(0,-4px,0) rotate(93deg) scale(.615);opacity:1;animation-timing-function:cubic-bezier(.2,.65,.35,1)}100%{transform:translate3d(0,0,0) rotate(90deg) scale(.62);opacity:1}}
|
||||
@keyframes unfurlHalo{0%{opacity:0;transform:translate(-50%,-50%) scale(.35)}18%{opacity:.34}72%{opacity:.72}100%{opacity:0;transform:translate(-50%,-50%) scale(2.5,.9)}}
|
||||
@keyframes sealCopyOut{to{opacity:0;transform:translateY(-10px)}}
|
||||
/* [修改 2] 竖直单卷完成后淡出,由两侧实体卷轴和中间画布无缝接替。 */
|
||||
.app.scroll-fade-out .scroll-button{animation:none;transform:translateY(0) rotate(90deg) scale(.62);opacity:0;filter:drop-shadow(0 34px 30px rgba(71,52,29,.1)) brightness(1.18) blur(4px)}
|
||||
/* [修改 3] 中间画布从竖直窄缝向左右展开;改用正视水墨素材,纸面上下边缘保持绝对水平。 */
|
||||
.app{--canvas-unfurl-duration:2400ms;--canvas-unfurl-ease:cubic-bezier(.5,.02,.14,1);--roll-left-travel:-49.4vw;--roll-right-travel:49.4vw}
|
||||
/* [结构修复] 画布只占卷轴纸身高度:顶部 12.5% 至底部 19.5%,木轴区域完全没有画面。 */
|
||||
.portal{inset:12.5% 0 19.5%;overflow:hidden;clip-path:inset(0 49.4% 0 49.4% round 10px)!important;opacity:0;background-color:transparent!important;background-image:url('assets/homepage-origin-canvas-v2.png')!important;background-position:center;background-size:100% 128%;background-repeat:no-repeat;border:0;box-shadow:0 16px 34px rgba(34,23,14,.24);transform:none;filter:blur(5px) brightness(.72);transition:clip-path var(--canvas-unfurl-duration) var(--canvas-unfurl-ease),opacity .32s ease,filter 1600ms ease!important}
|
||||
.app.portal-open .portal{clip-path:inset(0 0 0 0 round 0)!important;opacity:1;transform:none;filter:none;pointer-events:auto}
|
||||
.portal:before{content:"";position:absolute;z-index:2;top:7%;bottom:7%;left:50%;width:30px;opacity:0;transform:translateX(-50%) scaleY(.22);background:linear-gradient(90deg,transparent,rgba(255,220,137,.42),rgba(255,235,179,.58),rgba(255,220,137,.42),transparent);filter:blur(7px);pointer-events:none}.app.portal-open .portal:before{animation:canvasSeamGlow 2400ms cubic-bezier(.42,0,.18,1) both}
|
||||
@keyframes canvasSeamGlow{0%{opacity:0;transform:translateX(-50%) scaleY(.22)}10%{opacity:.52}38%{opacity:.28;transform:translateX(-50%) scaleY(.86)}56%,100%{opacity:0;transform:translateX(-50%) scaleY(1)}}
|
||||
/* [修改 4] 复用真实卷轴素材:两根卷轴从中央重合位置向左右移动,画布始终夹在中间。 */
|
||||
.canvas-roll{position:absolute;z-index:52;left:50%;top:50%;width:46vh;height:88vh;opacity:0;background:url('assets/unfurl-paper-roll-real.png') center/contain no-repeat;filter:drop-shadow(0 22px 24px rgba(0,0,0,.48)) drop-shadow(0 0 15px rgba(221,153,67,.2));transition:opacity .28s ease;pointer-events:none;will-change:transform,opacity}
|
||||
.app.portal-open .canvas-roll{opacity:1}.app.portal-open .canvas-roll-left{animation:canvasRollLeft var(--canvas-unfurl-duration) var(--canvas-unfurl-ease) both}.app.portal-open .canvas-roll-right{animation:canvasRollRight var(--canvas-unfurl-duration) var(--canvas-unfurl-ease) both}.app.leaving-origin .canvas-roll{opacity:0;transition-duration:.62s}
|
||||
/* [修复穿帮] 卷轴中心与 portal 裁切边界同步移动:画布在展开阶段始终被两根卷轴夹住。 */
|
||||
@keyframes canvasRollLeft{0%{transform:translate(-50%,-50%) scale(.96)}100%{transform:translate(calc(var(--roll-left-travel) - 50%),-50%) scale(1)}}
|
||||
@keyframes canvasRollRight{0%{transform:translate(-50%,-50%) scale(-.96,.96)}100%{transform:translate(calc(var(--roll-right-travel) - 50%),-50%) scale(-1,1)}}
|
||||
/* [版本 B] 缘起在首页红框区域展开:保留顶部标题,卷轴与纸幅缩放到同一舞台。 */
|
||||
.app.layout-inframe{--roll-left-travel:-47vw;--roll-right-travel:47vw}.app.layout-inframe.is-opening{background:radial-gradient(circle at 50% 48%,#f1e4c9 0,#d6c19a 65%,#aa8d63 100%)}.app.layout-inframe.is-opening:before{opacity:.08}.app.layout-inframe.is-opening .intro{opacity:1;transform:none;filter:none;pointer-events:none}.app.layout-inframe.is-opening .scroll-zone{opacity:0;transition:opacity .45s ease}.app.layout-inframe.is-opening .topbar{color:#4d473b}.app.layout-inframe .portal{inset:45% 3% 0;background-size:100% 128%}.app.layout-inframe .canvas-roll{top:74%;width:34.5vh;height:66vh}.app.layout-inframe .origin-copy{left:14%;top:7%;width:min(475px,42vw);padding-top:10px}.app.layout-inframe.leaving-origin .intro{opacity:0;transform:scale(.97);filter:blur(4px)}
|
||||
@media(max-width:760px){.canvas-roll{width:46vh;height:89vh}.app.portal-open .canvas-roll-left{animation-name:canvasRollLeftMobile}.app.portal-open .canvas-roll-right{animation-name:canvasRollRightMobile}.app.layout-inframe .portal{inset:43% 2% 0;background-position:58% center}.app.layout-inframe .canvas-roll{top:73%;width:35vh;height:68vh}.app.layout-inframe .origin-copy{left:8%;top:7%;width:82vw}@keyframes canvasRollLeftMobile{0%{transform:translate(-50%,-50%) scale(.94)}100%{transform:translate(calc(var(--roll-left-travel) - 50%),-50%) scale(1)}}@keyframes canvasRollRightMobile{0%{transform:translate(-50%,-50%) scale(-.94,.94)}100%{transform:translate(calc(var(--roll-right-travel) - 50%),-50%) scale(-1,1)}}}
|
||||
/* [修改 5] 减少动效模式:JS 直接打开缘起;CSS 同时确保复杂动画不会执行。 */
|
||||
@media(prefers-reduced-motion:reduce){.app.scroll-unfurling .scroll-button,.app.scroll-unfurling .scroll-button img,.app.scroll-unfurling .scroll-zone:before{animation:none!important}.app.scroll-fade-out .scroll-button{transition:none!important}}
|
||||
/* 低高度桌面屏:正文和继续按钮始终完整落在画卷纸幅内。 */
|
||||
@media(max-height:800px) and (min-width:761px){.origin-copy{top:8%;padding-top:10px}.origin-copy h2{font-size:clamp(27px,3vw,42px);margin:8px 0 11px}.story-lines{font-size:14px;line-height:1.58}.continue{margin-top:10px;padding:9px 17px}.chapter-mark{bottom:6%}}
|
||||
/* 手机端:两侧卷轴缩进屏幕边缘,正文收进中央安全区,避免被木轴遮挡。 */
|
||||
@media(max-width:760px){.app{--roll-left-travel:-50vw;--roll-right-travel:50vw}.canvas-roll,.app.layout-inframe .canvas-roll{top:50%;width:18vh;height:72vh}.origin-copy,.app.layout-inframe .origin-copy{left:19%;top:6%;width:62vw;padding:7px 5px}.origin-copy:before{inset:-5px -8px -7px -6px}.origin-copy h2{max-width:none;font-size:clamp(22px,6.5vw,27px);line-height:1.25;margin:7px 0 10px}.story-lines{font-size:11.5px;line-height:1.5}.continue{margin-top:10px;padding:8px 10px;font-size:11px;letter-spacing:.06em;white-space:nowrap}}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="app" id="app">
|
||||
<section class="next-module" aria-label="铸身模块"><div class="next-copy"><div class="chapter">第二章 · 铸身</div><h2>铸身</h2><p>不必描述自己。走进故事,让每一次选择替你回答。</p></div></section>
|
||||
<div class="grain"></div>
|
||||
<header class="topbar"><div class="brand">无字卷 <small>THREE KINGDOMS · 208</small></div><button class="sound" aria-label="切换声音">♪</button></header>
|
||||
<section class="intro" id="intro">
|
||||
<div class="kicker">一卷只属于你的无字史书</div><h1><span>若生于乱世</span><span>你会是谁?</span></h1><p>无字卷不问你想成为谁,只把你放进那个时代,看你会走向哪里。<br>不是观看历史,而是让自己的选择,成为历史里的一笔。</p>
|
||||
<div class="scroll-zone"><button class="scroll-button" id="openScroll" aria-label="展开无字卷"><img src="assets/homepage-closed-scroll-alpha.png" alt="封印中的无字卷"></button><div class="prompt">轻触封印,寻找历史里的你</div><div class="subprompt">建议开启声音 · 戴上耳机</div></div>
|
||||
</section>
|
||||
<!-- [修改 6] 左右实体卷轴必须位于 portal 外层,避免被中间画布的 clip-path 裁切。 -->
|
||||
<div class="canvas-roll canvas-roll-left" aria-hidden="true"></div><div class="canvas-roll canvas-roll-right" aria-hidden="true"></div>
|
||||
<section class="portal" id="portal" aria-live="polite">
|
||||
<article class="origin-copy"><div class="chapter">缘起 · 建安十三年</div><h2>史书里,少了一个没有名字的人。</h2><div class="story-lines"><span>赤壁之前,史官在旧卷中发现了一段陌生的记载。</span><span>那人的一个选择,改变了许多人的命运。</span><span>可他的姓名、出身与面容,都被墨色抹去。</span><span>而那段人生,与你惊人地相似。</span></div><button class="continue" id="continueBtn">以我之名,继续写下去</button></article><div class="chapter-mark">第一章 · 缘起</div>
|
||||
</section>
|
||||
</main>
|
||||
<script>
|
||||
const app=document.getElementById('app'),openButton=document.getElementById('openScroll'),continueButton=document.getElementById('continueBtn');let opened=false,transitioning=false;
|
||||
/* [双版本] layout=fullscreen 为全画面缘起;layout=inframe 为红框区域内缘起。 */
|
||||
const layout=new URLSearchParams(location.search).get('layout');app.classList.add(layout==='inframe'?'layout-inframe':'layout-fullscreen');
|
||||
/* [修改 7] 严格时间轴:封印卷轴平滑转为竖直 1100ms → 左右卷轴携画布展开 2400ms → 缘起。 */
|
||||
openButton.addEventListener('click',()=>{
|
||||
if(opened)return;
|
||||
opened=true;
|
||||
openButton.disabled=true;
|
||||
const reduceMotion=window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
if(reduceMotion){
|
||||
app.classList.add('is-opening','portal-open','story-visible');
|
||||
return;
|
||||
}
|
||||
app.classList.add('scroll-unfurling');
|
||||
setTimeout(()=>app.classList.add('scroll-fade-out','is-opening','portal-open'),1100);
|
||||
setTimeout(()=>app.classList.add('story-visible'),3650);
|
||||
});
|
||||
continueButton.addEventListener('click',()=>{
|
||||
if(transitioning)return;
|
||||
transitioning=true;
|
||||
continueButton.disabled=true;
|
||||
app.classList.add('leaving-origin');
|
||||
setTimeout(()=>{
|
||||
try {
|
||||
if(typeof window.parent.__wuzijuanContinue==='function') window.parent.__wuzijuanContinue();
|
||||
else window.parent.postMessage({type:'wuzijuan:continue'},location.origin);
|
||||
} catch {
|
||||
window.parent.postMessage({type:'wuzijuan:continue'},location.origin);
|
||||
}
|
||||
},720);
|
||||
});
|
||||
document.querySelector('.sound').addEventListener('click',e=>{e.currentTarget.textContent=e.currentTarget.textContent==='♪'?'×':'♪'});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user