Image Cropping

The ImageToolsManager provides interactive cropping with aspect ratio constraints.

Starting a Crop

// Get a raster item (image on canvas)
const raster = app.imageGroup.children[0];

// Start cropping
app.imageTools.startCrop(raster);

With Aspect Ratio

app.imageTools.startCrop(raster, {
  aspectRatio: '16:9'
});

Available Aspect Ratios:

  • 'free' - No constraint (default)
  • '1:1' - Square
  • '16:9' - Widescreen
  • '9:16' - Vertical video
  • '4:3' - Standard
  • '3:4' - Portrait
  • '3:2' - Classic photo
  • '2:3' - Portrait photo

Crop UI

When cropping is active, the system displays:

  • Semi-transparent overlay over uncropped areas
  • Dashed crop rectangle with rule-of-thirds guides
  • Resize handles at corners and edges

Modifying the Crop

Resize by Handle

// Programmatic handle drag
app.imageTools.updateCrop('se', new Point(300, 400));  // Southeast corner

Handle Names:

  • nw, n, ne - Top handles
  • w, e - Side handles
  • sw, s, se - Bottom handles

Move Crop Area

app.imageTools.moveCrop(new Point(10, 0));  // Move 10px right

Change Aspect Ratio During Crop

app.imageTools.setCropAspectRatio('1:1');

Applying the Crop

const croppedRaster = await app.imageTools.applyCrop();
// Returns the new cropped raster item

Canceling

app.imageTools.cancelCrop();
// Original image is unchanged

Events

window.addEventListener('cropStarted', (e) => {
  console.log('Cropping:', e.detail.raster);
});

window.addEventListener('cropApplied', (e) => {
  console.log('Cropped:', e.detail.raster);
});

window.addEventListener('cropCancelled', () => {
  console.log('Crop cancelled');
});

Crop State

Check if cropping is active:

if (app.imageTools.cropState) {
  console.log('Currently cropping');
  console.log('Crop bounds:', app.imageTools.cropState.cropRect.bounds);
}

Example: Auto-Crop to Square

async function cropToSquare(raster) {
  app.imageTools.startCrop(raster, { aspectRatio: '1:1' });

  // Wait a frame for UI to setup
  await new Promise(r => requestAnimationFrame(r));

  // Apply immediately
  return await app.imageTools.applyCrop();
}