Skip to content
Devix Open Source

Reference

Options, methods and events

Options

The crop

Option Type Default What it does
value Blob | string — A file or a URL to open straight away.
aspect number | [number, number] | null null A shape, a range, or free.
aspects { label, value }[] — Shapes offered as buttons.
mode 'free' | 'fixed' 'free' Crop over a still picture, or a fixed hole with the picture moving under it.
minWidth / minHeight number 16 The smallest the crop may be, in source pixels.
minSourceWidth / minSourceHeight number — Turn away a picture smaller than this.
maxZoom number 8
zoomStep number 0.1 How much a wheel notch moves.
grid boolean true The rule-of-thirds grid while dragging.
rotatable boolean true Show the turn and flip buttons.
preview boolean false A live thumbnail of the output beside the tools.
live boolean false Call onCrop with a fresh picture on every change.

The output

These are the defaults for toBlob, toFile and toDataURL, and every one can be overridden per call.

Option Type Default What it does
maxWidth / maxHeight number — Cap the output. Never enlarges.
width / height number — Force an exact size.
type 'image/png' | 'image/jpeg' | 'image/webp' see below
quality number 0.9 0–1, for JPEG and WebP.
round boolean false Cut the output to an ellipse, transparently.
background string transparent What shows where the picture does not reach.

With no type: a PNG or GIF source stays a PNG, so transparency survives; anything else becomes WebP where the browser can write it, and JPEG where it cannot.

The rest

locale, theme, classNames, strings — as in every Devix widget.

Callbacks

createImageCropper(input, {
  onPick: (file, picker) => {},      // a picture was opened
  onChange: (crop, picker) => {},    // the crop moved; `crop` is in source pixels
  onCrop: (blob, picker) => {},      // a fresh picture, when `live` is on
  onRemove: (picker) => {},
  onError: (message, picker) => {},  // not a picture, or too small
});

Methods

await picker.open(fileOrUrl);
await picker.toBlob(options);
await picker.toFile(name, options);
await picker.toDataURL(options);

picker.getCrop();        // { x, y, width, height } in pixels of the original — or null
picker.setCrop({ x: 0, y: 0, width: 400, height: 400 });
picker.setAspect(16 / 9);
picker.rotate(90);       // or -90
picker.flip('x');        // or 'y'
picker.zoom(1.5);
picker.reset();
picker.clear();
picker.setOptions({ maxWidth: 256 });
picker.destroy();        // gives the page its own input back
picker.input;            // the real <input type="file">
picker.element;          // the widget root

getCrop() returns null until there is a picture and the widget has been laid out — so a cropper built inside a closed modal says nothing rather than 0 × 0.

Events

picker.element.addEventListener('dx:crop', (event) => {
  event.detail.crop;     // { x, y, width, height } in source pixels
  event.detail.width;    // the output size, after maxWidth and friends
  event.detail.height;
});

Words

createImageCropper(input, {
  strings: {
    label: 'أفلت صورة هنا',
    hint: 'أو اخترها',
    selection: 'منطقة القص',
    zoom: 'تكبير',
    rotateLeft: 'تدوير لليسار',
    rotateRight: 'تدوير لليمين',
    reset: 'إعادة',
    remove: 'إزالة',
    notAnImage: 'هذا ليس ملف صورة',
    size: (w, h) => `${w} × ${h}`,
    position: (x, y, w, h) => `${w} في ${h}، عند ${x}، ${y}`,
  },
});

RTL needs nothing else: the layout is written in logical properties, so dir="rtl" mirrors it.

Updated 12 Sep 2026