fix(vwb): image plein écran — calcul dimensions JS explicite (fix définitif)
Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 12s
security-audit / pip-audit (CVE dépendances) (push) Successful in 11s
security-audit / Scan secrets (grep) (push) Successful in 9s
tests / Lint (ruff + black) (push) Successful in 14s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped
Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 12s
security-audit / pip-audit (CVE dépendances) (push) Successful in 11s
security-audit / Scan secrets (grep) (push) Successful in 9s
tests / Lint (ruff + black) (push) Successful in 14s
tests / Tests unitaires (sans GPU) (push) Failing after 14s
tests / Tests sécurité (critique) (push) Has been skipped
Cause racine : max-width/max-height CSS ne font pas GRANDIR une image. Fix : calcul explicite width/height en JS via Math.min(ratio). min-height:0 sur le conteneur flex. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -412,6 +412,11 @@ function FullscreenSelector({
|
||||
// Scale de l'image affichee par rapport a l'image naturelle
|
||||
const [imageScale, setImageScale] = useState({ x: 1, y: 1 });
|
||||
|
||||
// Dimensions explicites de l'image (calculees pour remplir le conteneur en contain)
|
||||
// Resout le bug "timbre poste" : max-width/max-height seuls ne font PAS grandir
|
||||
// une image plus petite que le conteneur. On calcule la taille explicitement.
|
||||
const [imgDisplaySize, setImgDisplaySize] = useState<{ width: number; height: number } | null>(null);
|
||||
|
||||
// ── Detection automatique des elements UI ──
|
||||
useEffect(() => {
|
||||
const runDetection = async () => {
|
||||
@@ -433,24 +438,46 @@ function FullscreenSelector({
|
||||
runDetection();
|
||||
}, [capture.screenshot_base64]);
|
||||
|
||||
// ── Calcul de imageRect et imageScale ──
|
||||
// ── Calcul des dimensions image + imageRect + imageScale ──
|
||||
// Appele au chargement de l'image ET au redimensionnement de la fenetre.
|
||||
// Calcule la taille "contain" (remplir le conteneur en gardant le ratio)
|
||||
// et l'applique comme width/height explicite sur l'img.
|
||||
const recalcImageRect = useCallback(() => {
|
||||
if (!imgRef.current || !contentRef.current) return;
|
||||
|
||||
const containerRect = contentRef.current.getBoundingClientRect();
|
||||
const imgBounds = imgRef.current.getBoundingClientRect();
|
||||
const natW = imgRef.current.naturalWidth;
|
||||
const natH = imgRef.current.naturalHeight;
|
||||
|
||||
setImageRect({
|
||||
left: imgBounds.left - containerRect.left,
|
||||
top: imgBounds.top - containerRect.top,
|
||||
width: imgBounds.width,
|
||||
height: imgBounds.height,
|
||||
});
|
||||
if (natW > 0 && natH > 0) {
|
||||
// Calcul "contain" : ratio le plus contraignant
|
||||
const scale = Math.min(
|
||||
containerRect.width / natW,
|
||||
containerRect.height / natH
|
||||
);
|
||||
const displayW = Math.round(natW * scale);
|
||||
const displayH = Math.round(natH * scale);
|
||||
setImgDisplaySize({ width: displayW, height: displayH });
|
||||
}
|
||||
|
||||
setImageScale({
|
||||
x: imgBounds.width / imgRef.current.naturalWidth,
|
||||
y: imgBounds.height / imgRef.current.naturalHeight,
|
||||
// Apres le render avec les nouvelles dimensions, recalculer imageRect
|
||||
// On utilise requestAnimationFrame pour lire le layout apres le paint
|
||||
requestAnimationFrame(() => {
|
||||
if (!imgRef.current || !contentRef.current) return;
|
||||
const cRect = contentRef.current.getBoundingClientRect();
|
||||
const imgBounds = imgRef.current.getBoundingClientRect();
|
||||
|
||||
setImageRect({
|
||||
left: imgBounds.left - cRect.left,
|
||||
top: imgBounds.top - cRect.top,
|
||||
width: imgBounds.width,
|
||||
height: imgBounds.height,
|
||||
});
|
||||
|
||||
setImageScale({
|
||||
x: imgBounds.width / imgRef.current.naturalWidth,
|
||||
y: imgBounds.height / imgRef.current.naturalHeight,
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -601,7 +628,7 @@ function FullscreenSelector({
|
||||
<button onClick={onClose}>Fermer (Echap)</button>
|
||||
</div>
|
||||
|
||||
{/* Zone de contenu : flex center, l'image se dimensionne via max-width/max-height */}
|
||||
{/* Zone de contenu : flex center, l'image se dimensionne via imgDisplaySize (contain calcule en JS) */}
|
||||
<div
|
||||
className="fullscreen-content"
|
||||
ref={contentRef}
|
||||
@@ -615,7 +642,13 @@ function FullscreenSelector({
|
||||
alt="Capture plein ecran"
|
||||
draggable={false}
|
||||
onLoad={handleImageLoad}
|
||||
style={{ maxWidth: '100%', maxHeight: 'calc(100vh - 70px)', objectFit: 'contain' }}
|
||||
style={imgDisplaySize ? {
|
||||
width: imgDisplaySize.width,
|
||||
height: imgDisplaySize.height,
|
||||
} : {
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Overlay : positionne exactement sur l'image via imageRect.
|
||||
|
||||
@@ -1085,12 +1085,17 @@ body {
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
/* min-height: 0 — indispensable pour que flex:1 fonctionne dans un
|
||||
conteneur flex column. Sans ca, min-height:auto empeche le conteneur
|
||||
de se dimensionner correctement et l'image reste minuscule. */
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.fullscreen-content img {
|
||||
max-width: 100%;
|
||||
max-height: calc(100vh - 70px);
|
||||
object-fit: contain;
|
||||
/* Les dimensions width/height sont calculees en JS (contain manuel)
|
||||
pour garantir que l'image remplit le conteneur quel que soit sa
|
||||
taille naturelle (y compris thumbnails 320x240 de la bibliotheque). */
|
||||
display: block;
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user