Cropper instance

CropperInstance<E> is a structural type for bind:this and callback arguments. It is not a constructor. FixedCropperInstance<E> adds FixedCropperSettings to the extension. Use a $state binding and $derived reads:

<script lang="ts">
	import { RectangleStencil, Cropper, type CropperInstance } from 'svelte-advanced-cropper';
	import {
		Expand,
		LocateFixed,
		Maximize,
		Minimize2,
		MoveHorizontal,
		MoveVertical
	} from '@lucide/svelte';
	import SquareButton from '#site/demos/shared/SquareButton.svelte';
	import VerticalButtons from '#site/demos/shared/VerticalButtons.svelte';
	import { image } from '#site/paths.ts';

	const src = image('flowers-and-pier.jpg');

	let cropper: CropperInstance | undefined = $state();

	// Scale the stencil, then re-centre it on its previous centre. Each step of the
	// array is applied in turn, and each one respects the cropper's restrictions.
	function resize(widthFactor = 1, heightFactor = 1) {
		const initialCoordinates = cropper?.getCoordinates();
		if (!cropper || !initialCoordinates) {
			return;
		}

		cropper.setCoordinates([
			({ coordinates }) =>
				coordinates && {
					width: coordinates.width * widthFactor,
					height: coordinates.height * heightFactor
				},
			({ coordinates }) =>
				coordinates && {
					left: initialCoordinates.left + (initialCoordinates.width - coordinates.width) / 2,
					top: initialCoordinates.top + (initialCoordinates.height - coordinates.height) / 2
				}
		]);
	}

	function center() {
		cropper?.setCoordinates(
			({ coordinates, imageSize }) =>
				coordinates && {
					left: imageSize.width / 2 - coordinates.width / 2,
					top: imageSize.height / 2 - coordinates.height / 2
				}
		);
	}

	function maximize() {
		cropper?.setCoordinates(({ imageSize }) => imageSize);
	}
</script>

<div class="set-coordinates-example">
	<Cropper bind:this={cropper} class="set-coordinates-example__cropper" {src}>
		<RectangleStencil minAspectRatio={1 / 2} />
	</Cropper>
	<VerticalButtons>
		<SquareButton title="Resize (x2)" onclick={() => resize(2, 2)}><Expand /></SquareButton>
		<SquareButton title="Resize height (x2)" onclick={() => resize(1, 2)}>
			<MoveVertical />
		</SquareButton>
		<SquareButton title="Resize width (x2)" onclick={() => resize(2, 1)}>
			<MoveHorizontal />
		</SquareButton>
		<SquareButton title="Resize (x1/2)" onclick={() => resize(0.5, 0.5)}>
			<Minimize2 />
		</SquareButton>
		<SquareButton title="Maximize" onclick={maximize}><Maximize /></SquareButton>
		<SquareButton title="Center" onclick={center}><LocateFixed /></SquareButton>
	</VerticalButtons>
</div>

<style>
	.set-coordinates-example {
		position: relative;
	}
	:global(.set-coordinates-example__cropper) {
		max-height: 500px;
		background: #354146;
	}
</style>

Reading and changing state

Getters are reactive. Mutation methods and callbacks run untracked. Treat returned observations as read-only; change the crop through methods. A disabled cropper still accepts programmatic actions.

reset() rebuilds from defaults; refresh() measures and reconciles layout. Both are asynchronous. setImage(image) installs a plain displayed-image value without reloading or resetting coordinates. setState accepts a complete state, null, or an updater; it does not accept a partial state.

setCoordinates accepts partial coordinates, functions and sequential arrays. Each function sees the result of earlier transforms. Its extension-aware update type is:

type CoordinateUpdate<E extends SettingsExtension> =
	| Partial<Coordinates>
	| null
	| ((state: CropperState, settings: CropperSettings<E>) => Partial<Coordinates> | null);

