Files
rhinelab-ui/reference/boot-review.html
T

46 lines
7.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="zh-CN">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Rhine Lab · 前段 2D 动效对照</title>
<style>
*{box-sizing:border-box}body{margin:0;background:#eae5e1;color:#262824;font:14px Arial,"Microsoft YaHei",sans-serif}main{max-width:1800px;margin:auto;padding:28px}h1{font-size:22px;margin:0 0 10px;font-weight:600}p{line-height:1.7;color:#64645c;margin:0 0 22px}.views{display:grid;grid-template-columns:1fr 1fr;gap:12px}figure{margin:0}figcaption{margin:10px 0;font-size:12px}video,iframe{display:block;width:100%;aspect-ratio:16/9;border:0;background:#eae5e1}nav{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:22px 0 16px}button,a{font:inherit;color:inherit;border:1px solid #bcb9af;background:transparent;padding:9px 14px;cursor:pointer;text-decoration:none}button:hover,a:hover{background:#dcd6cc}button:focus-visible,input:focus-visible,a:focus-visible{outline:2px solid #94714b;outline-offset:3px}input{width:100%;accent-color:#786047}output{font:14px monospace;margin-left:auto}.marks{display:flex;gap:8px;flex-wrap:wrap;margin-top:14px}small{display:block;margin-top:20px;color:#64645c;line-height:1.8}@media(max-width:850px){main{padding:16px}}
.reference-frame{position:relative}.reference-frame img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;z-index:1;pointer-events:none}.reference-frame.playing img{display:none}
.crop{overflow:hidden;aspect-ratio:16/9}.crop>*{transform:scale(var(--zoom,1));transform-origin:var(--origin,50% 50%)}body[data-focus="ring"]{--zoom:1.7;--origin:50% 50%}body[data-focus="brand"]{--zoom:2.6;--origin:0% 0%}body[data-focus="company"]{--zoom:2.7;--origin:50% 46%}body[data-focus="orbit"]{--zoom:3.8;--origin:50% 50%}body[data-focus="logo"]{--zoom:3.8;--origin:50% 50%}body[data-focus="gap"]{--zoom:3.8;--origin:29% 50%}</style>
<main>
<h1>前段 2D 动效对照</h1>
<p>左侧为原片,右侧为实时界面。拖动时间轴或逐帧前后移动,两侧会同步;原片每秒 25 帧。</p>
<div class="views">
<figure><figcaption>原视频 · 6.76–27.00 秒</figcaption><div class="crop"><div class="reference-frame"><img id="reference-still" alt="原视频当前帧" src="boot-frames/0169.jpg"><video id="reference" muted playsinline preload="auto" src="../《明日方舟》特别映像%20[莱茵生命:访问]%20[BV1rr4y1b7sz].mp4"></video></div></div></figure>
<figure><figcaption>实时界面 · 逐帧重建</figcaption><div class="crop"><iframe id="replica" title="实时场景对照" src="/?time=1.76&freeze=1&review=1"></iframe></div></figure>
</div>
<nav><button id="play">播放对照</button><button id="prev">← 前一帧</button><button id="next">后一帧 →</button><a href="/" target="_blank">播放完整尺寸动画 ↗</a><a href="/?scene=archive" target="_blank">进入交互 ↗</a><output id="stamp">6.76 s · FRAME 169</output></nav>
<input id="timeline" aria-label="原视频帧位置" type="range" min="169" max="675" step="1" value="169">
<nav aria-label="局部放大"><label>放大位置 <select id="focus"><option value="full">完整画面</option><option value="logo">Logo 绘制与符号 · 3.8×</option><option value="gap">Logo 移动缺口 · 3.8×</option><option value="brand">左上三行文字 · 2.6×</option><option value="ring">权限圆环 · 1.7×</option><option value="orbit">小圆与环绕点 · 3.8×</option><option value="company">名称黑底扫过 · 2.7×</option></select></label><button data-frame="237">9.48 · 连续笔画</button><button data-frame="248">9.92 · 符号展开</button><button data-frame="258">10.32 · 加号旋转</button><button data-frame="460">18.40 · 缺口移动</button><button data-frame="278">11.12 · 第一行</button><button data-frame="280">11.20 · 第二行</button><button data-frame="282">11.28 · 第三行</button><button data-frame="305">12.20 · 三行落定</button><button data-frame="551">22.04 · 环绕点出现</button><button data-frame="568">22.72 · 小圆收束</button><button data-frame="592">23.68 · 黑底快速段</button><button data-frame="610">24.40 · 黑底落定</button></nav>
<div class="marks"><button data-frame="187">7.48 · 英文输入</button><button data-frame="240">9.60 · 标志绘制</button><button data-frame="286">11.44 · 身份输入</button><button data-frame="337">13.48 · 姓名</button><button data-frame="500">20.00 · 圆环收拢</button><button data-frame="540">21.60 · 圆环落定</button><button data-frame="550">22.00 · 中心图形</button><button data-frame="569">22.76 · 黑白闪切</button><button data-frame="594">23.76 · 黑底扫过</button><button data-frame="635">25.40 · 欢迎页</button><button data-frame="669">26.76 · 白场转场</button><label>速度 <select id="speed"><option value="1">正常</option><option value="0.5">半速</option><option value="0.25">四分之一</option></select></label></div>
<small>仅用于本地复核。产品从原片画面变白后开始,不包含黑底鹰角片头;原视频不进入产品页面。← / → 逐帧前后移动。</small>
</main>
<script type="module">
const video=document.querySelector('#reference'),frame=document.querySelector('#replica'),slider=document.querySelector('#timeline'),stamp=document.querySelector('#stamp'),play=document.querySelector('#play');
const still=document.querySelector('#reference-still'),params=new URLSearchParams(location.search);let desired=Math.max(169,Math.min(675,Number(params.get('frame'))||169))/25;
if(['full','logo','gap','brand','ring','orbit','company'].includes(params.get('focus'))){document.body.dataset.focus=params.get('focus');document.querySelector('#focus').value=params.get('focus')}
function sync(t){desired=t;still.src=`boot-frames/${String(Math.round(t*25)).padStart(4,'0')}.jpg`;slider.value=String(Math.round(t*25));stamp.textContent=`${t.toFixed(2)} s · FRAME ${Math.round(t*25)}`;frame.contentWindow.postMessage({type:'rhine-review-frame',time:t-5},location.origin)}
function pause(){video.pause();video.parentElement.classList.remove('playing');play.textContent='播放对照'}
function seek(n){pause();const t=Math.max(169,Math.min(675,n))/25;desired=t;sync(t);video.currentTime=t}
video.addEventListener('loadedmetadata',()=>seek(Math.round(desired*25)));
frame.addEventListener('load',()=>sync(desired));
slider.addEventListener('input',()=>seek(Number(slider.value)));
document.querySelector('#prev').onclick=()=>seek(Number(slider.value)-1);
document.querySelector('#next').onclick=()=>seek(Number(slider.value)+1);
document.querySelectorAll('[data-frame]').forEach(b=>b.onclick=()=>seek(Number(b.dataset.frame)));
play.onclick=async()=>{if(!video.paused){pause();return}if(video.currentTime>=27.0)seek(169);await video.play();video.parentElement.classList.add('playing');play.textContent='暂停'};
video.addEventListener('seeked',()=>sync(video.currentTime));
function tick(_,metadata){if(!video.paused){if(metadata.mediaTime>=27.04){seek(169)}else sync(metadata.mediaTime)}video.requestVideoFrameCallback(tick)}
video.requestVideoFrameCallback(tick);
document.querySelector('#speed').onchange=e=>video.playbackRate=Number(e.target.value);
document.querySelector('#focus').onchange=e=>{document.body.dataset.focus=e.target.value;seek({logo:229,gap:425,brand:278,ring:532,orbit:544,company:592,full:Number(slider.value)}[e.target.value])};
document.addEventListener('keydown',e=>{if(e.target===slider)return;if(e.code==='ArrowLeft'){e.preventDefault();seek(Number(slider.value)-1)}if(e.code==='ArrowRight'){e.preventDefault();seek(Number(slider.value)+1)}});
</script>
</html>