update
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover, maximum-scale=1" />
|
||||
<title>Newbury Exhibit — pose jitter meter</title>
|
||||
<style>
|
||||
:root {
|
||||
--red:#f65151; --yellow:#fff35d; --blue:#529eff; --cyan:#51eaf1;
|
||||
--ink:#e8eaf2; --dim:#8a93ad; --panel:rgba(10,12,20,0.86);
|
||||
--good:#51eaf1; --warn:#fff35d; --bad:#f65151;
|
||||
}
|
||||
* { box-sizing:border-box; }
|
||||
html,body { margin:0; height:100%; background:#05060a; color:var(--ink);
|
||||
font-family:'Segoe UI',system-ui,-apple-system,sans-serif; overflow:hidden;
|
||||
-webkit-user-select:none; user-select:none; }
|
||||
#stage { position:fixed; inset:0; }
|
||||
#video,#overlay { position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
|
||||
#overlay { pointer-events:none; }
|
||||
|
||||
.card { background:var(--panel); border:1px solid rgba(255,255,255,0.08);
|
||||
border-radius:14px; backdrop-filter:blur(10px); }
|
||||
|
||||
#hud { position:fixed; left:10px; right:10px; top:calc(8px + env(safe-area-inset-top));
|
||||
padding:10px 12px; font-size:12.5px; line-height:1.45; }
|
||||
#hud .top { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
|
||||
#hud .title { font-weight:700; font-size:13px; letter-spacing:-0.01em; }
|
||||
.tag { padding:1px 8px; border-radius:999px; font-size:11px; font-weight:600; }
|
||||
.tag.on { background:rgba(81,234,241,0.16); color:var(--cyan); }
|
||||
.tag.off { background:rgba(246,81,81,0.16); color:var(--bad); }
|
||||
.grid { display:grid; grid-template-columns:repeat(4,1fr); gap:6px; margin-top:4px; }
|
||||
.stat { background:rgba(255,255,255,0.04); border-radius:9px; padding:6px 8px; }
|
||||
.stat .k { color:var(--dim); font-size:10px; text-transform:uppercase; letter-spacing:0.04em; }
|
||||
.stat .v { font-size:16px; font-weight:700; font-variant-numeric:tabular-nums; }
|
||||
.stat .u { color:var(--dim); font-size:10px; font-weight:400; }
|
||||
.jitter-good { color:var(--good); } .jitter-warn { color:var(--warn); } .jitter-bad { color:var(--bad); }
|
||||
|
||||
#markersList { margin-top:6px; font-size:11px; color:var(--dim); min-height:14px; }
|
||||
#markersList b { color:var(--blue); }
|
||||
|
||||
/* bottom controls */
|
||||
#controls { position:fixed; left:10px; right:10px; bottom:calc(10px + env(safe-area-inset-bottom));
|
||||
padding:10px 12px; display:flex; flex-direction:column; gap:8px; }
|
||||
#controls .row { display:flex; gap:8px; align-items:center; }
|
||||
#note { flex:1; background:rgba(255,255,255,0.06); border:1px solid rgba(255,255,255,0.1);
|
||||
color:var(--ink); border-radius:9px; padding:8px 10px; font-size:13px; font-family:inherit; }
|
||||
#note::placeholder { color:var(--dim); }
|
||||
button { appearance:none; border:0; cursor:pointer; font-family:inherit; font-weight:600;
|
||||
border-radius:9px; padding:9px 12px; font-size:13px; }
|
||||
.btn-rec { background:linear-gradient(135deg,var(--red),#ff2678); color:#fff; }
|
||||
.btn-rec.recording { background:linear-gradient(135deg,#2a2f44,#1a1d2b); color:var(--bad);
|
||||
box-shadow:0 0 0 1px var(--bad) inset; }
|
||||
.btn-ghost { background:rgba(255,255,255,0.08); color:var(--ink); }
|
||||
.btn-go { background:linear-gradient(135deg,var(--blue),var(--cyan)); color:#06121f; }
|
||||
.counter { font-variant-numeric:tabular-nums; font-weight:700; color:var(--cyan); min-width:54px; text-align:center; }
|
||||
|
||||
#recBadge { position:fixed; top:calc(8px + env(safe-area-inset-top)); right:14px;
|
||||
display:none; align-items:center; gap:6px; z-index:5; font-size:12px; font-weight:700; color:var(--bad); }
|
||||
#recBadge.show { display:flex; }
|
||||
#recDot { width:9px; height:9px; border-radius:50%; background:var(--bad); animation:pulse 1s infinite; }
|
||||
@keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:0.3;} }
|
||||
|
||||
#start { position:fixed; inset:0; display:flex; flex-direction:column; align-items:center;
|
||||
justify-content:center; gap:18px; text-align:center; padding:24px;
|
||||
background:radial-gradient(circle at 50% 38%,#161a2b,#05060a 70%); }
|
||||
#start h1 { font-size:24px; margin:0; }
|
||||
#start h1 span { background:linear-gradient(90deg,var(--red),var(--yellow),var(--blue));
|
||||
-webkit-background-clip:text; background-clip:text; color:transparent; }
|
||||
#start p { color:var(--dim); max-width:32ch; margin:0; line-height:1.6; font-size:14px; }
|
||||
#err { color:var(--bad); font-size:12.5px; max-width:34ch; }
|
||||
.hidden { display:none !important; }
|
||||
|
||||
/* export modal */
|
||||
#modal { position:fixed; inset:0; background:rgba(2,3,8,0.8); z-index:20;
|
||||
display:none; align-items:center; justify-content:center; padding:18px; }
|
||||
#modal.show { display:flex; }
|
||||
#modal .card { width:100%; max-width:520px; max-height:80vh; padding:16px; display:flex; flex-direction:column; }
|
||||
#modal h2 { margin:0 0 8px; font-size:16px; }
|
||||
#modal .summary { font-size:12.5px; color:var(--dim); line-height:1.6; margin-bottom:10px;
|
||||
white-space:pre-wrap; font-family:ui-monospace,Menlo,Consolas,monospace; background:rgba(255,255,255,0.04);
|
||||
border-radius:8px; padding:10px; overflow:auto; }
|
||||
#modal .row { display:flex; gap:8px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="stage">
|
||||
<video id="video" playsinline muted autoplay></video>
|
||||
<canvas id="overlay"></canvas>
|
||||
</div>
|
||||
|
||||
<div id="recBadge"><span id="recDot"></span>REC <span id="recTime">0.0s</span></div>
|
||||
|
||||
<div id="hud" class="card hidden">
|
||||
<div class="top">
|
||||
<span class="title">Pose jitter</span>
|
||||
<span id="lock" class="tag off">no marker</span>
|
||||
<span style="margin-left:auto;color:var(--dim);font-size:11px">fps <b id="fps" style="color:var(--ink)">0</b></span>
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div class="stat"><div class="k">Pos jitter</div><div class="v"><span id="posJit">—</span><span class="u"> mm</span></div></div>
|
||||
<div class="stat"><div class="k">Ang jitter</div><div class="v"><span id="angJit">—</span><span class="u"> °</span></div></div>
|
||||
<div class="stat"><div class="k">Distance</div><div class="v"><span id="dist">—</span><span class="u"> mm</span></div></div>
|
||||
<div class="stat"><div class="k">View angle</div><div class="v"><span id="ang">—</span><span class="u"> °</span></div></div>
|
||||
</div>
|
||||
<div id="markersList">point at a crest…</div>
|
||||
</div>
|
||||
|
||||
<div id="controls" class="card hidden">
|
||||
<div class="row">
|
||||
<input id="note" type="text" placeholder="label this run (e.g. '1 marker, 30cm, room light)" />
|
||||
</div>
|
||||
<div class="row">
|
||||
<button id="rec" class="btn-rec">● Record</button>
|
||||
<span class="counter" id="sampleCount">0</span>
|
||||
<button id="markPoint" class="btn-ghost" title="tag a moment in the log">Flag</button>
|
||||
<button id="export" class="btn-go" style="margin-left:auto">Export ▼</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modal">
|
||||
<div class="card">
|
||||
<h2>Session results</h2>
|
||||
<div class="summary" id="summary">—</div>
|
||||
<div class="row">
|
||||
<button class="btn-go" id="downloadJson" style="flex:1">Download JSON</button>
|
||||
<button class="btn-ghost" id="copyText" style="flex:1">Copy summary</button>
|
||||
</div>
|
||||
<div class="row" style="margin-top:8px">
|
||||
<button class="btn-ghost" id="closeModal" style="flex:1">Close</button>
|
||||
<button class="btn-rec" id="clearAll" style="flex:1">Clear all runs</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="start">
|
||||
<h1>Newbury <span>jitter meter</span></h1>
|
||||
<p>Hold the phone steady on a crest, hit Record for ~10s, then move closer / further / to a sharper angle and record again. Export and send me the file.</p>
|
||||
<button id="go" class="btn-go" style="padding:14px 30px;border-radius:999px;font-size:16px">Start camera</button>
|
||||
<div id="err"></div>
|
||||
</div>
|
||||
|
||||
<script src="vendor/cv.js"></script>
|
||||
<script src="vendor/svd.js"></script>
|
||||
<script src="vendor/posit1.js"></script>
|
||||
<script src="vendor/aruco.js"></script>
|
||||
<script src="vendor/dictionaries/aruco_4x4_1000.js"></script>
|
||||
<script src="js/jitter.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user