This commit is contained in:
mike
2026-06-28 00:23:48 +02:00
parent 03b754112c
commit 19e0656ccb

View File

@@ -2227,6 +2227,7 @@
// --- HYDRATION_START ---
const PRELOADED_IMAGES = [
"20260628_001216_pad_20260626_035101_pad_20260626_034830_jb.nobg.png",
"20260627_232502_pad_20260626_035101_pad_20260626_034830_jb.nobg.png",
"20260627_232843_pad_20260626_035101_pad_20260626_034830_jb.nobg.png",
"20260627_232526_pad_20260626_035101_pad_20260626_034830_jb.nobg.png",
@@ -6923,16 +6924,24 @@
function getImageDisplayRect(img) {
if (!img || !img.naturalWidth) return null;
// If the image is zoomed, getBoundingClientRect() returns the SCALED dimensions.
// We need to account for this to find the actual visible image area.
const isZoomed = img.classList.contains('zoomed');
const scale = isZoomed ? 2.2 : 1.0;
const rect = img.getBoundingClientRect();
const container = img.parentElement;
const crect = container.getBoundingClientRect();
// The natural aspect ratio
const iw = img.naturalWidth;
const ih = img.naturalHeight;
const cw = rect.width;
const ch = rect.height;
const aspect = iw / ih;
// The container dimensions for the image (before scaling)
const cw = rect.width / scale;
const ch = rect.height / scale;
const caspect = cw / ch;
let dw, dh, dl, dt;
@@ -6948,10 +6957,41 @@
dl = (cw - dw) / 2;
}
// Adjust relative to container if needed, but since img is a flex item
// centered in .studio-viewer, its rect.left/top might already be offset.
// Actually, dl and dt above are relative to the img element's box.
// We want coordinates relative to .studio-viewer.
// Adjust for scale: the visual center stays the same,
// but the width/height and offsets from the top-left change.
if (isZoomed) {
const centerRelX = cw / 2;
const centerRelY = ch / 2;
// dw, dh are unscaled visual dimensions of the content.
// dl, dt are unscaled offsets within the img element's box.
// We want the scaled versions.
dw *= scale;
dh *= scale;
// The top-left of the content relative to the center of the img element:
const contentRelCenterX = dl - centerRelX;
const contentRelCenterY = dt - centerRelY;
// The top-left of the content relative to the center of the img element (scaled):
const contentRelCenterXScaled = contentRelCenterX * scale;
const contentRelCenterYScaled = contentRelCenterY * scale;
// The new offsets relative to the top-left of the scaled img element:
// Actually, rect.left/top are already for the scaled element's bounding box.
// We just need to find where the content starts within that bounding box.
const finalDl = contentRelCenterXScaled + (rect.width / 2);
const finalDt = contentRelCenterYScaled + (rect.height / 2);
return {
left: rect.left - crect.left + finalDl,
top: rect.top - crect.top + finalDt,
width: dw,
height: dh
};
}
const finalLeft = rect.left - crect.left + dl;
const finalTop = rect.top - crect.top + dt;
@@ -7125,23 +7165,20 @@
const fname = lbNames[lbIdx];
if (document.getElementById('poseCanvas')) _removePoseOverlay(); // skeleton is per-image
document.getElementById('poseResults')?.remove();
_fsModelFilename = fname; // keep faceswap/scenery/segment in sync
const isVid = isVideo(fname) || fileContentType[fname] === 'video';
const lbImgEl = document.getElementById('lbImg');
const lbVideoEl = document.getElementById('lbVideo');
lbImgEl.onload = () => {
const dimEl = document.getElementById('lbImgDims');
if (dimEl) dimEl.textContent = `${lbImgEl.naturalWidth} x ${lbImgEl.naturalHeight}`;
// Use requestAnimationFrame to ensure layout has updated before measuring for checkerboard/previews
requestAnimationFrame(() => {
updatePadPreview();
const cb = document.getElementById('sbCheckerboard');
if (cb && cb.checked) toggleCheckerboard(true);
});
// Overlay re-sync is now handled by ResizeObserver
};
_fsModelFilename = fname; // keep faceswap/scenery/segment in sync
const isVid = isVideo(fname) || fileContentType[fname] === 'video';
// Show image dimensions
const dimEl = document.getElementById('lbImgDims');
if (dimEl) {
@@ -7163,6 +7200,10 @@
lbImgEl.style.display = '';
lbImgEl.classList.remove('zoomed');
lbImgEl.src = lbUrls[lbIdx];
// If it's already in cache, onload might not fire or already fired
if (lbImgEl.complete && lbImgEl.naturalWidth) {
lbImgEl.onload();
}
}
const backBtn = document.getElementById('lbBackBtn');
@@ -9878,6 +9919,20 @@
// Initialize
document.addEventListener('DOMContentLoaded', () => {
const img = document.getElementById('lbImg');
if (img) {
const ro = new ResizeObserver(() => {
if (_isStudioOpen()) {
requestAnimationFrame(() => {
updatePadPreview();
const cb = document.getElementById('sbCheckerboard');
if (cb && cb.checked) toggleCheckerboard(true);
});
}
});
ro.observe(img);
}
window.addEventListener('resize', () => {
if (_isStudioOpen()) {
requestAnimationFrame(() => {
@@ -10134,7 +10189,11 @@
}
function toggleImageZoom() {
document.getElementById('lbImg')?.classList.toggle('zoomed');
const img = document.getElementById('lbImg');
if (img) {
img.classList.toggle('zoomed');
// The ResizeObserver will handle the follow-up logic automatically.
}
}
// ---- sidebar panels ----
@@ -11731,7 +11790,7 @@
if (btn) btn.disabled = false;
}
function toggleCheckerboard(on) {
function toggleCheckerboard(on, isRetry=false) {
const viewer = document.getElementById('studioViewer');
const cbLayer = document.getElementById('studioCheckerboard');
const img = document.getElementById('lbImg');