fix(report): cap dimension scores and match zoom crops to thumbnails

This commit is contained in:
xsl
2026-10-15 20:17:07 +08:00
parent 482fb4280d
commit 5632ac43d7
13 changed files with 91 additions and 24 deletions
+26 -2
View File
@@ -1300,7 +1300,7 @@
el.classList.toggle('dim-bad', has && rank === 'worst');
box.classList.toggle('worst', has && rank === 'worst');
box.classList.toggle('best', has && rank === 'best');
box.querySelector('.dim-bar i').style.width = has ? Math.max(0, Math.min(100, dim.S * 10)) + '%' : '0';
box.querySelector('.dim-bar i').style.width = has ? Math.max(0, SkinScore.capDimensionScore(dim.S) * 10) + '%' : '0';
}
function setCat(key, cat) {
@@ -1733,6 +1733,30 @@
});
/* ─── 报告页:每张维度卡各自的子 Tab;点检测图放大,再点返回 ─── */
function reportZoomSource(img, frame) {
// Bake the thumbnail's CSS zoom/translation and clipping into the large
// image. Annotations are already composited with their own photograph.
try {
var box=img.getBoundingClientRect(), windowBox=frame.getBoundingClientRect();
if (!img.naturalWidth || !box.width || !windowBox.width || !windowBox.height) return img.src;
var style=getComputedStyle(img), scaleX=box.width/img.naturalWidth, scaleY=box.height/img.naturalHeight;
if (style.objectFit==='cover' || style.objectFit==='contain') {
scaleX=scaleY=style.objectFit==='cover' ? Math.max(scaleX,scaleY) : Math.min(scaleX,scaleY);
}
var width=img.naturalWidth*scaleX, height=img.naturalHeight*scaleY;
var position=style.objectPosition.split(' ');
var px=position[0].endsWith('%') ? parseFloat(position[0])/100 : .5;
var py=position[1] && position[1].endsWith('%') ? parseFloat(position[1])/100 : .5;
var ratio=Math.min(4,1600/Math.max(windowBox.width,windowBox.height));
var cv=document.createElement('canvas');
cv.width=Math.round(windowBox.width*ratio);cv.height=Math.round(windowBox.height*ratio);
var ctx=cv.getContext('2d');
ctx.fillStyle=getComputedStyle(frame).backgroundColor;ctx.fillRect(0,0,cv.width,cv.height);
ctx.drawImage(img,(box.left-windowBox.left+(box.width-width)*px)*ratio,
(box.top-windowBox.top+(box.height-height)*py)*ratio,width*ratio,height*ratio);
return cv.toDataURL('image/jpeg',.95);
} catch (_) { return img.src; }
}
document.querySelectorAll('.card-detail').forEach(function (card, group) {
card.querySelector('.detail-tabs').setAttribute('role', 'tablist');
var tabs = Array.from(card.querySelectorAll('.dtab')), panels = Array.from(card.querySelectorAll('.dpanel'));
@@ -1781,7 +1805,7 @@
var sideButton = e.target.closest('.contour-side-photo, .wrinkle-side-photo');
var img = sideButton ? sideButton.querySelector('img') : e.target.closest('.ditem-img');
if (img && img.src && !img.hidden && img.closest('.dpanel').classList.contains('active')) {
$('#zoom-img').src = img.src;
$('#zoom-img').src = reportZoomSource(img, sideButton || img.closest('.viz-frame'));
openOverlay('p-zoom');
history.pushState({ screen: currentScreen, overlay: 'p-zoom' }, '');
}