ImageEditor | Zoom & Pan
Zoom is what turns the editor from “draw a big red circle on it” into something you can make a precise correction with. It stays live in every tool: magnify to 8x and the draw, line, arrow, text and crop tools all keep working at that magnification.
How it works
Section titled “How it works”The zoom is a transform applied to the drawing surface, not to the native view. Two things follow from that:
- The image and every annotation are re-rendered at the zoomed scale rather than being a magnified bitmap, so edges stay crisp all the way in.
- Every touch point is mapped back through the transform before any tool math runs, so a stroke drawn at 400% lands exactly where the finger was, at 1/4 of the on-screen size in image terms.
Zoom is view state. It is never baked into the exported image, and Reset() returns to fit-to-view along with clearing edits.
Gestures
Section titled “Gestures”| Gesture | Result |
|---|---|
| Pinch (two fingers) | Zoom about the midpoint between the fingers — works in every tool |
| Two-finger drag | Pan — works in every tool, including mid-annotation |
| One-finger drag in Move mode | Pan when zoomed in |
| Double-tap | Toggle between fit-to-view and 2.5x, anchored on the tap |
| Mouse wheel (Blazor) | Zoom about the cursor |
| Middle-button drag (Blazor) | Pan in every tool |
A second finger arriving mid-stroke turns the gesture into a zoom and discards the partial stroke rather than committing a stray mark.
In crop mode, dragging inside the crop box moves it and dragging a handle resizes it — dragging anywhere outside the box pans the image instead.
Toolbar controls
Section titled “Toolbar controls”The default toolbar carries a zoom cluster: zoom out, a live percentage readout, zoom in, and fit-to-view. Tapping the percentage itself returns to fit. Hide the cluster with ShowZoomControls="False" — keep it on for desktop, where there is no pinch gesture.
<shiny:ImageEditor Source="{Binding ImageSource}" AllowZoom="True" ZoomLevel="{Binding ZoomLevel}" MinZoom="1" MaxZoom="8" ShowZoomControls="True" />ZoomLevel is two-way: read it to show your own indicator, write it to zoom from code. ZoomChanged fires for gestures and code alike.
editor.ZoomIn();editor.ZoomOut();editor.ZoomToFit();editor.ZoomLevel = 4; // 400%, anchored on the centre of the viewBlazor
Section titled “Blazor”<ImageEditor @ref="editor" Source="@url" AllowZoom="true" MaxZoom="8" ShowZoomControls="true" ZoomLevelChanged="v => zoom = v" />
<p>Zoom: @(Math.Round(zoom * 100))%</p>
@code { ImageEditor? editor; double zoom = 1;
Task ZoomTo400() => editor!.SetZoomAsync(4).AsTask();}The canvas owns the wheel while AllowZoom is on, so scrolling over the editor zooms rather than scrolling the page. Set AllowZoom="false" if the editor sits inside a scrolling document and you would rather keep the page scroll.
Details worth knowing
Section titled “Details worth knowing”- Pan is clamped. While the image is smaller than the view it stays centred; once zooming makes it larger it edge-locks, so the image can never be lost off-screen.
- Chrome does not scale. Crop handles, hairlines and the image border keep a constant on-screen size at any zoom, and the crop hit-targets shrink in image space to match — grabbing a handle feels the same at 100% and 800%.
- Entering crop returns to fit-to-view. The crop rect is normalised against the whole image, so it needs the whole image visible. Every other tool keeps the zoom you set up.
- Annotations are resolution-independent. Strokes, lines and text record the on-screen image width they were captured at, so a pen stroke made while zoomed in keeps its proportions when the image is exported at full resolution.


