Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions packages/web/assets/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,77 @@ html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
font-size: 0.9rem;
margin-top: 12px;
}

/* PD calibration wizard */
.calibrate-btn {
margin-top: 8px;
width: 100%;
font-size: 12px;
padding: 6px 10px;
border-color: var(--accent2);
color: var(--accent2);
background: #0d1528;
}
.calibrate-btn.active {
background: #1a2744;
border-color: var(--accent);
color: var(--accent);
}
.cal-info {
margin-top: 8px;
padding: 8px 10px;
background: #0d1528;
border: 1px solid var(--line);
border-radius: 8px;
font-size: 11px;
line-height: 1.5;
}
.cal-info.hidden { display: none; }
.cal-info .cal-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 4px;
}
.cal-info .cal-label { color: var(--muted); }
.cal-info .cal-value { color: var(--accent); font-weight: 600; }
.cal-info .cal-hint {
color: var(--muted);
font-size: 10px;
margin-top: 4px;
font-style: italic;
}
.cal-info .cal-actions {
display: flex;
gap: 6px;
margin-top: 8px;
}
.cal-info .cal-actions .btn {
font-size: 10px;
padding: 4px 8px;
flex: 1;
}
/* Calibration card overlay on stage */
#cal-overlay {
position: absolute;
border: 2px dashed var(--accent);
border-radius: 8px;
background: rgba(245,197,24,0.08);
pointer-events: none;
display: none;
z-index: 3;
transition: none;
}
#cal-overlay.visible { display: block; }
#cal-overlay .cal-card-label {
position: absolute;
bottom: -22px;
left: 50%;
transform: translateX(-50%);
font-size: 10px;
color: var(--accent);
background: #000a;
padding: 2px 6px;
border-radius: 4px;
white-space: nowrap;
}
103 changes: 103 additions & 0 deletions packages/web/assets/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ try {
}
let sessionId = null;

// --- PD Calibration Wizard state ---
let calMode = false;
let cardPx = 200; // credit card width in pixels (adjustable)
const CARD_WIDTH_MM = 85.6; // standard ISO/IEC 7810 ID-1 credit card
const CARD_HEIGHT_MM = 54.0;
const CARD_ASPECT = CARD_WIDTH_MM / CARD_HEIGHT_MM;

function isStaticDemo() {
return !!(globalThis.BeeARStatic && globalThis.BeeARStatic.detectStatic());
}
Expand Down Expand Up @@ -856,6 +863,102 @@ function renderGallery() {

// UI element event binding configuration
document.getElementById("btn-cam").onclick = startCamera;

// --- PD Calibration Wizard ---
function measurePdPx() {
const lx = face.left[0] * canvas.width;
const ly = face.left[1] * canvas.height;
const rx = face.right[0] * canvas.width;
const ry = face.right[1] * canvas.height;
return Math.hypot(rx - lx, ry - ly) || 100;
}

function pdToFitScale(frameWidthMm, pdMmVal, pdPxVal) {
const pd = Math.max(50, Math.min(80, Number(pdMmVal) || 64));
const pdPixels = Number(pdPxVal) || 100;
return (Number(frameWidthMm) || 140) / pd * pdPixels * 1.15;
}

function computePdFromCard(cardPxWidth, pupilPx) {
if (!cardPxWidth || cardPxWidth <= 0) return null;
return Math.round(pupilPx / (cardPxWidth / CARD_WIDTH_MM));
}

function toggleCalibration() {
calMode = !calMode;
const btn = document.getElementById("btn-calibrate");
const info = document.getElementById("cal-info");
const overlay = document.getElementById("cal-overlay");
if (calMode) {
btn.classList.add("active");
btn.textContent = "📏 Exit Calibration";
info.classList.remove("hidden");
if (mode === "idle") startDemo();
updateCalInfo();
} else {
btn.classList.remove("active");
btn.textContent = "📏 Calibrate PD";
info.classList.add("hidden");
if (overlay) overlay.classList.remove("visible");
}
}

function updateCalInfo() {
if (!calMode) return;
const pdPx = measurePdPx();
const pxPerMm = cardPx / CARD_WIDTH_MM;
const estimatedPd = computePdFromCard(cardPx, pdPx) || pdMm;
const info = document.getElementById("cal-info");
if (!info) return;
info.innerHTML =
'<div class="cal-row"><span class="cal-label">Card width</span><span class="cal-value">' + cardPx + 'px</span></div>' +
'<div class="cal-row"><span class="cal-label">Scale</span><span class="cal-value">' + pxPerMm.toFixed(2) + ' px/mm</span></div>' +
'<div class="cal-row"><span class="cal-label">PD (pixels)</span><span class="cal-value">' + pdPx.toFixed(0) + 'px</span></div>' +
'<div class="cal-row"><span class="cal-label">Estimated PD</span><span class="cal-value">' + estimatedPd + 'mm</span></div>' +
'<p class="cal-hint">Hold a credit card (85.6×54mm) to your forehead. Adjust the slider until the outline matches your card.</p>' +
'<div class="cal-actions">' +
'<button class="btn primary" id="cal-apply">✅ Apply PD</button>' +
'<button class="btn" id="cal-cancel">✖ Cancel</button>' +
'</div>';
document.getElementById("cal-apply").onclick = function() {
pdMm = Math.max(50, Math.min(80, estimatedPd));
document.getElementById("pd").value = pdMm;
document.getElementById("pd-val").textContent = String(pdMm);
updateMeta();
toggleCalibration();
};
document.getElementById("cal-cancel").onclick = toggleCalibration;
drawCardCalibrationOverlay();
}

function drawCardCalibrationOverlay() {
var overlay = document.getElementById("cal-overlay");
if (!overlay) {
overlay = document.createElement("div");
overlay.id = "cal-overlay";
var lbl = document.createElement("span");
lbl.className = "cal-card-label";
lbl.textContent = "Credit card ref (85.6×54mm)";
overlay.appendChild(lbl);
var stage = document.querySelector(".stage");
if (stage) stage.appendChild(overlay);
}
if (!calMode) { overlay.classList.remove("visible"); return; }
overlay.classList.add("visible");
var stageEl = document.querySelector(".stage");
if (!stageEl) return;
var cRect = canvas.getBoundingClientRect();
var sRect = stageEl.getBoundingClientRect();
var cardH = Math.round(cardPx / CARD_ASPECT);
var midX = (face.left[0] + face.right[0]) / 2 * cRect.width;
var midY = Math.min(face.left[1], face.right[1]) * cRect.height - cardH * 0.8;
overlay.style.left = (cRect.left - sRect.left + midX - cardPx / 2) + "px";
overlay.style.top = (cRect.top - sRect.top + Math.max(0, midY)) + "px";
overlay.style.width = cardPx + "px";
overlay.style.height = cardH + "px";
}

document.getElementById("btn-calibrate").onclick = toggleCalibration;
document.getElementById("btn-demo").onclick = startDemo;
const btnDemoNext = document.getElementById("btn-demo-next");
if (btnDemoNext) btnDemoNext.onclick = nextDemoFace;
Expand Down
2 changes: 2 additions & 0 deletions packages/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ <h2 id="lbl-catalog">Catalog</h2>
<input id="pd" type="range" min="54" max="74" step="1" value="64" />
</label>
<p class="muted small" id="pd-hint">Calibrate pupil distance for better fit scale</p>
<button id="btn-calibrate" class="btn calibrate-btn" type="button">📏 Calibrate PD</button>
<div id="cal-info" class="cal-info hidden"></div>
</div>
<div id="catalog" class="catalog"></div>
<div class="meta" id="meta">Select a SKU</div>
Expand Down