mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2026-02-01 20:10:35 +01:00
zoom fix
This commit is contained in:
parent
5c9e590856
commit
5234c9daa6
@ -191,7 +191,6 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
flex: 1,
|
||||
minHeight: 0,
|
||||
minWidth: 0,
|
||||
@ -287,8 +286,6 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur
|
||||
minHeight: 0,
|
||||
minWidth: 0,
|
||||
contain: 'strict',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Scroller
|
||||
|
||||
@ -119,7 +119,7 @@ export function ZoomAPIBridge() {
|
||||
}
|
||||
|
||||
const fitWidthZoom = zoomState.currentZoomLevel;
|
||||
if (!fitWidthZoom || fitWidthZoom <= 0) {
|
||||
if (!fitWidthZoom || fitWidthZoom <= 0 || fitWidthZoom === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -143,31 +143,19 @@ export function ZoomAPIBridge() {
|
||||
return;
|
||||
}
|
||||
|
||||
const metrics = viewport ?? {};
|
||||
const viewportWidth =
|
||||
metrics.clientWidth ?? metrics.width ?? window.innerWidth ?? 0;
|
||||
const viewportHeight =
|
||||
metrics.clientHeight ?? metrics.height ?? window.innerHeight ?? 0;
|
||||
const viewportWidth = window.innerWidth ?? 0;
|
||||
const viewportHeight = window.innerHeight ?? 0;
|
||||
|
||||
if (viewportWidth <= 0 || viewportHeight <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pageRect = await measureRenderedPageRect({
|
||||
shouldCancel: () => cancelled,
|
||||
});
|
||||
if (cancelled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const decision = determineAutoZoom({
|
||||
viewportWidth,
|
||||
viewportHeight,
|
||||
fitWidthZoom,
|
||||
pagesPerSpread,
|
||||
pageRect: pageRect
|
||||
? { width: pageRect.width, height: pageRect.height }
|
||||
: undefined,
|
||||
pageRect: undefined,
|
||||
metadataAspectRatio: metadataAspectRatio ?? null,
|
||||
visibilityThreshold: DEFAULT_VISIBILITY_THRESHOLD,
|
||||
fallbackZoom: DEFAULT_FALLBACK_ZOOM,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export const DEFAULT_VISIBILITY_THRESHOLD = 80; // Require at least 80% of the page height to be visible
|
||||
export const DEFAULT_VISIBILITY_THRESHOLD = 70; // Require at least 70% of the page height to be visible
|
||||
export const DEFAULT_FALLBACK_ZOOM = 1.44; // 144% fallback when no reliable metadata is present
|
||||
|
||||
export interface ZoomViewport {
|
||||
@ -36,47 +36,48 @@ export function determineAutoZoom({
|
||||
visibilityThreshold = DEFAULT_VISIBILITY_THRESHOLD,
|
||||
fallbackZoom = DEFAULT_FALLBACK_ZOOM,
|
||||
}: AutoZoomParams): AutoZoomDecision {
|
||||
// Get aspect ratio from pageRect or metadata
|
||||
const rectWidth = pageRect?.width ?? 0;
|
||||
const rectHeight = pageRect?.height ?? 0;
|
||||
|
||||
const aspectRatio: number | null =
|
||||
rectWidth > 0 ? rectHeight / rectWidth : metadataAspectRatio ?? null;
|
||||
|
||||
let renderedHeight: number | null = rectHeight > 0 ? rectHeight : null;
|
||||
|
||||
if (!renderedHeight || renderedHeight <= 0) {
|
||||
if (aspectRatio == null || aspectRatio <= 0) {
|
||||
return { type: 'fallback', zoom: Math.min(fitWidthZoom, fallbackZoom) };
|
||||
}
|
||||
|
||||
const pageWidth = viewportWidth / (fitWidthZoom * pagesPerSpread);
|
||||
const pageHeight = pageWidth * aspectRatio;
|
||||
renderedHeight = pageHeight * fitWidthZoom;
|
||||
// Need aspect ratio to proceed
|
||||
if (!aspectRatio || aspectRatio <= 0) {
|
||||
return { type: 'fallback', zoom: Math.min(fitWidthZoom, fallbackZoom) };
|
||||
}
|
||||
|
||||
if (!renderedHeight || renderedHeight <= 0) {
|
||||
return { type: 'fitWidth' };
|
||||
}
|
||||
|
||||
const isLandscape = aspectRatio !== null && aspectRatio < 1;
|
||||
// Landscape pages need 100% visibility, portrait need 80%
|
||||
const isLandscape = aspectRatio < 1;
|
||||
const targetVisibility = isLandscape ? 100 : visibilityThreshold;
|
||||
|
||||
const visiblePercent = (viewportHeight / renderedHeight) * 100;
|
||||
// Step 1: Calculate what zoom level shows targetVisibility% (80%) of page height
|
||||
//
|
||||
// At fitWidth, page dimensions are:
|
||||
// pageHeightAtFitWidth = (viewportWidth / pagesPerSpread) * aspectRatio
|
||||
//
|
||||
// For 80% of page to be visible:
|
||||
// viewportHeight / pageHeightAtZoom = targetVisibility / 100
|
||||
// viewportHeight / (pageHeightAtFitWidth * zoomRatio) = targetVisibility / 100
|
||||
//
|
||||
// Where zoomRatio = heightBasedZoom / fitWidthZoom
|
||||
//
|
||||
// Solving:
|
||||
// heightBasedZoom = fitWidthZoom * viewportHeight / (pageHeightAtFitWidth * targetVisibility / 100)
|
||||
// heightBasedZoom = fitWidthZoom * (viewportHeight / pageHeightAtFitWidth) * (100 / targetVisibility)
|
||||
|
||||
if (visiblePercent >= targetVisibility) {
|
||||
const pageHeightAtFitWidth = (viewportWidth / pagesPerSpread) * aspectRatio;
|
||||
const heightBasedZoom = fitWidthZoom * (viewportHeight / pageHeightAtFitWidth) / (targetVisibility / 100);
|
||||
|
||||
// Step 2: Compare with fitWidth
|
||||
// Use whichever is smaller (more zoomed out) to ensure both constraints are met
|
||||
if (heightBasedZoom < fitWidthZoom) {
|
||||
// Need to zoom out from fitWidth to show enough height
|
||||
return { type: 'adjust', zoom: heightBasedZoom };
|
||||
} else {
|
||||
// fitWidth already shows enough
|
||||
return { type: 'fitWidth' };
|
||||
}
|
||||
|
||||
const allowableHeightRatio = targetVisibility / 100;
|
||||
const zoomScale =
|
||||
viewportHeight / (allowableHeightRatio * renderedHeight);
|
||||
const targetZoom = Math.min(fitWidthZoom, fitWidthZoom * zoomScale);
|
||||
|
||||
if (Math.abs(targetZoom - fitWidthZoom) < 0.001) {
|
||||
return { type: 'fitWidth' };
|
||||
}
|
||||
|
||||
return { type: 'adjust', zoom: targetZoom };
|
||||
}
|
||||
|
||||
export interface MeasurePageRectOptions {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user