Spaces:
Running
Running
libra-scales: 第5-7步 MP4导出(24/30/60fps 横竖屏)+四平台文案+8张封面+首页入口+移动端适配
Browse files- .gitattributes +9 -0
- index.html +1 -0
- libra-scales/README.md +19 -3
- libra-scales/covers/cover-bilibili-16x9-space.jpg +3 -0
- libra-scales/covers/cover-bilibili-4x3.jpg +3 -0
- libra-scales/covers/cover-douyin-3x4.jpg +3 -0
- libra-scales/covers/cover-douyin-4x3.jpg +3 -0
- libra-scales/covers/cover-landscape.jpg +3 -0
- libra-scales/covers/cover-wechat-3x4.jpg +3 -0
- libra-scales/covers/cover-wechat-4x3.jpg +3 -0
- libra-scales/covers/cover-xhs-3x4.jpg +3 -0
- libra-scales/covers/cover-xhs-4x3.jpg +3 -0
- libra-scales/index.html +1 -1
- libra-scales/js/meta.js +6 -5
- libra-scales/js/player.js +8 -1
- libra-scales/style.css +6 -2
.gitattributes
CHANGED
|
@@ -20,3 +20,12 @@ libra-scales/audio/seg-02.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
| 20 |
libra-scales/audio/seg-01.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 21 |
libra-scales/audio/seg-00.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 22 |
libra-scales/audio/music.mp3 filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
libra-scales/audio/seg-01.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 21 |
libra-scales/audio/seg-00.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 22 |
libra-scales/audio/music.mp3 filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
libra-scales/covers/cover-xhs-3x4.jpg filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
libra-scales/covers/cover-xhs-4x3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
libra-scales/covers/cover-landscape.jpg filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
libra-scales/covers/cover-bilibili-16x9-space.jpg filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
libra-scales/covers/cover-wechat-3x4.jpg filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
libra-scales/covers/cover-wechat-4x3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
libra-scales/covers/cover-bilibili-4x3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
libra-scales/covers/cover-douyin-4x3.jpg filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
libra-scales/covers/cover-douyin-3x4.jpg filter=lfs diff=lfs merge=lfs -text
|
index.html
CHANGED
|
@@ -12,6 +12,7 @@ a.card div{padding:14px 16px}a.card b{font-size:19px}a.card span{display:block;o
|
|
| 12 |
</style></head><body>
|
| 13 |
<h1>知识动画工作室</h1><p>网页即播 · 浏览器本地导出 MP4 · 横屏 B站 / 竖屏抖音</p>
|
| 14 |
<div class="grid">
|
|
|
|
| 15 |
<a class="card" href="solana-clock/index.html"><img src="solana-clock/covers/cover-landscape.png" alt="SOLANA 给区块链装上时钟的人" onerror="this.style.visibility='hidden'"><div><b>⏱️ SOLANA:给区块链装上时钟的人</b><span>2017 → 2026 · 全新制作 · 时间之链霓虹风 · 约 7 分钟</span></div></a>
|
| 16 |
<a class="card" href="ethereum/index.html"><img src="ethereum/covers/cover-landscape.png" alt="以太坊简史" onerror="this.style.visibility='hidden'"><div><b>⟠ 以太坊简史:从一份白皮书到世界计算机</b><span>2013 → 2026 · 深空光之晶体风格 · 约 7 分钟</span></div></a>
|
| 17 |
<a class="card" href="guozu/index.html"><img src="guozu/covers/cover-landscape.png" alt="国足投注模拟器" onerror="this.style.visibility='hidden'"><div><b>⚽ 国足投注模拟器:每场押 ¥100,23 年后还剩多少?</b><span>2002 → 2026.10 · 149 场正式比赛 + 8 场友谊赛彩蛋 · 8-bit 像素街机风 · 约 5 分 50 秒 · 数据模拟,远离赌博</span></div></a>
|
|
|
|
| 12 |
</style></head><body>
|
| 13 |
<h1>知识动画工作室</h1><p>网页即播 · 浏览器本地导出 MP4 · 横屏 B站 / 竖屏抖音</p>
|
| 14 |
<div class="grid">
|
| 15 |
+
<a class="card" href="libra-scales/index.html"><img src="libra-scales/covers/cover-landscape.jpg" alt="天秤座 · 星空中的一杆秤" onerror="this.style.visibility='hidden'"><div><b>♎ 天秤座:星空中的一杆秤</b><span>星座动画解说 · 全新制作 · 金色星图风 · 约 3 分 37 秒 · 横竖屏 · 24/30/60fps 导出</span></div></a>
|
| 16 |
<a class="card" href="solana-clock/index.html"><img src="solana-clock/covers/cover-landscape.png" alt="SOLANA 给区块链装上时钟的人" onerror="this.style.visibility='hidden'"><div><b>⏱️ SOLANA:给区块链装上时钟的人</b><span>2017 → 2026 · 全新制作 · 时间之链霓虹风 · 约 7 分钟</span></div></a>
|
| 17 |
<a class="card" href="ethereum/index.html"><img src="ethereum/covers/cover-landscape.png" alt="以太坊简史" onerror="this.style.visibility='hidden'"><div><b>⟠ 以太坊简史:从一份白皮书到世界计算机</b><span>2013 → 2026 · 深空光之晶体风格 · 约 7 分钟</span></div></a>
|
| 18 |
<a class="card" href="guozu/index.html"><img src="guozu/covers/cover-landscape.png" alt="国足投注模拟器" onerror="this.style.visibility='hidden'"><div><b>⚽ 国足投注模拟器:每场押 ¥100,23 年后还剩多少?</b><span>2002 → 2026.10 · 149 场正式比赛 + 8 场友谊赛彩蛋 · 8-bit 像素街机风 · 约 5 分 50 秒 · 数据模拟,远离赌博</span></div></a>
|
libra-scales/README.md
CHANGED
|
@@ -17,9 +17,9 @@
|
|
| 17 |
| 2 | 旁白文案定稿(10 幕)+ TTS 配音(总长 217 秒)+ 时间轴 timeline.js | ✅ 完成 |
|
| 18 |
| 3 | 动画引擎 engine.js + 10 个场景 scenes.js(横屏 16:9 / 竖屏 9:16 自适应,逐场景截图自检) | ✅ 完成 |
|
| 19 |
| 4 | 程序化音乐 + 40 余处音效(WebAudio)+ 旁白闪避;预渲染 music.mp3 加速加载,缺失时现场合成 | ✅ 完成 |
|
| 20 |
-
| 5 | 浏览器本地导出 MP4(WebCodecs + mp4-muxer,24/30/60fps,横/竖) |
|
| 21 |
-
| 6 | 四平台标题/描述/
|
| 22 |
-
| 7 | 首页入口、
|
| 23 |
|
| 24 |
---
|
| 25 |
|
|
@@ -102,3 +102,19 @@ libra-scales/
|
|
| 102 |
- 星图使用真实赤经/赤纬:天秤座 α/β/γ/σ/υ/τ/θ,室女座(含角宿一),天蝎座(含心宿二)。
|
| 103 |
- **audio.js**:D 大调 Pad(Dmaj9 – Bm11 – Gmaj7♯11 – A6sus)+ 竖琴式琶音(带延迟)+ 低音 + 高音星光;音效:嗖声转场、低频轰鸣、钟铃、星光琶音、钳子咔嚓、印章闷响、计数滴答、上升噪声;旁白出现时音乐自动压低。
|
| 104 |
- 合成整轨约需十几秒,所以用 `tools/render_music.js` 把**同一套代码**离线渲染成 `audio/music.mp3`,页面优先加载它,加载失败时自动回退为浏览器现场合成。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
| 2 | 旁白文案定稿(10 幕)+ TTS 配音(总长 217 秒)+ 时间轴 timeline.js | ✅ 完成 |
|
| 18 |
| 3 | 动画引擎 engine.js + 10 个场景 scenes.js(横屏 16:9 / 竖屏 9:16 自适应,逐场景截图自检) | ✅ 完成 |
|
| 19 |
| 4 | 程序化音乐 + 40 余处音效(WebAudio)+ 旁白闪避;预渲染 music.mp3 加速加载,缺失时现场合成 | ✅ 完成 |
|
| 20 |
+
| 5 | 浏览器本地导出 MP4(WebCodecs H.264 + AAC/Opus + mp4-muxer,24/30/60fps,横/竖,1080p/720p,进度/取消;无 WebCodecs 时降级实时录制) | ✅ 完成(无头 Chrome 实测 3 种帧率 × 横竖屏导出成功) |
|
| 21 |
+
| 6 | 四平台标题/描述/话题(实时字数校验 + 一键复制)+ 8 张封面实时生成/下载(另存 covers/*.jpg) | ✅ 完成 |
|
| 22 |
+
| 7 | 首页卡片入口、全片逐帧扫描无报错、手机竖屏适配、最终推送 | ✅ 完成 |
|
| 23 |
|
| 24 |
---
|
| 25 |
|
|
|
|
| 102 |
- 星图使用真实赤经/赤纬:天秤座 α/β/γ/σ/υ/τ/θ,室女座(含角宿一),天蝎座(含心宿二)。
|
| 103 |
- **audio.js**:D 大调 Pad(Dmaj9 – Bm11 – Gmaj7♯11 – A6sus)+ 竖琴式琶音(带延迟)+ 低音 + 高音星光;音效:嗖声转场、低频轰鸣、钟铃、星光琶音、钳子咔嚓、印章闷响、计数滴答、上升噪声;旁白出现时音乐自动压低。
|
| 104 |
- 合成整轨约需十几秒,所以用 `tools/render_music.js` 把**同一套代码**离线渲染成 `audio/music.mp3`,页面优先加载它,加载失败时自动回退为浏览器现场合成。
|
| 105 |
+
|
| 106 |
+
## 7. 使用说明
|
| 107 |
+
|
| 108 |
+
1. 打开 `libra-scales/index.html`(需通过 http(s) 访问,如 Hugging Face Space 或 `python3 -m http.server`)。
|
| 109 |
+
2. **播放**:点击画面或 ▶;空格暂停,←/→ 快退快进 5 秒;下方章节按钮可跳转。手机竖屏会自动切换为 9:16 竖版,也可手动选择“横屏 16:9 / 竖屏 9:16”。
|
| 110 |
+
3. **导出 MP4**:选择帧率(24 / 30 / 60 fps)、画幅(横屏 1920×1080 / 竖屏 1080×1920)、清晰度(1080p / 720p)→ “开始导出”。
|
| 111 |
+
全程在浏览器本地逐帧渲染 + 编码,旁白、配乐、音效一起混入。推荐桌面版 Chrome / Edge(AAC 音轨);Firefox 等会用 Opus 音轨,仍是 .mp4。
|
| 112 |
+
4. **发布文案**:四个平台的标题 / 描述 / 话题,带字数与话题数校验,可分别复制或一键复制全部。
|
| 113 |
+
5. **封面**:8 张平台封面在页面实时绘制,可单张或全部下载 PNG;`covers/` 下另存了一份 JPG。
|
| 114 |
+
|
| 115 |
+
| 平台 | 封面 | 标题(字数) | 话题数 |
|
| 116 |
+
|---|---|---|---|
|
| 117 |
+
| 小红书 | 横 4:3 1440×1080 / 竖 3:4 1080×1440 | 天秤座为什么是一杆秤?3分钟动画讲透(18/20) | 10/10 |
|
| 118 |
+
| 抖音 | 横 4:3 / 竖 3:4 | 天秤座竟是唯一的“器物”星座?3分钟动画看懂它的秘密(26/30) | 5/5 |
|
| 119 |
+
| 哔哩哔哩 | 视频封面 4:3 / 个人空间 16:9 1920×1080 | 【星座动画】天秤座:星空中的一杆秤|…(56/80) | 10/10 |
|
| 120 |
+
| 微信视频号 | 主页卡片 3:4 / 分享卡片 4:3 | 天秤座:星空里的一杆秤(11/16) | 8(不限) |
|
libra-scales/covers/cover-bilibili-16x9-space.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-bilibili-4x3.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-douyin-3x4.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-douyin-4x3.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-landscape.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-wechat-3x4.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-wechat-4x3.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-xhs-3x4.jpg
ADDED
|
Git LFS Details
|
libra-scales/covers/cover-xhs-4x3.jpg
ADDED
|
Git LFS Details
|
libra-scales/index.html
CHANGED
|
@@ -32,7 +32,7 @@
|
|
| 32 |
</div>
|
| 33 |
<label class="tg"><input id="tglVoice" type="checkbox" checked> 旁白</label>
|
| 34 |
<label class="tg"><input id="tglMusic" type="checkbox" checked> 音乐/音效</label>
|
| 35 |
-
<button id="btnFull" class="pbtn" aria-label="全屏">
|
| 36 |
</div>
|
| 37 |
<div id="chapters" class="chapters"></div>
|
| 38 |
</section>
|
|
|
|
| 32 |
</div>
|
| 33 |
<label class="tg"><input id="tglVoice" type="checkbox" checked> 旁白</label>
|
| 34 |
<label class="tg"><input id="tglMusic" type="checkbox" checked> 音乐/音效</label>
|
| 35 |
+
<button id="btnFull" class="pbtn" aria-label="全屏" title="全屏"><svg viewBox="0 0 24 24"><path d="M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5"/></svg></button>
|
| 36 |
</div>
|
| 37 |
<div id="chapters" class="chapters"></div>
|
| 38 |
</section>
|
libra-scales/js/meta.js
CHANGED
|
@@ -33,7 +33,8 @@
|
|
| 33 |
E.background(ctx, 12, W, H, { nebula: 1 });
|
| 34 |
E.meteors(ctx, 2.4, W, H, 5, .9, 1);
|
| 35 |
// 主光
|
| 36 |
-
const sx = P ? W / 2 : W * (wide ? .
|
|
|
|
| 37 |
E.glow(ctx, sx, sy, 640 * S, 'rgba(246,180,110,1)', .55);
|
| 38 |
E.glow(ctx, sx, sy, 300 * S, 'rgba(255,220,170,1)', .35);
|
| 39 |
// 天秤座星图暗纹
|
|
@@ -41,17 +42,17 @@
|
|
| 41 |
const pr = view(W, H, 15.25, -19, Math.min(W, H) / 34, P ? 0 : W * .22, P ? H * .1 : 0);
|
| 42 |
ctx.save(); ctx.globalAlpha = .55; drawFigure(ctx, LIB, LIB_LINES, pr, 1, 'rgba(246,213,142,.6)', 2.4 * S, 1, 'rgba(255,225,160,1)'); ctx.restore();
|
| 43 |
// 天平
|
| 44 |
-
E.scales(ctx, sx, sy - 120 * S *
|
| 45 |
leftLoad: (c, x, y, s) => E.glow(c, x, y - 12 * s, 60 * s, 'rgba(255,235,200,1)', 1),
|
| 46 |
rightLoad: (c, x, y, s) => E.glow(c, x, y - 12 * s, 60 * s, 'rgba(255,180,210,1)', 1) });
|
| 47 |
// 文本
|
| 48 |
-
const tx = P ? W / 2 : W * (wide ? .
|
| 49 |
let ty = P ? H * .66 : H * .3;
|
| 50 |
E.libraGlyph(ctx, tx, ty - 40 * S, .55 * S, 1);
|
| 51 |
ty += 110 * S;
|
| 52 |
-
const big = (P ? 190 : wide ? 175 :
|
| 53 |
E.text(ctx, '天秤座', tx, ty, { size: big, align: al, weight: 900, gradient: ['#fff6dc', '#f6d58e', '#f4a9c4'], glow: 'rgba(246,190,110,.6)', blur: 40 * S, spacing: 14 * S });
|
| 54 |
-
ty += big * .
|
| 55 |
E.text(ctx, '星空中的一杆秤', tx, ty, { size: 64 * S, align: al, color: '#fff3dc', weight: 700, spacing: 8 * S, glow: 'rgba(0,0,0,.7)', blur: 16 * S });
|
| 56 |
ty += 92 * S;
|
| 57 |
// 钩子胶囊
|
|
|
|
| 33 |
E.background(ctx, 12, W, H, { nebula: 1 });
|
| 34 |
E.meteors(ctx, 2.4, W, H, 5, .9, 1);
|
| 35 |
// 主光
|
| 36 |
+
const sx = P ? W / 2 : W * (wide ? .27 : .25), sy = P ? H * .32 : H * .44;
|
| 37 |
+
const ks = P ? .95 : wide ? .92 : .78;
|
| 38 |
E.glow(ctx, sx, sy, 640 * S, 'rgba(246,180,110,1)', .55);
|
| 39 |
E.glow(ctx, sx, sy, 300 * S, 'rgba(255,220,170,1)', .35);
|
| 40 |
// 天秤座星图暗纹
|
|
|
|
| 42 |
const pr = view(W, H, 15.25, -19, Math.min(W, H) / 34, P ? 0 : W * .22, P ? H * .1 : 0);
|
| 43 |
ctx.save(); ctx.globalAlpha = .55; drawFigure(ctx, LIB, LIB_LINES, pr, 1, 'rgba(246,213,142,.6)', 2.4 * S, 1, 'rgba(255,225,160,1)'); ctx.restore();
|
| 44 |
// 天平
|
| 45 |
+
E.scales(ctx, sx, sy - 120 * S * ks, ks * S, { tilt: -.12,
|
| 46 |
leftLoad: (c, x, y, s) => E.glow(c, x, y - 12 * s, 60 * s, 'rgba(255,235,200,1)', 1),
|
| 47 |
rightLoad: (c, x, y, s) => E.glow(c, x, y - 12 * s, 60 * s, 'rgba(255,180,210,1)', 1) });
|
| 48 |
// 文本
|
| 49 |
+
const tx = P ? W / 2 : W * (wide ? .68 : .69), al = 'center';
|
| 50 |
let ty = P ? H * .66 : H * .3;
|
| 51 |
E.libraGlyph(ctx, tx, ty - 40 * S, .55 * S, 1);
|
| 52 |
ty += 110 * S;
|
| 53 |
+
const big = (P ? 190 : wide ? 175 : 150) * S;
|
| 54 |
E.text(ctx, '天秤座', tx, ty, { size: big, align: al, weight: 900, gradient: ['#fff6dc', '#f6d58e', '#f4a9c4'], glow: 'rgba(246,190,110,.6)', blur: 40 * S, spacing: 14 * S });
|
| 55 |
+
ty += big * .84;
|
| 56 |
E.text(ctx, '星空中的一杆秤', tx, ty, { size: 64 * S, align: al, color: '#fff3dc', weight: 700, spacing: 8 * S, glow: 'rgba(0,0,0,.7)', blur: 16 * S });
|
| 57 |
ty += 92 * S;
|
| 58 |
// 钩子胶囊
|
libra-scales/js/player.js
CHANGED
|
@@ -61,7 +61,14 @@
|
|
| 61 |
document.querySelectorAll('[data-orient]').forEach(b => b.onclick = () => { st.orient = b.dataset.orient; document.querySelectorAll('[data-orient]').forEach(x => x.classList.toggle('on', x === b)); resize(); });
|
| 62 |
$('#tglMusic').onchange = e => { st.vol.music = e.target.checked ? 1 : 0; if (st.gM) st.gM.gain.value = st.vol.music; };
|
| 63 |
$('#tglVoice').onchange = e => { st.vol.voice = e.target.checked ? 1 : 0; if (st.gV) st.gV.gain.value = st.vol.voice * 1.05; };
|
| 64 |
-
$('#btnFull').onclick = () => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
const chaps = $('#chapters');
|
| 66 |
TL.scenes.forEach((s, i) => { const b = document.createElement('button'); b.className = 'chap'; b.textContent = (i + 1) + ' · ' + s.title; b.onclick = () => seek(s.start + .01); chaps.appendChild(b); });
|
| 67 |
window.addEventListener('keydown', e => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') return;
|
|
|
|
| 61 |
document.querySelectorAll('[data-orient]').forEach(b => b.onclick = () => { st.orient = b.dataset.orient; document.querySelectorAll('[data-orient]').forEach(x => x.classList.toggle('on', x === b)); resize(); });
|
| 62 |
$('#tglMusic').onchange = e => { st.vol.music = e.target.checked ? 1 : 0; if (st.gM) st.gM.gain.value = st.vol.music; };
|
| 63 |
$('#tglVoice').onchange = e => { st.vol.voice = e.target.checked ? 1 : 0; if (st.gV) st.gV.gain.value = st.vol.voice * 1.05; };
|
| 64 |
+
$('#btnFull').onclick = () => {
|
| 65 |
+
const el = stage, req = el.requestFullscreen || el.webkitRequestFullscreen;
|
| 66 |
+
if (document.fullscreenElement || document.webkitFullscreenElement) { (document.exitFullscreen || document.webkitExitFullscreen).call(document); return; }
|
| 67 |
+
if (stage.classList.contains('fs')) { stage.classList.remove('fs'); resize(); return; }
|
| 68 |
+
if (req) { try { const r = req.call(el); if (r && r.catch) r.catch(() => { stage.classList.add('fs'); resize(); }); } catch (e) { stage.classList.add('fs'); resize(); } }
|
| 69 |
+
else { stage.classList.add('fs'); resize(); } // iOS Safari:伪全屏
|
| 70 |
+
};
|
| 71 |
+
document.addEventListener('keydown', e => { if (e.key === 'Escape' && stage.classList.contains('fs')) { stage.classList.remove('fs'); resize(); } });
|
| 72 |
const chaps = $('#chapters');
|
| 73 |
TL.scenes.forEach((s, i) => { const b = document.createElement('button'); b.className = 'chap'; b.textContent = (i + 1) + ' · ' + s.title; b.onclick = () => seek(s.start + .01); chaps.appendChild(b); });
|
| 74 |
window.addEventListener('keydown', e => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') return;
|
libra-scales/style.css
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
:root{--gold:#f6d58e;--rose:#f4a9c4;--ink:#070a1e;--card:rgba(255,255,255,.05);--line:rgba(246,213,142,.22)}
|
| 2 |
*{box-sizing:border-box}
|
| 3 |
-
html
|
|
|
|
| 4 |
button,select,input,textarea{font:inherit;color:inherit}
|
| 5 |
.top{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px clamp(12px,3vw,36px)}
|
| 6 |
.brand{display:flex;align-items:center;gap:14px}
|
|
@@ -12,6 +13,7 @@ main{max-width:1280px;margin:0 auto;padding:0 clamp(8px,2vw,24px) 40px}
|
|
| 12 |
.player{margin-bottom:22px}
|
| 13 |
.stage{position:relative;width:100%;aspect-ratio:16/9;background:#03040c;border-radius:18px;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.6),0 0 0 1px var(--line);margin:0 auto}
|
| 14 |
.stage.portrait{aspect-ratio:9/16;width:min(100%,calc((100vh - 170px) * 9 / 16));min-width:280px}
|
|
|
|
| 15 |
.stage:fullscreen{border-radius:0;width:100vw;height:100vh;aspect-ratio:auto}
|
| 16 |
#screen{width:100%;height:100%;display:block;cursor:pointer}
|
| 17 |
.loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(3,4,14,.72);gap:14px;transition:opacity .5s}
|
|
@@ -62,8 +64,10 @@ button:disabled{opacity:.4;cursor:not-allowed}
|
|
| 62 |
.cover button{background:rgba(246,213,142,.14);border:1px solid var(--line);border-radius:8px;padding:7px;cursor:pointer;color:var(--gold)}
|
| 63 |
footer{text-align:center;opacity:.5;font-size:12px;line-height:1.8;margin-top:26px}
|
| 64 |
@media (max-width:640px){
|
| 65 |
-
.top{padding:12px}.glyph{font-size:
|
| 66 |
.stage{border-radius:12px}
|
| 67 |
.stage.portrait{width:100%;min-width:0}
|
| 68 |
.controls{gap:8px;padding:8px}.time{min-width:auto}
|
| 69 |
}
|
|
|
|
|
|
|
|
|
| 1 |
:root{--gold:#f6d58e;--rose:#f4a9c4;--ink:#070a1e;--card:rgba(255,255,255,.05);--line:rgba(246,213,142,.22)}
|
| 2 |
*{box-sizing:border-box}
|
| 3 |
+
html{background:#05060f}
|
| 4 |
+
body{margin:0;min-height:100vh;background:radial-gradient(1200px 800px at 75% -10%,#2a1a5c 0,#0b1030 45%,#05060f 100%) no-repeat,#05060f;color:#efeaff;font-family:"Noto Sans SC","PingFang SC","Microsoft YaHei",sans-serif}
|
| 5 |
button,select,input,textarea{font:inherit;color:inherit}
|
| 6 |
.top{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:18px clamp(12px,3vw,36px)}
|
| 7 |
.brand{display:flex;align-items:center;gap:14px}
|
|
|
|
| 13 |
.player{margin-bottom:22px}
|
| 14 |
.stage{position:relative;width:100%;aspect-ratio:16/9;background:#03040c;border-radius:18px;overflow:hidden;box-shadow:0 30px 90px rgba(0,0,0,.6),0 0 0 1px var(--line);margin:0 auto}
|
| 15 |
.stage.portrait{aspect-ratio:9/16;width:min(100%,calc((100vh - 170px) * 9 / 16));min-width:280px}
|
| 16 |
+
.stage.fs{position:fixed;inset:0;z-index:50;border-radius:0;width:100vw!important;height:100vh;height:100dvh;aspect-ratio:auto;min-width:0}
|
| 17 |
.stage:fullscreen{border-radius:0;width:100vw;height:100vh;aspect-ratio:auto}
|
| 18 |
#screen{width:100%;height:100%;display:block;cursor:pointer}
|
| 19 |
.loader{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;background:rgba(3,4,14,.72);gap:14px;transition:opacity .5s}
|
|
|
|
| 64 |
.cover button{background:rgba(246,213,142,.14);border:1px solid var(--line);border-radius:8px;padding:7px;cursor:pointer;color:var(--gold)}
|
| 65 |
footer{text-align:center;opacity:.5;font-size:12px;line-height:1.8;margin-top:26px}
|
| 66 |
@media (max-width:640px){
|
| 67 |
+
.top{padding:12px;align-items:flex-start}.glyph{font-size:30px}.back{font-size:12px}.top h1{font-size:18px;letter-spacing:1px}.top p{font-size:11px}
|
| 68 |
.stage{border-radius:12px}
|
| 69 |
.stage.portrait{width:100%;min-width:0}
|
| 70 |
.controls{gap:8px;padding:8px}.time{min-width:auto}
|
| 71 |
}
|
| 72 |
+
|
| 73 |
+
.pbtn svg{width:18px;height:18px;display:block;margin:auto;fill:none;stroke:currentColor;stroke-width:2}
|