功能增加
This commit is contained in:
1 parent
b340fc7ad7
commit
f1993eb388
69 files changed
+2243
-162
No files matched your search
@@ -0,0 +1,39 @@
|
||||
export type CanvasSize = { width: number; height: number };
|
||||
export type CanvasView = { zoom: number; x: number; y: number };
|
||||
export type CanvasPosition = { x: number; y: number };
|
||||
export const MIN_CANVAS_ZOOM = 0.25;
|
||||
export const MAX_CANVAS_ZOOM = 8;
|
||||
export const FIT_CANVAS_VIEW: CanvasView = { zoom: 1, x: 0, y: 0 };
|
||||
|
||||
export function fitCanvasImage(image: CanvasSize, viewport: CanvasSize): CanvasSize {
|
||||
if (image.width <= 0 || image.height <= 0 || viewport.width <= 0 || viewport.height <= 0) return { width: 0, height: 0 };
|
||||
const scale = Math.min(Math.max(1, viewport.width - 20) / image.width, Math.max(1, viewport.height - 20) / image.height);
|
||||
return { width: image.width * scale, height: image.height * scale };
|
||||
}
|
||||
|
||||
export function constrainCanvasView(view: CanvasView, fittedImage: CanvasSize, viewport: CanvasSize): CanvasView {
|
||||
const zoom = Math.max(MIN_CANVAS_ZOOM, Math.min(MAX_CANVAS_ZOOM, Number.isFinite(view.zoom) ? view.zoom : 1));
|
||||
const maxX = Math.max(0, (fittedImage.width * zoom - viewport.width) / 2);
|
||||
const maxY = Math.max(0, (fittedImage.height * zoom - viewport.height) / 2);
|
||||
return {
|
||||
zoom,
|
||||
x: Math.max(-maxX, Math.min(maxX, Number.isFinite(view.x) ? view.x : 0)),
|
||||
y: Math.max(-maxY, Math.min(maxY, Number.isFinite(view.y) ? view.y : 0))
|
||||
};
|
||||
}
|
||||
|
||||
// The anchor is relative to the viewport center. Preserve the image point
|
||||
// under the cursor when zooming, except where an image edge limits panning.
|
||||
export function zoomCanvasAt(view: CanvasView, requestedZoom: number, anchor: CanvasPosition, fittedImage: CanvasSize, viewport: CanvasSize): CanvasView {
|
||||
const zoom = Math.max(MIN_CANVAS_ZOOM, Math.min(MAX_CANVAS_ZOOM, requestedZoom));
|
||||
const factor = zoom / view.zoom;
|
||||
return constrainCanvasView({ zoom, x: anchor.x - (anchor.x - view.x) * factor, y: anchor.y - (anchor.y - view.y) * factor }, fittedImage, viewport);
|
||||
}
|
||||
|
||||
// Use the *transformed image bounds*, never the clipped viewport bounds.
|
||||
// Persisted annotations and provider prompts remain in the 0–1000 space.
|
||||
export function canvasAnnotationPoint(point: CanvasPosition, bounds: CanvasSize & { left: number; top: number }): CanvasPosition | null {
|
||||
if (bounds.width <= 0 || bounds.height <= 0) return null;
|
||||
const clamp = (value: number) => Math.max(0, Math.min(1000, Math.round(value)));
|
||||
return { x: clamp((point.x - bounds.left) / bounds.width * 1000), y: clamp((point.y - bounds.top) / bounds.height * 1000) };
|
||||
}
|
||||
Reference in new issue
Block a user