Skip to content
Shiny.Net.HttpServer v1 - A lightweight feature rich HTTP Server - Tunnels, Websockets, AOT, ASPNET Featureset, & Works EVERYWHERE!Let me see!

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.

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.

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.

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 view
<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.

  • 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.