added fit to page button for canvas

This commit is contained in:
Kilian Schüttler 2025-03-25 18:13:47 +01:00
parent fcfa06f691
commit 5227c0acea
2 changed files with 58 additions and 31 deletions

View File

@ -1,35 +1,45 @@
<script lang="ts">
import {
ZoomInOutline,
ZoomOutOutline,
RefreshOutline,
} from "flowbite-svelte-icons";
import {
ZoomInOutline,
ZoomOutOutline,
RefreshOutline,
MinimizeOutline
} from 'flowbite-svelte-icons';
let {
scale,
onZoomIn,
onZoomOut,
resetZoom,
}: {
scale: number;
onZoomIn: () => void;
onZoomOut: () => void;
resetZoom: () => void;
} = $props();
let {
scale,
onZoomIn,
onZoomOut,
resetZoom,
fit,
showFit
}: {
scale: number;
onZoomIn: () => void;
onZoomOut: () => void;
resetZoom: () => void;
fit: () => void;
showFit: boolean;
} = $props();
</script>
<div class="controls">
<span class="zoom-level">{(scale * 100).toFixed(0)}%</span>
<button class="control-button" onclick={onZoomIn}>
<ZoomInOutline />
</button>
<button class="control-button" onclick={onZoomOut}>
<ZoomOutOutline />
</button>
<button class="control-button" onclick={resetZoom}>
<RefreshOutline />
</button>
<span class="zoom-level">{(scale * 100).toFixed(0)}%</span>
{#if showFit}
<button class="control-button" onclick={fit}>
<MinimizeOutline />
</button>
{/if}
<button class="control-button" onclick={onZoomIn}>
<ZoomInOutline />
</button>
<button class="control-button" onclick={onZoomOut}>
<ZoomOutOutline />
</button>
<button class="control-button" onclick={resetZoom}>
<RefreshOutline />
</button>
</div>
<style lang="postcss">

View File

@ -1,6 +1,5 @@
<script lang="ts">
import ZoomControls from '../components/ZoomControls.svelte';
import { onMount } from 'svelte';
type ZoomableProps = {
minZoom?: number;
@ -12,7 +11,7 @@
};
let {
minZoom = 0.5,
minZoom = 0.1,
maxZoom = 10,
zoomStep = 0.1,
imgUrl,
@ -21,6 +20,8 @@
}: ZoomableProps = $props();
let currentImgUrl = $state(imgUrl);
let image: HTMLImageElement | undefined = $state(undefined);
let container = $state<HTMLDivElement>();
type ViewState = {
x: number;
@ -35,7 +36,6 @@
});
// DOM refs
let container = $state<HTMLElement>();
// Drag state
type DragState = {
@ -94,6 +94,20 @@
dragState = undefined;
}
function fitCanvasToPage() {
if (!canvas || !container) return;
const w = canvas.width;
const h = canvas.height;
const targetWidth = container.offsetWidth;
const targetHeight = container.offsetHeight;
const wScale = targetWidth / w;
const hScale = targetHeight / h;
viewState.scale = Math.min(maxZoom, Math.max(minZoom, Math.min(wScale, hScale)));
viewState.x = 0;
viewState.y = 0;
}
function resetZoom() {
viewState.scale = 1;
if (container) {
@ -122,9 +136,11 @@
<div class="relative w-full h-full">
<ZoomControls
scale={viewState.scale}
onZoomIn={() => (viewState.scale = Math.min(viewState.scale + zoomStep, maxZoom))}
onZoomOut={() => (viewState.scale = Math.max(viewState.scale - zoomStep, minZoom))}
onZoomIn={() => (viewState.scale = Math.min(viewState.scale + (zoomStep * viewState.scale), maxZoom))}
onZoomOut={() => (viewState.scale = Math.max(viewState.scale - (zoomStep * viewState.scale), minZoom))}
{resetZoom}
fit={fitCanvasToPage}
showFit={!image}
/>
<div
class="container"
@ -140,6 +156,7 @@
{#if imgUrl}
<img
class="zoomimage"
bind:this={image}
alt="rendered-page"
src={currentImgUrl}
style:transform="translate({viewState.x}px, {viewState.y}px) scale({viewState.scale})"