Spaces:
Running
Running
Download shift.html from yxma/react-action-debug: direct link, hf CLI and curl.
- Browser
- Download file 5.68 kB
-
https://huggingface.co/spaces/yxma/react-action-debug/resolve/main/shift.html
- Command line
-
hf download hf://spaces/yxma/react-action-debug/shift.html
-
curl -L -o shift.html https://huggingface.co/spaces/yxma/react-action-debug/resolve/main/shift.html
5.68 kB
| <html lang="zh"><head><meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width,initial-scale=1"> | |
| <title>mocap shift — episode_006_seg00</title> | |
| <style> | |
| :root{--bg:#0e1116;--panel:#161b22;--line:#30363d;--fg:#e6edf3;--dim:#8b949e; | |
| --L:#58a6ff;--R:#ff9d4d} | |
| *{box-sizing:border-box} body{margin:0;background:var(--bg);color:var(--fg); | |
| font:13px/1.5 ui-monospace,SFMono-Regular,Menlo,monospace} | |
| header{padding:10px 14px;border-bottom:1px solid var(--line)} | |
| h1{margin:0;font-size:15px;font-weight:600} | |
| .sub{color:var(--dim);font-size:12px;margin-top:2px} | |
| .sub a{color:var(--L)} | |
| #wrap{position:relative;width:100%;max-width:960px;margin:0 auto;background:#000} | |
| #wrap img,#wrap canvas{width:100%;display:block} | |
| #ov{position:absolute;inset:0} | |
| .bar{display:flex;gap:8px;align-items:center;padding:8px 14px;flex-wrap:wrap; | |
| border-bottom:1px solid var(--line)} | |
| button{background:var(--panel);color:var(--fg);border:1px solid var(--line); | |
| border-radius:5px;padding:4px 10px;cursor:pointer;font:inherit} | |
| button:hover{border-color:var(--dim)} | |
| input[type=range]{accent-color:var(--L)} | |
| #srange{width:260px} #frange{flex:1;min-width:200px} | |
| .val{font-variant-numeric:tabular-nums} .tag{color:var(--dim)} | |
| .big{font-size:17px;font-weight:600;color:var(--L);min-width:52px;display:inline-block;text-align:right} | |
| kbd{background:var(--panel);border:1px solid var(--line);border-radius:3px;padding:0 4px} | |
| .note{padding:8px 14px;color:var(--dim);font-size:12px;border-top:1px solid var(--line)} | |
| </style></head><body> | |
| <header> | |
| <h1>mocap 时间偏移检查 · view_middle</h1> | |
| <div class="sub">图像固定,叠加用 <b>pose[frame + shift]</b> 绘制 · <a href="index.html">← 完整面板播放器</a></div> | |
| </header> | |
| <div id="wrap"><img id="img" alt=""><canvas id="ov"></canvas></div> | |
| <div class="bar"> | |
| <span class="tag">shift</span><span class="big" id="sv">0</span><span class="tag">帧</span> | |
| <input id="srange" type="range" min="-8" max="8" step="1" value="0"> | |
| <button id="s0">归零</button> | |
| <button id="sweep">▶ 扫描 -5…+5</button> | |
| </div> | |
| <div class="bar"> | |
| <span class="tag">frame</span><span class="val" id="fv">0</span> | |
| <span class="tag">row</span><span class="val" id="rv">—</span> | |
| <input id="frange" type="range" min="0" value="0"> | |
| <button id="prev">◀</button><button id="next">▶</button> | |
| <button id="play">▶ 播放</button> | |
| </div> | |
| <div class="note"> | |
| 正偏移 = 叠加取<b>更晚</b>的位姿。若 mocap 落后于相机,正偏移会让叠加贴回传感器。 | |
| 蓝 = 左,橙 = 右。<kbd>←</kbd><kbd>→</kbd> 帧 · <kbd>↑</kbd><kbd>↓</kbd> shift · <kbd>空格</kbd> 播放 | |
| </div> | |
| <script> | |
| const $=id=>document.getElementById(id); | |
| let D=null,i=0,sh=0,playing=false,timer=null,sweeping=null; | |
| const pad=n=>String(n).padStart(4,'0'); | |
| fetch('data.json').then(r=>r.json()).then(d=>{D=d;$('frange').max=d.n-1;show(0);}); | |
| function pt(arr,row){const k=row-D.proj.lo_row; | |
| return (k>=0&&k<arr.length)?arr[k]:null;} | |
| function show(k){ | |
| i=Math.max(0,Math.min(D.n-1,k)); | |
| $('img').src='mid/m'+pad(i+1)+'.jpg'; | |
| $('frange').value=i; $('fv').textContent=i; | |
| $('rv').textContent=D.rows[i]; draw(); | |
| } | |
| function draw(){ | |
| const c=$('ov'),img=$('img'); | |
| const W=img.clientWidth||960, H=img.clientHeight||W*D.proj.h/D.proj.w; | |
| c.width=W*devicePixelRatio; c.height=H*devicePixelRatio; | |
| c.style.height=H+'px'; | |
| const g=c.getContext('2d'); g.clearRect(0,0,c.width,c.height); | |
| const sx=c.width/D.proj.w, sy=c.height/D.proj.h; | |
| const row=D.rows[i]+sh; | |
| [['left','#58a6ff'],['right','#ff9d4d']].forEach(([side,col])=>{ | |
| const p=pt(D.proj[side],row); if(!p)return; | |
| const x=p[0]*sx,y=p[1]*sy,r=13*devicePixelRatio; | |
| g.strokeStyle=col; g.lineWidth=2.4*devicePixelRatio; | |
| g.beginPath(); g.arc(x,y,r,0,7); g.stroke(); | |
| g.beginPath(); g.moveTo(x-r*1.5,y); g.lineTo(x+r*1.5,y); | |
| g.moveTo(x,y-r*1.5); g.lineTo(x,y+r*1.5); g.stroke(); | |
| }); | |
| // shift != 0 时把原位置画成虚线,便于对比 | |
| if(sh!==0){ g.setLineDash([5*devicePixelRatio,4*devicePixelRatio]); | |
| [['left','#58a6ff'],['right','#ff9d4d']].forEach(([side,col])=>{ | |
| const p=pt(D.proj[side],D.rows[i]); if(!p)return; | |
| g.strokeStyle=col+'70'; g.lineWidth=1.6*devicePixelRatio; | |
| g.beginPath(); g.arc(p[0]*sx,p[1]*sy,13*devicePixelRatio,0,7); g.stroke();}); | |
| g.setLineDash([]); } | |
| } | |
| $('srange').oninput=e=>{sh=+e.target.value;$('sv').textContent=(sh>0?'+':'')+sh;draw();}; | |
| $('s0').onclick=()=>{sh=0;$('srange').value=0;$('sv').textContent='0';draw();}; | |
| $('sweep').onclick=()=>{ | |
| if(sweeping){clearInterval(sweeping);sweeping=null;$('sweep').textContent='▶ 扫描 -5…+5';return;} | |
| let v=-5; $('sweep').textContent='⏸ 停止扫描'; | |
| sweeping=setInterval(()=>{sh=v;$('srange').value=v;$('sv').textContent=(v>0?'+':'')+v;draw(); | |
| v++; if(v>5)v=-5;},700);}; | |
| $('frange').oninput=e=>show(+e.target.value); | |
| $('prev').onclick=()=>show(i-1); $('next').onclick=()=>show(i+1); | |
| $('play').onclick=()=>{playing=!playing;$('play').textContent=playing?'⏸':'▶ 播放'; | |
| if(playing)timer=setInterval(()=>show(i>=D.n-1?0:i+1),1000/30); else clearInterval(timer);}; | |
| addEventListener('keydown',e=>{ | |
| if(e.key==='ArrowLeft'){show(i-1);e.preventDefault();} | |
| if(e.key==='ArrowRight'){show(i+1);e.preventDefault();} | |
| if(e.key==='ArrowUp'){$('srange').value=Math.min(8,sh+1);$('srange').oninput({target:$('srange')});e.preventDefault();} | |
| if(e.key==='ArrowDown'){$('srange').value=Math.max(-8,sh-1);$('srange').oninput({target:$('srange')});e.preventDefault();} | |
| if(e.code==='Space'){$('play').click();e.preventDefault();}}); | |
| $('img').onload=draw; addEventListener('resize',draw); | |
| </script></body></html> | |