Search Docs
Loading...
Skip to content

Force Crop

Enforce specific aspect ratios or fixed dimensions on design blocks using the force crop API.

Force crop applied in the photo editor

5 mins
estimated time
GitHub

Overview#

Force cropping ensures that a page or any croppable block uses a specific aspect ratio or fixed size when the editor loads. We send an .applyForceCrop event through the editor’s event handler, providing the target design block, an array of ForceCropPreset candidates, and a ForceCropMode.

TypePurpose
ForceCropPresetIdentifies a crop preset by source ID and preset ID
ForceCropModeControls crop UI behavior: .silent, .always, or .ifNeeded

When multiple candidates are provided, the system automatically selects the best match based on the block’s current dimensions.

Setting Up Force Crop#

In the onLoaded callback, we get the current page and send the force crop event with preset candidates from the default ly.img.crop.presets asset source, which is registered by addDefaultAssetSources.

builder.onLoaded { context, existing in
guard let page = try context.engine.scene.getCurrentPage() else { return }
let sourceID = Engine.DefaultAssetSource.cropPresets.rawValue
context.eventHandler.send(.applyForceCrop(
to: page,
with: [
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-1-1"),
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-16-9"),
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-9-16"),
],
mode: .ifNeeded,
))
try await existing()
}

Applying Force Crop#

We send the .applyForceCrop event with the page, preset candidates, and mode. The event can be fired outside onLoaded as well — at any appropriate time in your business logic, but not in onCreate.

context.eventHandler.send(.applyForceCrop(
to: page,
with: [
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-1-1"),
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-16-9"),
ForceCropPreset(sourceID: sourceID, presetID: "aspect-ratio-9-16"),
],
mode: .ifNeeded,
))

Understanding Crop Modes#

The ForceCropMode parameter controls how the editor responds after applying a crop preset.

ModeBehavior
.silentApplies the crop without opening the crop UI.
.alwaysApplies the crop and opens the crop sheet immediately.
.ifNeededCompares the preset with the current frame dimensions. The crop is applied and the sheet opens only if the ratio/size differs materially.

Isolating Presets#

To ensure the user only sees the enforced preset, we recreate the asset source in the onLoaded callback:

let sourceID = Engine.DefaultAssetSource.cropPresets.rawValue
try context.engine.asset.removeSource(sourceID: sourceID)
try context.engine.asset.addLocalSource(sourceID: sourceID)
try context.engine.asset.addAsset(to: sourceID, asset: myCustomPreset)

Next Steps#