getCoordinates() rounds by default; pass { round: false } for fractional values. getStencilCoordinates() uses boundary pixels. getTransforms() returns identity transforms when empty.

Operation options

The core option interfaces have optional boolean fields: TransitionOptions.transitions, ImmediatelyOptions.immediately, InteractionOptions.interaction, NormalizeOptions.normalize and PostprocessOptions.postprocess. Omitted options retain the core method’s behavior. To perform an immediate edit without an animated transition, pass { transitions: false }.

Gesture methods accept boundary-pixel deltas with normalization enabled. Pair moveCoordinates, resizeCoordinates and transformImage with their corresponding end methods for custom interactions. The parameters argument of resizeCoordinates is typed unknown by the core; built-in stencils supply ResizeOptions.

Canvas lifetime

getCanvas(options?: DrawOptions) returns null before readiness, without a usable source, or when canvas export is disabled. The returned canvas is reused by later exports; copy or encode it before another export if you need a snapshot. Rotated-image scratch pixels are released after drawing. The application owns images and object URLs it passes to setImage.

Methods

All 33 public methods are listed below. Optional option objects default to the core’s normal behavior; no argument is needed for observation methods.

reset

reset: () => Promise<void>;

refresh

refresh: () => Promise<void>;

clear

clear: () => void;

setCoordinates

setCoordinates: ( transforms: CoordinateUpdate<E> | CoordinateUpdate<E>[], options?: ImmediatelyOptions & TransitionOptions ) => void;

setState

setState: ( modifier: | CropperState | null | ((state: CropperState | null, settings: CropperSettings<E>) => CropperState | null), options?: TransitionOptions & ImmediatelyOptions & InteractionOptions & PostprocessOptions ) => void;

setImage

setImage: (image: CropperImage) => void;

flipImage

flipImage: (horizontal?: boolean | undefined, vertical?: boolean | undefined, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

zoomImage

zoomImage: (scale: Scale | number, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

rotateImage

rotateImage: (rotate: number | Rotate, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

reconcileState

reconcileState: (options?: TransitionOptions) => void;

moveImage

moveImage: (left: number, top?: number | undefined, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

moveCoordinates

moveCoordinates: (directions: Partial<MoveDirections>, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

moveCoordinatesEnd

moveCoordinatesEnd: (options?: ImmediatelyOptions & TransitionOptions) => void;

resizeCoordinates

resizeCoordinates: (anchor: ResizeAnchor, directions: Partial<MoveDirections>, parameters?: unknown, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

resizeCoordinatesEnd

resizeCoordinatesEnd: (options?: ImmediatelyOptions & TransitionOptions) => void;

transformImage

transformImage: (transform: ImageTransform, options?: InteractionOptions & ImmediatelyOptions & NormalizeOptions & TransitionOptions) => void;

transformImageEnd

transformImageEnd: (options?: ImmediatelyOptions & TransitionOptions) => void;

setVisibleArea

setVisibleArea: (visibleArea: VisibleArea, options?: ImmediatelyOptions & TransitionOptions) => void;

startTransitions

startTransitions: () => void;

hasInteractions

hasInteractions: () => boolean;

getInteractions

getInteractions: () => CropperInteractions;

getCoordinates

getCoordinates: (options?: { round?: boolean }) => Coordinates | null;

getVisibleArea

getVisibleArea: () => VisibleArea | null;

getTransforms

getTransforms: () => Transforms;

getStencilCoordinates

getStencilCoordinates: () => Coordinates;

getDefaultState

getDefaultState: () => CropperState | null;

getCanvas

getCanvas: (options?: DrawOptions) => HTMLCanvasElement | null;

getSettings

getSettings: () => CropperSettings<E>;

getImage

getImage: () => CropperImage | null;

getState

getState: () => CropperState | null;

getTransitions

getTransitions: () => CropperTransitions;

isLoading

isLoading: () => boolean;

isLoaded

isLoaded: () => boolean;