Spaces:
Running
Running
Normalise ep4 to viewer.html (drop view.html); sidebar height now tracks the video column
Browse files- ep0/viewer.html +42 -4
- ep1/viewer.html +42 -4
- ep2/viewer.html +42 -4
- ep3/viewer.html +42 -4
- ep4/view.html +0 -0
- ep4/viewer.html +3 -0
- ep5/viewer.html +42 -4
- teleop.html +1 -1
ep0/viewer.html
CHANGED
|
@@ -56,6 +56,9 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
|
|
|
|
|
|
|
|
|
| 59 |
</style></head><body>
|
| 60 |
<header>
|
| 61 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
@@ -219,7 +222,7 @@ function handLayout(mirror){
|
|
| 219 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 220 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 221 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 222 |
-
const FING=[['little',64,42,
|
| 223 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 224 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 225 |
for(const [nm,off,cx,top] of FING){
|
|
@@ -255,8 +258,16 @@ function handLayout(mirror){
|
|
| 255 |
}
|
| 256 |
|
| 257 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 259 |
-
|
| 260 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 261 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 262 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
@@ -267,9 +278,9 @@ function drawTactile(i){
|
|
| 267 |
_frame=i; _hit=[];
|
| 268 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 269 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 270 |
-
const oy=(HH-
|
| 271 |
HANDS.forEach((hd,hi)=>{
|
| 272 |
-
const ox=
|
| 273 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 274 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 275 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
@@ -393,4 +404,31 @@ window.addEventListener('load',update);
|
|
| 393 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 394 |
},200);
|
| 395 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
</script></body></html>
|
|
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
| 59 |
+
|
| 60 |
+
.layout{align-items:start}
|
| 61 |
+
.sidecol>.panel:first-child{flex:0 0 auto;min-height:60px;overflow:auto}
|
| 62 |
</style></head><body>
|
| 63 |
<header>
|
| 64 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
|
|
| 222 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 223 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 224 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 225 |
+
const FING=[['little',64,42,70],['ring',48,76,48],['middle',32,110,36],['index',16,140,50]];
|
| 226 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 227 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 228 |
for(const [nm,off,cx,top] of FING){
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
| 261 |
+
// 内容包围盒: 缩放时按它算, 避免上下留白吃掉尺寸
|
| 262 |
+
const BBOX=(function(){var x0=1e9,y0=1e9,x1=-1e9,y1=-1e9;
|
| 263 |
+
HANDS.forEach(function(h){h.lay.cells.concat(h.lay.outline).forEach(function(o){
|
| 264 |
+
var a=o.rot||0,ca=Math.cos(a),sa=Math.sin(a);
|
| 265 |
+
[[0,0],[o.w,0],[0,o.h],[o.w,o.h]].forEach(function(p){ // 旋转矩形的四个真实角点
|
| 266 |
+
var X=o.x+p[0]*ca-p[1]*sa, Y=o.y+p[0]*sa+p[1]*ca;
|
| 267 |
+
x0=Math.min(x0,X);y0=Math.min(y0,Y);x1=Math.max(x1,X);y1=Math.max(y1,Y);});});});
|
| 268 |
+
return {x:x0-2,y:y0-2,w:x1-x0+4,h:y1-y0+4};})();
|
| 269 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 270 |
+
let HW=372, HH=210, HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 271 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 272 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 273 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
|
|
| 278 |
_frame=i; _hit=[];
|
| 279 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 280 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 281 |
+
const oy=(HH-BBOX.h*HSC)/2-BBOX.y*HSC;
|
| 282 |
HANDS.forEach((hd,hi)=>{
|
| 283 |
+
const ox=8+hi*(HW/2)-BBOX.x*HSC;
|
| 284 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 285 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 286 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
|
|
| 404 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 405 |
},200);
|
| 406 |
})();
|
| 407 |
+
|
| 408 |
+
// ---- 侧栏高度贴合左侧视频列 ----
|
| 409 |
+
function fitHand(){
|
| 410 |
+
var camPanel=document.querySelector('.layout > .panel');
|
| 411 |
+
var spans=document.querySelector('.sidecol > .panel:first-child');
|
| 412 |
+
var tac=document.querySelector('.tacpanel');
|
| 413 |
+
if(!camPanel||!spans||!tac) return;
|
| 414 |
+
spans.style.maxHeight=''; // 先量自然高度
|
| 415 |
+
var availH=camPanel.getBoundingClientRect().height;
|
| 416 |
+
var chrome=tac.getBoundingClientRect().height-cHand.getBoundingClientRect().height;
|
| 417 |
+
var spansH=spans.getBoundingClientRect().height;
|
| 418 |
+
var h=availH-spansH-14-chrome;
|
| 419 |
+
if(h<150){ // 空间不够: 让 spans 滚动, 画布保底 150
|
| 420 |
+
h=150;
|
| 421 |
+
var cap=availH-14-chrome-h;
|
| 422 |
+
if(cap>60) spans.style.maxHeight=Math.floor(cap)+'px';
|
| 423 |
+
}
|
| 424 |
+
h=Math.min(300,Math.max(150,Math.floor(h)));
|
| 425 |
+
var w=Math.max(280,Math.floor(tac.clientWidth-20));
|
| 426 |
+
if(h===HH && w===HW) return;
|
| 427 |
+
HH=h; HW=w; HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 428 |
+
cHand.style.height=HH+'px';
|
| 429 |
+
drawTactile(_frame);
|
| 430 |
+
}
|
| 431 |
+
window.addEventListener('resize',function(){clearTimeout(window.__fitT);window.__fitT=setTimeout(fitHand,120);});
|
| 432 |
+
window.addEventListener('load',function(){fitHand();setTimeout(fitHand,400);});
|
| 433 |
+
setTimeout(fitHand,150); setTimeout(fitHand,900);
|
| 434 |
</script></body></html>
|
ep1/viewer.html
CHANGED
|
@@ -56,6 +56,9 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
|
|
|
|
|
|
|
|
|
| 59 |
</style></head><body>
|
| 60 |
<header>
|
| 61 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
@@ -219,7 +222,7 @@ function handLayout(mirror){
|
|
| 219 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 220 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 221 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 222 |
-
const FING=[['little',64,42,
|
| 223 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 224 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 225 |
for(const [nm,off,cx,top] of FING){
|
|
@@ -255,8 +258,16 @@ function handLayout(mirror){
|
|
| 255 |
}
|
| 256 |
|
| 257 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 259 |
-
|
| 260 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 261 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 262 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
@@ -267,9 +278,9 @@ function drawTactile(i){
|
|
| 267 |
_frame=i; _hit=[];
|
| 268 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 269 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 270 |
-
const oy=(HH-
|
| 271 |
HANDS.forEach((hd,hi)=>{
|
| 272 |
-
const ox=
|
| 273 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 274 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 275 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
@@ -393,4 +404,31 @@ window.addEventListener('load',update);
|
|
| 393 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 394 |
},200);
|
| 395 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
</script></body></html>
|
|
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
| 59 |
+
|
| 60 |
+
.layout{align-items:start}
|
| 61 |
+
.sidecol>.panel:first-child{flex:0 0 auto;min-height:60px;overflow:auto}
|
| 62 |
</style></head><body>
|
| 63 |
<header>
|
| 64 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
|
|
| 222 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 223 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 224 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 225 |
+
const FING=[['little',64,42,70],['ring',48,76,48],['middle',32,110,36],['index',16,140,50]];
|
| 226 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 227 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 228 |
for(const [nm,off,cx,top] of FING){
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
| 261 |
+
// 内容包围盒: 缩放时按它算, 避免上下留白吃掉尺寸
|
| 262 |
+
const BBOX=(function(){var x0=1e9,y0=1e9,x1=-1e9,y1=-1e9;
|
| 263 |
+
HANDS.forEach(function(h){h.lay.cells.concat(h.lay.outline).forEach(function(o){
|
| 264 |
+
var a=o.rot||0,ca=Math.cos(a),sa=Math.sin(a);
|
| 265 |
+
[[0,0],[o.w,0],[0,o.h],[o.w,o.h]].forEach(function(p){ // 旋转矩形的四个真实角点
|
| 266 |
+
var X=o.x+p[0]*ca-p[1]*sa, Y=o.y+p[0]*sa+p[1]*ca;
|
| 267 |
+
x0=Math.min(x0,X);y0=Math.min(y0,Y);x1=Math.max(x1,X);y1=Math.max(y1,Y);});});});
|
| 268 |
+
return {x:x0-2,y:y0-2,w:x1-x0+4,h:y1-y0+4};})();
|
| 269 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 270 |
+
let HW=372, HH=210, HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 271 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 272 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 273 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
|
|
| 278 |
_frame=i; _hit=[];
|
| 279 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 280 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 281 |
+
const oy=(HH-BBOX.h*HSC)/2-BBOX.y*HSC;
|
| 282 |
HANDS.forEach((hd,hi)=>{
|
| 283 |
+
const ox=8+hi*(HW/2)-BBOX.x*HSC;
|
| 284 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 285 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 286 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
|
|
| 404 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 405 |
},200);
|
| 406 |
})();
|
| 407 |
+
|
| 408 |
+
// ---- 侧栏高度贴合左侧视频列 ----
|
| 409 |
+
function fitHand(){
|
| 410 |
+
var camPanel=document.querySelector('.layout > .panel');
|
| 411 |
+
var spans=document.querySelector('.sidecol > .panel:first-child');
|
| 412 |
+
var tac=document.querySelector('.tacpanel');
|
| 413 |
+
if(!camPanel||!spans||!tac) return;
|
| 414 |
+
spans.style.maxHeight=''; // 先量自然高度
|
| 415 |
+
var availH=camPanel.getBoundingClientRect().height;
|
| 416 |
+
var chrome=tac.getBoundingClientRect().height-cHand.getBoundingClientRect().height;
|
| 417 |
+
var spansH=spans.getBoundingClientRect().height;
|
| 418 |
+
var h=availH-spansH-14-chrome;
|
| 419 |
+
if(h<150){ // 空间不够: 让 spans 滚动, 画布保底 150
|
| 420 |
+
h=150;
|
| 421 |
+
var cap=availH-14-chrome-h;
|
| 422 |
+
if(cap>60) spans.style.maxHeight=Math.floor(cap)+'px';
|
| 423 |
+
}
|
| 424 |
+
h=Math.min(300,Math.max(150,Math.floor(h)));
|
| 425 |
+
var w=Math.max(280,Math.floor(tac.clientWidth-20));
|
| 426 |
+
if(h===HH && w===HW) return;
|
| 427 |
+
HH=h; HW=w; HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 428 |
+
cHand.style.height=HH+'px';
|
| 429 |
+
drawTactile(_frame);
|
| 430 |
+
}
|
| 431 |
+
window.addEventListener('resize',function(){clearTimeout(window.__fitT);window.__fitT=setTimeout(fitHand,120);});
|
| 432 |
+
window.addEventListener('load',function(){fitHand();setTimeout(fitHand,400);});
|
| 433 |
+
setTimeout(fitHand,150); setTimeout(fitHand,900);
|
| 434 |
</script></body></html>
|
ep2/viewer.html
CHANGED
|
@@ -56,6 +56,9 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
|
|
|
|
|
|
|
|
|
| 59 |
</style></head><body>
|
| 60 |
<header>
|
| 61 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
@@ -219,7 +222,7 @@ function handLayout(mirror){
|
|
| 219 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 220 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 221 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 222 |
-
const FING=[['little',64,42,
|
| 223 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 224 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 225 |
for(const [nm,off,cx,top] of FING){
|
|
@@ -255,8 +258,16 @@ function handLayout(mirror){
|
|
| 255 |
}
|
| 256 |
|
| 257 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 259 |
-
|
| 260 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 261 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 262 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
@@ -267,9 +278,9 @@ function drawTactile(i){
|
|
| 267 |
_frame=i; _hit=[];
|
| 268 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 269 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 270 |
-
const oy=(HH-
|
| 271 |
HANDS.forEach((hd,hi)=>{
|
| 272 |
-
const ox=
|
| 273 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 274 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 275 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
@@ -393,4 +404,31 @@ window.addEventListener('load',update);
|
|
| 393 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 394 |
},200);
|
| 395 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
</script></body></html>
|
|
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
| 59 |
+
|
| 60 |
+
.layout{align-items:start}
|
| 61 |
+
.sidecol>.panel:first-child{flex:0 0 auto;min-height:60px;overflow:auto}
|
| 62 |
</style></head><body>
|
| 63 |
<header>
|
| 64 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
|
|
| 222 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 223 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 224 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 225 |
+
const FING=[['little',64,42,70],['ring',48,76,48],['middle',32,110,36],['index',16,140,50]];
|
| 226 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 227 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 228 |
for(const [nm,off,cx,top] of FING){
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
| 261 |
+
// 内容包围盒: 缩放时按它算, 避免上下留白吃掉尺寸
|
| 262 |
+
const BBOX=(function(){var x0=1e9,y0=1e9,x1=-1e9,y1=-1e9;
|
| 263 |
+
HANDS.forEach(function(h){h.lay.cells.concat(h.lay.outline).forEach(function(o){
|
| 264 |
+
var a=o.rot||0,ca=Math.cos(a),sa=Math.sin(a);
|
| 265 |
+
[[0,0],[o.w,0],[0,o.h],[o.w,o.h]].forEach(function(p){ // 旋转矩形的四个真实角点
|
| 266 |
+
var X=o.x+p[0]*ca-p[1]*sa, Y=o.y+p[0]*sa+p[1]*ca;
|
| 267 |
+
x0=Math.min(x0,X);y0=Math.min(y0,Y);x1=Math.max(x1,X);y1=Math.max(y1,Y);});});});
|
| 268 |
+
return {x:x0-2,y:y0-2,w:x1-x0+4,h:y1-y0+4};})();
|
| 269 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 270 |
+
let HW=372, HH=210, HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 271 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 272 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 273 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
|
|
| 278 |
_frame=i; _hit=[];
|
| 279 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 280 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 281 |
+
const oy=(HH-BBOX.h*HSC)/2-BBOX.y*HSC;
|
| 282 |
HANDS.forEach((hd,hi)=>{
|
| 283 |
+
const ox=8+hi*(HW/2)-BBOX.x*HSC;
|
| 284 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 285 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 286 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
|
|
| 404 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 405 |
},200);
|
| 406 |
})();
|
| 407 |
+
|
| 408 |
+
// ---- 侧栏高度贴合左侧视频列 ----
|
| 409 |
+
function fitHand(){
|
| 410 |
+
var camPanel=document.querySelector('.layout > .panel');
|
| 411 |
+
var spans=document.querySelector('.sidecol > .panel:first-child');
|
| 412 |
+
var tac=document.querySelector('.tacpanel');
|
| 413 |
+
if(!camPanel||!spans||!tac) return;
|
| 414 |
+
spans.style.maxHeight=''; // 先量自然高度
|
| 415 |
+
var availH=camPanel.getBoundingClientRect().height;
|
| 416 |
+
var chrome=tac.getBoundingClientRect().height-cHand.getBoundingClientRect().height;
|
| 417 |
+
var spansH=spans.getBoundingClientRect().height;
|
| 418 |
+
var h=availH-spansH-14-chrome;
|
| 419 |
+
if(h<150){ // 空间不够: 让 spans 滚动, 画布保底 150
|
| 420 |
+
h=150;
|
| 421 |
+
var cap=availH-14-chrome-h;
|
| 422 |
+
if(cap>60) spans.style.maxHeight=Math.floor(cap)+'px';
|
| 423 |
+
}
|
| 424 |
+
h=Math.min(300,Math.max(150,Math.floor(h)));
|
| 425 |
+
var w=Math.max(280,Math.floor(tac.clientWidth-20));
|
| 426 |
+
if(h===HH && w===HW) return;
|
| 427 |
+
HH=h; HW=w; HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 428 |
+
cHand.style.height=HH+'px';
|
| 429 |
+
drawTactile(_frame);
|
| 430 |
+
}
|
| 431 |
+
window.addEventListener('resize',function(){clearTimeout(window.__fitT);window.__fitT=setTimeout(fitHand,120);});
|
| 432 |
+
window.addEventListener('load',function(){fitHand();setTimeout(fitHand,400);});
|
| 433 |
+
setTimeout(fitHand,150); setTimeout(fitHand,900);
|
| 434 |
</script></body></html>
|
ep3/viewer.html
CHANGED
|
@@ -56,6 +56,9 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
|
|
|
|
|
|
|
|
|
| 59 |
</style></head><body>
|
| 60 |
<header>
|
| 61 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
@@ -219,7 +222,7 @@ function handLayout(mirror){
|
|
| 219 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 220 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 221 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 222 |
-
const FING=[['little',64,42,
|
| 223 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 224 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 225 |
for(const [nm,off,cx,top] of FING){
|
|
@@ -255,8 +258,16 @@ function handLayout(mirror){
|
|
| 255 |
}
|
| 256 |
|
| 257 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 259 |
-
|
| 260 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 261 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 262 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
@@ -267,9 +278,9 @@ function drawTactile(i){
|
|
| 267 |
_frame=i; _hit=[];
|
| 268 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 269 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 270 |
-
const oy=(HH-
|
| 271 |
HANDS.forEach((hd,hi)=>{
|
| 272 |
-
const ox=
|
| 273 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 274 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 275 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
@@ -393,4 +404,31 @@ window.addEventListener('load',update);
|
|
| 393 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 394 |
},200);
|
| 395 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
</script></body></html>
|
|
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
| 59 |
+
|
| 60 |
+
.layout{align-items:start}
|
| 61 |
+
.sidecol>.panel:first-child{flex:0 0 auto;min-height:60px;overflow:auto}
|
| 62 |
</style></head><body>
|
| 63 |
<header>
|
| 64 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
|
|
| 222 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 223 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 224 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 225 |
+
const FING=[['little',64,42,70],['ring',48,76,48],['middle',32,110,36],['index',16,140,50]];
|
| 226 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 227 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 228 |
for(const [nm,off,cx,top] of FING){
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
| 261 |
+
// 内容包围盒: 缩放时按它算, 避免上下留白吃掉尺寸
|
| 262 |
+
const BBOX=(function(){var x0=1e9,y0=1e9,x1=-1e9,y1=-1e9;
|
| 263 |
+
HANDS.forEach(function(h){h.lay.cells.concat(h.lay.outline).forEach(function(o){
|
| 264 |
+
var a=o.rot||0,ca=Math.cos(a),sa=Math.sin(a);
|
| 265 |
+
[[0,0],[o.w,0],[0,o.h],[o.w,o.h]].forEach(function(p){ // 旋转矩形的四个真实角点
|
| 266 |
+
var X=o.x+p[0]*ca-p[1]*sa, Y=o.y+p[0]*sa+p[1]*ca;
|
| 267 |
+
x0=Math.min(x0,X);y0=Math.min(y0,Y);x1=Math.max(x1,X);y1=Math.max(y1,Y);});});});
|
| 268 |
+
return {x:x0-2,y:y0-2,w:x1-x0+4,h:y1-y0+4};})();
|
| 269 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 270 |
+
let HW=372, HH=210, HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 271 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 272 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 273 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
|
|
| 278 |
_frame=i; _hit=[];
|
| 279 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 280 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 281 |
+
const oy=(HH-BBOX.h*HSC)/2-BBOX.y*HSC;
|
| 282 |
HANDS.forEach((hd,hi)=>{
|
| 283 |
+
const ox=8+hi*(HW/2)-BBOX.x*HSC;
|
| 284 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 285 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 286 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
|
|
| 404 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 405 |
},200);
|
| 406 |
})();
|
| 407 |
+
|
| 408 |
+
// ---- 侧栏高度贴合左侧视频列 ----
|
| 409 |
+
function fitHand(){
|
| 410 |
+
var camPanel=document.querySelector('.layout > .panel');
|
| 411 |
+
var spans=document.querySelector('.sidecol > .panel:first-child');
|
| 412 |
+
var tac=document.querySelector('.tacpanel');
|
| 413 |
+
if(!camPanel||!spans||!tac) return;
|
| 414 |
+
spans.style.maxHeight=''; // 先量自然高度
|
| 415 |
+
var availH=camPanel.getBoundingClientRect().height;
|
| 416 |
+
var chrome=tac.getBoundingClientRect().height-cHand.getBoundingClientRect().height;
|
| 417 |
+
var spansH=spans.getBoundingClientRect().height;
|
| 418 |
+
var h=availH-spansH-14-chrome;
|
| 419 |
+
if(h<150){ // 空间不够: 让 spans 滚动, 画布保底 150
|
| 420 |
+
h=150;
|
| 421 |
+
var cap=availH-14-chrome-h;
|
| 422 |
+
if(cap>60) spans.style.maxHeight=Math.floor(cap)+'px';
|
| 423 |
+
}
|
| 424 |
+
h=Math.min(300,Math.max(150,Math.floor(h)));
|
| 425 |
+
var w=Math.max(280,Math.floor(tac.clientWidth-20));
|
| 426 |
+
if(h===HH && w===HW) return;
|
| 427 |
+
HH=h; HW=w; HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 428 |
+
cHand.style.height=HH+'px';
|
| 429 |
+
drawTactile(_frame);
|
| 430 |
+
}
|
| 431 |
+
window.addEventListener('resize',function(){clearTimeout(window.__fitT);window.__fitT=setTimeout(fitHand,120);});
|
| 432 |
+
window.addEventListener('load',function(){fitHand();setTimeout(fitHand,400);});
|
| 433 |
+
setTimeout(fitHand,150); setTimeout(fitHand,900);
|
| 434 |
</script></body></html>
|
ep4/view.html
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
ep4/viewer.html
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6bf2fe4455605ca1af3102dd615e0d0fd8206bc8b62fe3af920f46df4ad3953d
|
| 3 |
+
size 607139
|
ep5/viewer.html
CHANGED
|
@@ -56,6 +56,9 @@ canvas{width:100%;display:block;cursor:pointer}
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
|
|
|
|
|
|
|
|
|
| 59 |
</style></head><body>
|
| 60 |
<header>
|
| 61 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
@@ -219,7 +222,7 @@ function handLayout(mirror){
|
|
| 219 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 220 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 221 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 222 |
-
const FING=[['little',64,42,
|
| 223 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 224 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 225 |
for(const [nm,off,cx,top] of FING){
|
|
@@ -255,8 +258,16 @@ function handLayout(mirror){
|
|
| 255 |
}
|
| 256 |
|
| 257 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 259 |
-
|
| 260 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 261 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 262 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
@@ -267,9 +278,9 @@ function drawTactile(i){
|
|
| 267 |
_frame=i; _hit=[];
|
| 268 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 269 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 270 |
-
const oy=(HH-
|
| 271 |
HANDS.forEach((hd,hi)=>{
|
| 272 |
-
const ox=
|
| 273 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 274 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 275 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
@@ -393,4 +404,31 @@ window.addEventListener('load',update);
|
|
| 393 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 394 |
},200);
|
| 395 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
</script></body></html>
|
|
|
|
| 56 |
.tac-legend .grad{display:inline-block;width:70px;height:8px;border-radius:2px}
|
| 57 |
.tac-legend .sw{display:inline-block;width:9px;height:9px;border-radius:2px;background:#1b2028;border:1px solid #2a3340}
|
| 58 |
@media(max-width:1200px){.layout{grid-template-columns:1fr}}
|
| 59 |
+
|
| 60 |
+
.layout{align-items:start}
|
| 61 |
+
.sidecol>.panel:first-child{flex:0 0 auto;min-height:60px;overflow:auto}
|
| 62 |
</style></head><body>
|
| 63 |
<header>
|
| 64 |
<a class="back" href="../teleop.html">← all episodes</a>
|
|
|
|
| 222 |
const U=8.8, PX=14, PY=150, GAP=1.5; // 手掌网格单位
|
| 223 |
const CW=9.5,CH=5.4,G=1.3, PH=8*(CH+G)-G; // 指尖阵列 20.3 x 52.3
|
| 224 |
// 从左到右: 小指, 无名指, 中指, 食指(食指紧邻右侧拇指)
|
| 225 |
+
const FING=[['little',64,42,70],['ring',48,76,48],['middle',32,110,36],['index',16,140,50]];
|
| 226 |
outline.push({x:10,y:146,w:140,h:131,r:19,palm:true}); // 手掌轮廓(完整掌面)
|
| 227 |
outline.push({x:40,y:275,w:56,h:19,r:9}); // 手腕
|
| 228 |
for(const [nm,off,cx,top] of FING){
|
|
|
|
| 258 |
}
|
| 259 |
|
| 260 |
const HANDS=[{name:'left',base:0,lay:handLayout(true)},{name:'right',base:TAC_N,lay:handLayout(false)}];
|
| 261 |
+
// 内容包围盒: 缩放时按它算, 避免上下留白吃掉尺寸
|
| 262 |
+
const BBOX=(function(){var x0=1e9,y0=1e9,x1=-1e9,y1=-1e9;
|
| 263 |
+
HANDS.forEach(function(h){h.lay.cells.concat(h.lay.outline).forEach(function(o){
|
| 264 |
+
var a=o.rot||0,ca=Math.cos(a),sa=Math.sin(a);
|
| 265 |
+
[[0,0],[o.w,0],[0,o.h],[o.w,o.h]].forEach(function(p){ // 旋转矩形的四个真实角点
|
| 266 |
+
var X=o.x+p[0]*ca-p[1]*sa, Y=o.y+p[0]*sa+p[1]*ca;
|
| 267 |
+
x0=Math.min(x0,X);y0=Math.min(y0,Y);x1=Math.max(x1,X);y1=Math.max(y1,Y);});});});
|
| 268 |
+
return {x:x0-2,y:y0-2,w:x1-x0+4,h:y1-y0+4};})();
|
| 269 |
const cHand=document.getElementById('cHand'), tacTip=document.getElementById('tacTip');
|
| 270 |
+
let HW=372, HH=210, HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 271 |
cHand.style.width=HW+'px'; cHand.style.height=HH+'px';
|
| 272 |
document.getElementById('tacGrad').style.background='linear-gradient(90deg,'+RAMP.map(c=>`rgb(${c[0]},${c[1]},${c[2]})`).join(',')+')';
|
| 273 |
document.getElementById('tacPeakLbl').textContent=TAC_PEAK;
|
|
|
|
| 278 |
_frame=i; _hit=[];
|
| 279 |
const dpr=devicePixelRatio||1, ctx=cHand.getContext('2d');
|
| 280 |
cHand.width=HW*dpr; cHand.height=HH*dpr; ctx.setTransform(dpr,0,0,dpr,0,0); ctx.clearRect(0,0,HW,HH);
|
| 281 |
+
const oy=(HH-BBOX.h*HSC)/2-BBOX.y*HSC;
|
| 282 |
HANDS.forEach((hd,hi)=>{
|
| 283 |
+
const ox=8+hi*(HW/2)-BBOX.x*HSC;
|
| 284 |
ctx.save(); ctx.translate(ox,oy); ctx.scale(HSC,HSC);
|
| 285 |
ctx.strokeStyle='#26313f'; ctx.lineWidth=1.1;
|
| 286 |
for(const o of hd.lay.outline){ctx.save(); ctx.strokeStyle=o.palm?'#33475c':'#26313f';
|
|
|
|
| 404 |
if(d>0 && master.currentTime>=d-0.08) restart();
|
| 405 |
},200);
|
| 406 |
})();
|
| 407 |
+
|
| 408 |
+
// ---- 侧栏高度贴合左侧视频列 ----
|
| 409 |
+
function fitHand(){
|
| 410 |
+
var camPanel=document.querySelector('.layout > .panel');
|
| 411 |
+
var spans=document.querySelector('.sidecol > .panel:first-child');
|
| 412 |
+
var tac=document.querySelector('.tacpanel');
|
| 413 |
+
if(!camPanel||!spans||!tac) return;
|
| 414 |
+
spans.style.maxHeight=''; // 先量自然高度
|
| 415 |
+
var availH=camPanel.getBoundingClientRect().height;
|
| 416 |
+
var chrome=tac.getBoundingClientRect().height-cHand.getBoundingClientRect().height;
|
| 417 |
+
var spansH=spans.getBoundingClientRect().height;
|
| 418 |
+
var h=availH-spansH-14-chrome;
|
| 419 |
+
if(h<150){ // 空间不够: 让 spans 滚动, 画布保底 150
|
| 420 |
+
h=150;
|
| 421 |
+
var cap=availH-14-chrome-h;
|
| 422 |
+
if(cap>60) spans.style.maxHeight=Math.floor(cap)+'px';
|
| 423 |
+
}
|
| 424 |
+
h=Math.min(300,Math.max(150,Math.floor(h)));
|
| 425 |
+
var w=Math.max(280,Math.floor(tac.clientWidth-20));
|
| 426 |
+
if(h===HH && w===HW) return;
|
| 427 |
+
HH=h; HW=w; HSC=Math.min(HH/BBOX.h,(HW/2-8)/BBOX.w);
|
| 428 |
+
cHand.style.height=HH+'px';
|
| 429 |
+
drawTactile(_frame);
|
| 430 |
+
}
|
| 431 |
+
window.addEventListener('resize',function(){clearTimeout(window.__fitT);window.__fitT=setTimeout(fitHand,120);});
|
| 432 |
+
window.addEventListener('load',function(){fitHand();setTimeout(fitHand,400);});
|
| 433 |
+
setTimeout(fitHand,150); setTimeout(fitHand,900);
|
| 434 |
</script></body></html>
|
teleop.html
CHANGED
|
@@ -27,6 +27,6 @@ header{padding:22px 26px 6px}h1{margin:0 0 4px;font-size:22px}
|
|
| 27 |
<a class="card" href="ep1/viewer.html"><div class="ph"><img src="ep1/thumb.jpg" alt="episode 1"><span class="pi"></span></div><div class="m"><div class="t">Episode 1 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.8s</span><span>563 frames</span></div></div></a>
|
| 28 |
<a class="card" href="ep2/viewer.html"><div class="ph"><img src="ep2/thumb.jpg" alt="episode 2"><span class="pi"></span></div><div class="m"><div class="t">Episode 2 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.7s</span><span>562 frames</span></div></div></a>
|
| 29 |
<a class="card" href="ep3/viewer.html"><div class="ph"><img src="ep3/thumb.jpg" alt="episode 3"><span class="pi"></span></div><div class="m"><div class="t">Episode 3 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>20.5s</span><span>614 frames</span></div></div></a>
|
| 30 |
-
<a class="card" href="ep4/
|
| 31 |
<a class="card" href="ep5/viewer.html"><div class="ph"><img src="ep5/thumb.jpg" alt="episode 5"><span class="pi"></span></div><div class="m"><div class="t">Episode 5 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.4s</span><span>553 frames</span></div></div></a></div>
|
| 32 |
</body></html>
|
|
|
|
| 27 |
<a class="card" href="ep1/viewer.html"><div class="ph"><img src="ep1/thumb.jpg" alt="episode 1"><span class="pi"></span></div><div class="m"><div class="t">Episode 1 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.8s</span><span>563 frames</span></div></div></a>
|
| 28 |
<a class="card" href="ep2/viewer.html"><div class="ph"><img src="ep2/thumb.jpg" alt="episode 2"><span class="pi"></span></div><div class="m"><div class="t">Episode 2 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.7s</span><span>562 frames</span></div></div></a>
|
| 29 |
<a class="card" href="ep3/viewer.html"><div class="ph"><img src="ep3/thumb.jpg" alt="episode 3"><span class="pi"></span></div><div class="m"><div class="t">Episode 3 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>20.5s</span><span>614 frames</span></div></div></a>
|
| 30 |
+
<a class="card" href="ep4/viewer.html"><div class="ph"><img src="ep4/thumb.jpg" alt="episode 4"><span class="pi"></span></div><div class="m"><div class="t">Episode 4 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>22.4s</span><span>673 frames</span></div></div></a>
|
| 31 |
<a class="card" href="ep5/viewer.html"><div class="ph"><img src="ep5/thumb.jpg" alt="episode 5"><span class="pi"></span></div><div class="m"><div class="t">Episode 5 · Pick up the water bottle and put it in the basket</div><div class="r"><span class="chip">A2</span><span>18.4s</span><span>553 frames</span></div></div></a></div>
|
| 32 |
</body></html>
|