@bensitu/image-editor 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +235 -81
- package/dist/cjs/index.cjs +2969 -747
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/annotation/annotation-lock.js +7 -0
- package/dist/esm/annotation/annotation-lock.js.map +1 -0
- package/dist/esm/annotation/annotation-manager.js +217 -0
- package/dist/esm/annotation/annotation-manager.js.map +1 -0
- package/dist/esm/annotation/annotation-style.js +50 -0
- package/dist/esm/annotation/annotation-style.js.map +1 -0
- package/dist/esm/annotation/draw-controller.js +114 -0
- package/dist/esm/annotation/draw-controller.js.map +1 -0
- package/dist/esm/annotation/text-controller.js +234 -0
- package/dist/esm/annotation/text-controller.js.map +1 -0
- package/dist/esm/core/default-options.js +232 -3
- package/dist/esm/core/default-options.js.map +1 -1
- package/dist/esm/core/editor-object-kind.js +37 -0
- package/dist/esm/core/editor-object-kind.js.map +1 -0
- package/dist/esm/core/errors.js +19 -0
- package/dist/esm/core/errors.js.map +1 -1
- package/dist/esm/core/layer-order.js +100 -0
- package/dist/esm/core/layer-order.js.map +1 -0
- package/dist/esm/core/public-types.js +34 -1
- package/dist/esm/core/public-types.js.map +1 -1
- package/dist/esm/core/state-serializer.js +104 -24
- package/dist/esm/core/state-serializer.js.map +1 -1
- package/dist/esm/crop/crop-controller.js +2 -0
- package/dist/esm/crop/crop-controller.js.map +1 -1
- package/dist/esm/export/export-format.js.map +1 -1
- package/dist/esm/export/export-service.js +123 -135
- package/dist/esm/export/export-service.js.map +1 -1
- package/dist/esm/export/overlay-merge-service.js +75 -0
- package/dist/esm/export/overlay-merge-service.js.map +1 -0
- package/dist/esm/history/history-manager.js +2 -2
- package/dist/esm/history/history-manager.js.map +1 -1
- package/dist/esm/image/image-loader.js +18 -49
- package/dist/esm/image/image-loader.js.map +1 -1
- package/dist/esm/image/transform-controller.js.map +1 -1
- package/dist/esm/image-editor.js +1063 -60
- package/dist/esm/image-editor.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/mask/mask-factory.js +39 -14
- package/dist/esm/mask/mask-factory.js.map +1 -1
- package/dist/esm/mask/mask-label-manager.js +2 -0
- package/dist/esm/mask/mask-label-manager.js.map +1 -1
- package/dist/esm/mask/mask-list.js.map +1 -1
- package/dist/esm/mask/mask-style.js.map +1 -1
- package/dist/esm/mosaic/mosaic-controller.js +24 -28
- package/dist/esm/mosaic/mosaic-controller.js.map +1 -1
- package/dist/esm/utils/image-element-loader.js +55 -0
- package/dist/esm/utils/image-element-loader.js.map +1 -0
- package/dist/esm/utils/pointer.js +28 -0
- package/dist/esm/utils/pointer.js.map +1 -0
- package/dist/types/annotation/annotation-lock.d.ts +12 -0
- package/dist/types/annotation/annotation-lock.d.ts.map +1 -0
- package/dist/types/annotation/annotation-manager.d.ts +33 -0
- package/dist/types/annotation/annotation-manager.d.ts.map +1 -0
- package/dist/types/annotation/annotation-style.d.ts +13 -0
- package/dist/types/annotation/annotation-style.d.ts.map +1 -0
- package/dist/types/annotation/draw-controller.d.ts +43 -0
- package/dist/types/annotation/draw-controller.d.ts.map +1 -0
- package/dist/types/annotation/text-controller.d.ts +47 -0
- package/dist/types/annotation/text-controller.d.ts.map +1 -0
- package/dist/types/core/default-options.d.ts +14 -2
- package/dist/types/core/default-options.d.ts.map +1 -1
- package/dist/types/core/editor-object-kind.d.ts +29 -0
- package/dist/types/core/editor-object-kind.d.ts.map +1 -0
- package/dist/types/core/errors.d.ts +11 -1
- package/dist/types/core/errors.d.ts.map +1 -1
- package/dist/types/core/layer-order.d.ts +21 -0
- package/dist/types/core/layer-order.d.ts.map +1 -0
- package/dist/types/core/public-types.d.ts +222 -24
- package/dist/types/core/public-types.d.ts.map +1 -1
- package/dist/types/core/state-serializer.d.ts +30 -5
- package/dist/types/core/state-serializer.d.ts.map +1 -1
- package/dist/types/crop/crop-controller.d.ts +6 -7
- package/dist/types/crop/crop-controller.d.ts.map +1 -1
- package/dist/types/export/export-format.d.ts +5 -33
- package/dist/types/export/export-format.d.ts.map +1 -1
- package/dist/types/export/export-service.d.ts +24 -15
- package/dist/types/export/export-service.d.ts.map +1 -1
- package/dist/types/export/overlay-merge-service.d.ts +38 -0
- package/dist/types/export/overlay-merge-service.d.ts.map +1 -0
- package/dist/types/history/history-manager.d.ts +11 -14
- package/dist/types/history/history-manager.d.ts.map +1 -1
- package/dist/types/image/image-loader.d.ts +22 -17
- package/dist/types/image/image-loader.d.ts.map +1 -1
- package/dist/types/image/image-resampler.d.ts +1 -1
- package/dist/types/image/transform-controller.d.ts +5 -7
- package/dist/types/image/transform-controller.d.ts.map +1 -1
- package/dist/types/image-editor.d.ts +75 -7
- package/dist/types/image-editor.d.ts.map +1 -1
- package/dist/types/index.d.cts +3 -3
- package/dist/types/index.d.cts.map +1 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/mask/mask-factory.d.ts.map +1 -1
- package/dist/types/mask/mask-label-manager.d.ts +10 -9
- package/dist/types/mask/mask-label-manager.d.ts.map +1 -1
- package/dist/types/mask/mask-list.d.ts +11 -12
- package/dist/types/mask/mask-list.d.ts.map +1 -1
- package/dist/types/mask/mask-style.d.ts +19 -20
- package/dist/types/mask/mask-style.d.ts.map +1 -1
- package/dist/types/mosaic/mosaic-controller.d.ts +3 -3
- package/dist/types/mosaic/mosaic-controller.d.ts.map +1 -1
- package/dist/types/ui/visibility-state.d.ts +2 -2
- package/dist/types/utils/image-element-loader.d.ts +19 -0
- package/dist/types/utils/image-element-loader.d.ts.map +1 -0
- package/dist/types/utils/pointer.d.ts +16 -0
- package/dist/types/utils/pointer.d.ts.map +1 -0
- package/dist/umd/image-editor.umd.js +1 -1
- package/dist/umd/image-editor.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
A lightweight, TypeScript-first canvas image editor built on top of
|
|
8
8
|
[Fabric.js](https://fabricjs.com/) v7. `ImageEditor` wraps a Fabric canvas
|
|
9
|
-
with image loading, scale and rotation, mask creation,
|
|
10
|
-
(undo/redo),
|
|
9
|
+
with image loading, scale and rotation, mask creation, Text and Draw
|
|
10
|
+
annotations, crop, Mosaic mode, history (undo/redo), layer operations, and
|
|
11
|
+
base64/file export — exposed as a single canonical class
|
|
11
12
|
with a stable public surface.
|
|
12
13
|
|
|
13
14
|
## Demo
|
|
@@ -30,8 +31,13 @@ with a stable public surface.
|
|
|
30
31
|
- Crop session with mask preservation toggle and atomic apply/cancel
|
|
31
32
|
- Mosaic mode with circular brush preview, runtime brush/block controls, and
|
|
32
33
|
one undo step per successful pixelation click
|
|
34
|
+
- Unified editor-owned object model for base images, masks, annotations, and
|
|
35
|
+
session overlays
|
|
36
|
+
- Text annotations, Draw mode, annotation update/delete APIs, and layer
|
|
37
|
+
operations
|
|
33
38
|
- Base64 and `File` exports with PNG/JPEG/WebP support, configurable
|
|
34
|
-
multiplier,
|
|
39
|
+
multiplier, independent mask/annotation rendering toggles, and state-mutating
|
|
40
|
+
mask/annotation merge APIs
|
|
35
41
|
|
|
36
42
|
## Requirements
|
|
37
43
|
|
|
@@ -127,6 +133,26 @@ resolve to `undefined`.
|
|
|
127
133
|
<button id="createMaskButton">Add Mask</button>
|
|
128
134
|
<button id="removeSelectedMaskButton">Remove Mask</button>
|
|
129
135
|
<button id="removeAllMasksButton">Remove All Masks</button>
|
|
136
|
+
<ul id="maskList"></ul>
|
|
137
|
+
|
|
138
|
+
<button id="enterTextModeButton">Text</button>
|
|
139
|
+
<button id="exitTextModeButton">Exit Text</button>
|
|
140
|
+
<input id="textColorInput" type="color" value="#ff0000" />
|
|
141
|
+
<input id="textFontSizeInput" type="number" min="8" max="160" value="32" />
|
|
142
|
+
|
|
143
|
+
<button id="enterDrawModeButton">Draw</button>
|
|
144
|
+
<button id="exitDrawModeButton">Exit Draw</button>
|
|
145
|
+
<input id="drawColorInput" type="color" value="#ff0000" />
|
|
146
|
+
<input id="drawBrushSizeInput" type="range" min="1" max="80" value="8" />
|
|
147
|
+
|
|
148
|
+
<button id="removeSelectedAnnotationButton">Remove Annotation</button>
|
|
149
|
+
<button id="removeAllAnnotationsButton">Remove All Annotations</button>
|
|
150
|
+
<button id="deleteSelectedObjectButton">Delete Selected</button>
|
|
151
|
+
<button id="bringSelectedObjectForwardButton">Forward</button>
|
|
152
|
+
<button id="sendSelectedObjectBackwardButton">Backward</button>
|
|
153
|
+
<button id="bringSelectedObjectToFrontButton">Front</button>
|
|
154
|
+
<button id="sendSelectedObjectToBackButton">Back</button>
|
|
155
|
+
<ul id="annotationList"></ul>
|
|
130
156
|
|
|
131
157
|
<button id="enterCropModeButton">Crop</button>
|
|
132
158
|
<button id="applyCropButton">Apply Crop</button>
|
|
@@ -143,14 +169,14 @@ resolve to `undefined`.
|
|
|
143
169
|
<input id="mosaicBlockSizeInput" type="range" min="2" max="40" step="1" value="8" />
|
|
144
170
|
</label>
|
|
145
171
|
|
|
146
|
-
<button id="mergeMasksButton">Merge</button>
|
|
172
|
+
<button id="mergeMasksButton">Merge Masks</button>
|
|
173
|
+
<button id="mergeAnnotationsButton">Merge Annotations</button>
|
|
147
174
|
<button id="downloadImageButton">Download</button>
|
|
148
175
|
<button id="undoButton">Undo</button>
|
|
149
176
|
<button id="redoButton">Redo</button>
|
|
150
177
|
<button id="resetImageTransformButton">Reset</button>
|
|
151
178
|
|
|
152
179
|
<input id="imageInput" type="file" accept="image/*" />
|
|
153
|
-
<ul id="maskList"></ul>
|
|
154
180
|
```
|
|
155
181
|
|
|
156
182
|
### TypeScript / ESM
|
|
@@ -168,6 +194,14 @@ const editor = new ImageEditor(fabric, {
|
|
|
168
194
|
brushSize: 48,
|
|
169
195
|
blockSize: 8,
|
|
170
196
|
},
|
|
197
|
+
defaultTextConfig: {
|
|
198
|
+
fill: '#ff0000',
|
|
199
|
+
fontSize: 32,
|
|
200
|
+
},
|
|
201
|
+
defaultDrawConfig: {
|
|
202
|
+
color: '#ff0000',
|
|
203
|
+
brushSize: 8,
|
|
204
|
+
},
|
|
171
205
|
} satisfies ImageEditorOptions);
|
|
172
206
|
|
|
173
207
|
editor.init({
|
|
@@ -181,6 +215,7 @@ editor.init({
|
|
|
181
215
|
createMaskButton: 'createMaskButton',
|
|
182
216
|
removeSelectedMaskButton: 'removeSelectedMaskButton',
|
|
183
217
|
removeAllMasksButton: 'removeAllMasksButton',
|
|
218
|
+
maskList: 'maskList',
|
|
184
219
|
enterCropModeButton: 'enterCropModeButton',
|
|
185
220
|
applyCropButton: 'applyCropButton',
|
|
186
221
|
cancelCropButton: 'cancelCropButton',
|
|
@@ -188,13 +223,29 @@ editor.init({
|
|
|
188
223
|
exitMosaicModeButton: 'exitMosaicModeButton',
|
|
189
224
|
mosaicBrushSizeInput: 'mosaicBrushSizeInput',
|
|
190
225
|
mosaicBlockSizeInput: 'mosaicBlockSizeInput',
|
|
226
|
+
enterTextModeButton: 'enterTextModeButton',
|
|
227
|
+
exitTextModeButton: 'exitTextModeButton',
|
|
228
|
+
textColorInput: 'textColorInput',
|
|
229
|
+
textFontSizeInput: 'textFontSizeInput',
|
|
230
|
+
enterDrawModeButton: 'enterDrawModeButton',
|
|
231
|
+
exitDrawModeButton: 'exitDrawModeButton',
|
|
232
|
+
drawColorInput: 'drawColorInput',
|
|
233
|
+
drawBrushSizeInput: 'drawBrushSizeInput',
|
|
234
|
+
removeSelectedAnnotationButton: 'removeSelectedAnnotationButton',
|
|
235
|
+
removeAllAnnotationsButton: 'removeAllAnnotationsButton',
|
|
236
|
+
deleteSelectedObjectButton: 'deleteSelectedObjectButton',
|
|
237
|
+
mergeAnnotationsButton: 'mergeAnnotationsButton',
|
|
238
|
+
bringSelectedObjectForwardButton: 'bringSelectedObjectForwardButton',
|
|
239
|
+
sendSelectedObjectBackwardButton: 'sendSelectedObjectBackwardButton',
|
|
240
|
+
bringSelectedObjectToFrontButton: 'bringSelectedObjectToFrontButton',
|
|
241
|
+
sendSelectedObjectToBackButton: 'sendSelectedObjectToBackButton',
|
|
242
|
+
annotationList: 'annotationList',
|
|
191
243
|
mergeMasksButton: 'mergeMasksButton',
|
|
192
244
|
downloadImageButton: 'downloadImageButton',
|
|
193
245
|
undoButton: 'undoButton',
|
|
194
246
|
redoButton: 'redoButton',
|
|
195
247
|
resetImageTransformButton: 'resetImageTransformButton',
|
|
196
248
|
imageInput: 'imageInput',
|
|
197
|
-
maskList: 'maskList',
|
|
198
249
|
});
|
|
199
250
|
|
|
200
251
|
// Load an image programmatically (base64 data URL).
|
|
@@ -203,6 +254,9 @@ await editor.loadImage('data:image/jpeg;base64,...');
|
|
|
203
254
|
// Add a rectangular mask, then export the result as base64.
|
|
204
255
|
const mask: MaskConfig = { shape: 'rect', width: 120, height: 80, left: '25%', top: '25%' };
|
|
205
256
|
editor.createMask(mask);
|
|
257
|
+
editor.createTextAnnotation({ text: 'Label', left: 120, top: 80 });
|
|
258
|
+
editor.enterDrawMode();
|
|
259
|
+
editor.setDrawConfig({ color: '#00aaff', brushSize: 10 });
|
|
206
260
|
|
|
207
261
|
const dataUrl = await editor.exportImageBase64({ fileType: 'png' });
|
|
208
262
|
```
|
|
@@ -216,18 +270,34 @@ const { ImageEditor } = require('@bensitu/image-editor');
|
|
|
216
270
|
const editor = new ImageEditor(fabric, { canvasWidth: 800, canvasHeight: 600 });
|
|
217
271
|
```
|
|
218
272
|
|
|
219
|
-
In v2, `require('@bensitu/image-editor')` returns a namespace object with
|
|
220
|
-
`ImageEditor`, `default`, and
|
|
221
|
-
|
|
273
|
+
In v2.2, `require('@bensitu/image-editor')` returns a namespace object with
|
|
274
|
+
`ImageEditor`, `default`, and the editor object guards
|
|
275
|
+
(`isBaseImageObject`, `isMaskObject`, `isAnnotationObject`,
|
|
276
|
+
`isTextAnnotationObject`, `isDrawAnnotationObject`, `isSessionObject`, and
|
|
277
|
+
`isEditableOverlayObject`); it does not return the constructor directly.
|
|
222
278
|
|
|
223
279
|
## Public API
|
|
224
280
|
|
|
225
281
|
`ImageEditor` is the only public class. The package barrel re-exports it as
|
|
226
|
-
both the default export and a named export, alongside
|
|
227
|
-
documented public types. Internal helpers (animation queue, command, history
|
|
282
|
+
both the default export and a named export, alongside the editor object guards
|
|
283
|
+
and the documented public types. Internal helpers (animation queue, command, history
|
|
228
284
|
manager, controllers, services, managers, utility modules) are intentionally
|
|
229
285
|
not exported and may change without notice.
|
|
230
286
|
|
|
287
|
+
### Object model
|
|
288
|
+
|
|
289
|
+
Every editor-owned Fabric object carries strict `editorObjectKind` metadata:
|
|
290
|
+
|
|
291
|
+
| Kind | Meaning |
|
|
292
|
+
| ------------ | ------------------------------------------------------------------------ |
|
|
293
|
+
| `baseImage` | The committed image at the bottom of the stack. |
|
|
294
|
+
| `mask` | Editable mask overlay with required `maskId`, `maskUid`, and `maskName`. |
|
|
295
|
+
| `annotation` | Editable Text or Draw overlay. Masks are not annotations. |
|
|
296
|
+
| `session` | Internal crop labels, mask labels, Mosaic previews, and tool previews. |
|
|
297
|
+
|
|
298
|
+
Session objects are never persisted, exported, or user-deletable. Strict type
|
|
299
|
+
guards reject legacy mask-like objects that do not carry `editorObjectKind`.
|
|
300
|
+
|
|
231
301
|
### Constructor
|
|
232
302
|
|
|
233
303
|
```ts
|
|
@@ -248,7 +318,7 @@ new ImageEditor(options?: ImageEditorOptions) // UMD: reads globalThis.fabric
|
|
|
248
318
|
| ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
249
319
|
| `loadImage(base64, options?)` | Load an image from a `data:image/...` URL. Returns `Promise<void>`. Transactional: any failure restores the prior canvas, scroll, overflow, and snapshot state. |
|
|
250
320
|
| `isImageLoaded()` | Returns `true` if a valid image is currently loaded on the canvas. |
|
|
251
|
-
| `isBusy()` | Returns `true` while the editor is loading, animating, in
|
|
321
|
+
| `isBusy()` | Returns `true` while the editor is loading, animating, or in Crop, Mosaic, Text, or Draw mode. |
|
|
252
322
|
| `setLayoutMode(mode)` | Select the layout strategy for future image loads. `mode` is `'fit'`, `'cover'`, or `'expand'`. |
|
|
253
323
|
|
|
254
324
|
`LoadImageOptions` currently includes `preserveScroll?: boolean` for
|
|
@@ -297,6 +367,8 @@ the JPEG, PNG, or WebP export options.
|
|
|
297
367
|
`MaskConfig` supports rect, circle, ellipse, polygon, and a custom
|
|
298
368
|
`fabricGenerator`. Falsy values in `styles` (`0`, `false`, `null`, `''`,
|
|
299
369
|
`NaN`) are applied verbatim.
|
|
370
|
+
Every mask is marked as `editorObjectKind: 'mask'` and includes required
|
|
371
|
+
`maskId`, `maskUid`, and `maskName` metadata.
|
|
300
372
|
|
|
301
373
|
Use `defaultMaskConfig` to define constructor-level defaults for masks created
|
|
302
374
|
through either `createMask()` or the built-in `createMaskButton`. Per-call
|
|
@@ -374,35 +446,99 @@ Mosaic edits replace base image pixels rather than adding Fabric overlay
|
|
|
374
446
|
objects, exported images include the Mosaic naturally while the preview circle
|
|
375
447
|
is never exported or saved in history.
|
|
376
448
|
|
|
449
|
+
### Text and Draw annotations
|
|
450
|
+
|
|
451
|
+
Tool modes are mutually exclusive: Crop, Mosaic, Text, and Draw cannot be
|
|
452
|
+
active at the same time. `getEditorState()` reports `activeToolMode` plus
|
|
453
|
+
`isCropMode`, `isMosaicMode`, `isTextMode`, and `isDrawMode`.
|
|
454
|
+
|
|
455
|
+
| Method | Description |
|
|
456
|
+
| ------------------------------------ | -------------------------------------------------------------------------- |
|
|
457
|
+
| `getAnnotations()` | Return current annotation objects in canvas order. Masks are not included. |
|
|
458
|
+
| `enterTextMode()` / `exitTextMode()` | Click empty canvas space to create editable text annotations. |
|
|
459
|
+
| `createTextAnnotation(config?)` | Create a text annotation directly and return it. |
|
|
460
|
+
| `getTextConfig()` | Return a defensive copy of the current Text config. |
|
|
461
|
+
| `setTextConfig(config)` | Patch current Text config without history. |
|
|
462
|
+
| `resetTextConfig()` | Restore Text config from constructor defaults. |
|
|
463
|
+
| `setTextColor(color)` | Convenience setter for text fill color. |
|
|
464
|
+
| `setTextFontSize(size)` | Convenience setter for text font size. |
|
|
465
|
+
| `enterDrawMode()` / `exitDrawMode()` | Use Fabric free drawing; each stroke becomes a Draw annotation. |
|
|
466
|
+
| `getDrawConfig()` | Return a defensive copy of the current Draw config. |
|
|
467
|
+
| `setDrawConfig(config)` | Patch current Draw config without history. |
|
|
468
|
+
| `resetDrawConfig()` | Restore Draw config from constructor defaults. |
|
|
469
|
+
| `setDrawColor(color)` | Convenience setter for brush color. |
|
|
470
|
+
| `setDrawBrushSize(size)` | Convenience setter for brush size. |
|
|
471
|
+
| `updateAnnotation(id, config)` | Update an annotation by id. |
|
|
472
|
+
| `updateSelectedAnnotation(config)` | Update selected annotation objects. |
|
|
473
|
+
| `removeSelectedAnnotation()` | Remove selected unlocked annotations. |
|
|
474
|
+
| `removeAllAnnotations(options?)` | Remove annotations only. Masks are preserved. |
|
|
475
|
+
| `deleteSelectedObject()` | Convenience deletion for selected masks and unlocked annotations. |
|
|
476
|
+
|
|
477
|
+
```ts
|
|
478
|
+
editor.enterTextMode();
|
|
479
|
+
editor.setTextConfig({ fill: '#ff0000', fontSize: 32 });
|
|
480
|
+
editor.updateSelectedAnnotation({ fill: '#00aaff' });
|
|
481
|
+
|
|
482
|
+
editor.enterDrawMode();
|
|
483
|
+
editor.setDrawConfig({ color: '#00aaff', brushSize: 10 });
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
Annotations carry `annotationHidden` and `annotationLocked` metadata. Hidden
|
|
487
|
+
annotations are not rendered during export. Locked annotations are not
|
|
488
|
+
selectable/editable and are skipped by selected-annotation update/delete
|
|
489
|
+
operations unless an API explicitly opts into forced removal.
|
|
490
|
+
|
|
491
|
+
### Layer operations
|
|
492
|
+
|
|
493
|
+
Editable overlays include masks and annotations. Layer operations keep the
|
|
494
|
+
base image below overlays and session objects above overlays.
|
|
495
|
+
|
|
496
|
+
| Method | Description |
|
|
497
|
+
| ------------------------------ | ------------------------------------------------- |
|
|
498
|
+
| `bringSelectedObjectForward()` | Move selected editable overlays one step up. |
|
|
499
|
+
| `sendSelectedObjectBackward()` | Move selected editable overlays one step down. |
|
|
500
|
+
| `bringSelectedObjectToFront()` | Move selected editable overlays to overlay front. |
|
|
501
|
+
| `sendSelectedObjectToBack()` | Move selected editable overlays to overlay back. |
|
|
502
|
+
|
|
377
503
|
### Merge and export
|
|
378
504
|
|
|
379
505
|
| Method | Description |
|
|
380
506
|
| ----------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
381
507
|
| `mergeMasks()` | Bake masks into the base image atomically. Returns `Promise<void>`. |
|
|
508
|
+
| `mergeAnnotations()` | Bake annotations into the base image atomically. Returns `Promise<void>`. |
|
|
382
509
|
| `exportImageBase64(options?)` | Returns `Promise<string>` (data URL). Resolves to `''` with a warning when no image is loaded. |
|
|
383
510
|
| `exportImageFile(options?)` | Returns `Promise<File>`. Rejects when no image is loaded. |
|
|
384
|
-
| `downloadImage(
|
|
385
|
-
|
|
386
|
-
`Base64ExportOptions` and `ImageFileExportOptions` separate
|
|
387
|
-
from export region selection
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
|
391
|
-
|
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
394
|
-
| `
|
|
395
|
-
| `
|
|
396
|
-
| `
|
|
397
|
-
| `
|
|
511
|
+
| `downloadImage(options?)` | Triggers a browser download. Also accepts a filename string. No-op when no image is loaded. |
|
|
512
|
+
|
|
513
|
+
`Base64ExportOptions` and `ImageFileExportOptions` separate overlay rendering
|
|
514
|
+
from export region selection. `DownloadImageOptions` supports the same overlay
|
|
515
|
+
rendering flags plus `fileName`:
|
|
516
|
+
|
|
517
|
+
| Option | Default | Description |
|
|
518
|
+
| ------------------ | --------- | ------------------------------------------------------------------------------------------- |
|
|
519
|
+
| `mergeMasks` | `true` | Render masks into exported pixels. Mask labels are never exported. |
|
|
520
|
+
| `mergeAnnotations` | `true` | Render non-hidden annotations into exported pixels. |
|
|
521
|
+
| `exportArea` | `'image'` | `'image'` clips to the image bounding box; `'canvas'` exports the canvas. |
|
|
522
|
+
| `fileType` | `'jpeg'` | `'png'`, `'jpeg'`, `'jpg'`, `'webp'`, or matching full MIME strings. |
|
|
523
|
+
| `format` | `'jpeg'` | Alias for `fileType` on `exportImageBase64`; `fileType` wins when both set. |
|
|
524
|
+
| `quality` | `0.92` | Lossy quality clamped to `[0, 1]`; ignored for PNG. |
|
|
525
|
+
| `multiplier` | `1` | Output resolution multiplier. |
|
|
526
|
+
| `fileName` | option | `ImageFileExportOptions` and `DownloadImageOptions`. Defaults to `defaultDownloadFileName`. |
|
|
398
527
|
|
|
399
528
|
```ts
|
|
400
|
-
await editor.exportImageBase64({
|
|
401
|
-
await editor.exportImageBase64({
|
|
402
|
-
await editor.exportImageBase64({
|
|
403
|
-
await editor.exportImageBase64({
|
|
529
|
+
await editor.exportImageBase64({ mergeMasks: true, mergeAnnotations: true });
|
|
530
|
+
await editor.exportImageBase64({ mergeMasks: false, mergeAnnotations: true });
|
|
531
|
+
await editor.exportImageBase64({ mergeMasks: true, mergeAnnotations: false });
|
|
532
|
+
await editor.exportImageBase64({ mergeMasks: false, mergeAnnotations: false });
|
|
533
|
+
editor.downloadImage({ mergeMasks: false, mergeAnnotations: false });
|
|
534
|
+
editor.downloadImage('edited_image.jpg'); // Backwards-compatible filename shorthand.
|
|
404
535
|
```
|
|
405
536
|
|
|
537
|
+
`mergeMasks` and `mergeAnnotations` in export options affect the rendered output
|
|
538
|
+
only. They do not mutate editor state, remove objects, or push history entries.
|
|
539
|
+
State-mutating merge APIs are `mergeMasks()` and `mergeAnnotations()`.
|
|
540
|
+
`mergeMasks()` preserves annotations; `mergeAnnotations()` preserves masks.
|
|
541
|
+
|
|
406
542
|
### State and history
|
|
407
543
|
|
|
408
544
|
| Method | Description |
|
|
@@ -418,53 +554,59 @@ Pass an `ImageEditorOptions` object as the second constructor argument
|
|
|
418
554
|
(or as the only argument when using the UMD global form). Unknown keys are
|
|
419
555
|
ignored; nested `label` and `crop` objects are deep-merged with the defaults.
|
|
420
556
|
|
|
421
|
-
| Option
|
|
422
|
-
|
|
|
423
|
-
| `canvasWidth`
|
|
424
|
-
| `canvasHeight`
|
|
425
|
-
| `backgroundColor`
|
|
426
|
-
| `animationDuration`
|
|
427
|
-
| `minScale`
|
|
428
|
-
| `maxScale`
|
|
429
|
-
| `scaleStep`
|
|
430
|
-
| `rotationStep`
|
|
431
|
-
| `defaultLayoutMode`
|
|
432
|
-
| `downsampleOnLoad`
|
|
433
|
-
| `downsampleMaxWidth`
|
|
434
|
-
| `downsampleMaxHeight`
|
|
435
|
-
| `downsampleQuality`
|
|
436
|
-
| `preserveSourceFormat`
|
|
437
|
-
| `downsampleMimeType`
|
|
438
|
-
| `imageLoadTimeoutMs`
|
|
439
|
-
| `exportMultiplier`
|
|
440
|
-
| `maxExportPixels`
|
|
441
|
-
| `maxHistorySize`
|
|
442
|
-
| `exportAreaByDefault`
|
|
443
|
-
| `
|
|
444
|
-
| `
|
|
445
|
-
| `
|
|
446
|
-
| `
|
|
447
|
-
| `
|
|
448
|
-
| `
|
|
449
|
-
| `
|
|
450
|
-
| `
|
|
451
|
-
| `
|
|
452
|
-
| `
|
|
453
|
-
| `
|
|
454
|
-
| `
|
|
455
|
-
| `
|
|
456
|
-
| `
|
|
457
|
-
| `
|
|
458
|
-
| `
|
|
459
|
-
| `
|
|
460
|
-
| `
|
|
461
|
-
| `
|
|
462
|
-
| `
|
|
463
|
-
| `
|
|
464
|
-
| `
|
|
465
|
-
| `
|
|
466
|
-
| `
|
|
467
|
-
| `
|
|
557
|
+
| Option | Default | Description |
|
|
558
|
+
| --------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
559
|
+
| `canvasWidth` | `800` | Initial and hidden-container fallback canvas width in pixels. |
|
|
560
|
+
| `canvasHeight` | `600` | Initial and hidden-container fallback canvas height in pixels. |
|
|
561
|
+
| `backgroundColor` | `'transparent'` | Fabric canvas background color. |
|
|
562
|
+
| `animationDuration` | `300` | Duration of scale and rotate animations (ms). |
|
|
563
|
+
| `minScale` | `0.1` | Minimum scale factor. |
|
|
564
|
+
| `maxScale` | `5.0` | Maximum scale factor. |
|
|
565
|
+
| `scaleStep` | `0.05` | Scale delta per zoom step. |
|
|
566
|
+
| `rotationStep` | `90` | Rotation step in degrees. |
|
|
567
|
+
| `defaultLayoutMode` | `'expand'` | Initial layout mode for image loads until changed by `setLayoutMode()`. Use `'fit'`, `'cover'`, or `'expand'`. Invalid runtime values fall back to `'expand'`. |
|
|
568
|
+
| `downsampleOnLoad` | `true` | Downsample large images on load. |
|
|
569
|
+
| `downsampleMaxWidth` | `4000` | Max width before downsampling kicks in. |
|
|
570
|
+
| `downsampleMaxHeight` | `3000` | Max height before downsampling kicks in. |
|
|
571
|
+
| `downsampleQuality` | `0.92` | Lossy quality used when downsampling and exporting. |
|
|
572
|
+
| `preserveSourceFormat` | `true` | Preserve PNG/WebP MIME through downsampling unless `downsampleMimeType` is set. |
|
|
573
|
+
| `downsampleMimeType` | `null` | Explicit downsample MIME type. Overrides `preserveSourceFormat`. |
|
|
574
|
+
| `imageLoadTimeoutMs` | `30000` | Maximum duration for both decode and Fabric image creation during `loadImage`. |
|
|
575
|
+
| `exportMultiplier` | `1` | Output resolution multiplier. |
|
|
576
|
+
| `maxExportPixels` | `50000000` | Maximum output pixel count after applying the export multiplier. Invalid values fall back to this default. |
|
|
577
|
+
| `maxHistorySize` | `50` | Maximum undo-history entries. Snapshots may include full image data URLs, so large images can duplicate memory across history entries. Lower this for memory-constrained pages. |
|
|
578
|
+
| `exportAreaByDefault` | `'image'` | Default export region for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
|
|
579
|
+
| `mergeMasksByDefault` | `true` | Default mask rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
|
|
580
|
+
| `mergeAnnotationsByDefault` | `true` | Default annotation rendering behavior for `exportImageBase64`, `exportImageFile`, and `downloadImage`. |
|
|
581
|
+
| `defaultMaskWidth` | `50` | Default mask width. |
|
|
582
|
+
| `defaultMaskHeight` | `80` | Default mask height. |
|
|
583
|
+
| `defaultMaskConfig` | `{}` | Defaults applied by `createMask()` after `defaultMaskWidth` / `defaultMaskHeight` and before per-call config. Supports `MaskConfig` fields except `onCreate` and `fabricGenerator`. |
|
|
584
|
+
| `defaultMosaicConfig` | see source | Defaults used to initialize the current Mosaic tool config. Supports `brushSize`, `blockSize`, preview circle styling, `outputFileType`, and `outputQuality`. Runtime Mosaic setters update the current config only. |
|
|
585
|
+
| `defaultTextConfig` | see source | Defaults used to initialize the current Text annotation config. Runtime Text setters update the current config only. |
|
|
586
|
+
| `defaultDrawConfig` | see source | Defaults used to initialize the current Draw mode config. Runtime Draw setters update the current config only. |
|
|
587
|
+
| `maskRotatable` | `false` | Allow masks to be rotated by the user. |
|
|
588
|
+
| `maskLabelOnSelect` | `true` | Show a label above a selected mask. |
|
|
589
|
+
| `maskLabelOffset` | `3` | Pixel offset of the label from the mask's top-left corner. |
|
|
590
|
+
| `maskName` | `'mask'` | Prefix used for auto-generated mask names. |
|
|
591
|
+
| `textAnnotationName` | `'text'` | Prefix used for auto-generated text annotation names. |
|
|
592
|
+
| `drawAnnotationName` | `'draw'` | Prefix used for auto-generated draw annotation names. |
|
|
593
|
+
| `groupSelection` | `false` | Allow Fabric multi-object group selection on the canvas. |
|
|
594
|
+
| `showPlaceholder` | `true` | Show a placeholder element while no image is loaded. |
|
|
595
|
+
| `initialImageBase64` | `null` | Base64 data URL auto-loaded after construction. |
|
|
596
|
+
| `defaultDownloadFileName` | `'edited_image.jpg'` | Default file name used by `downloadImage()`. |
|
|
597
|
+
| `onImageLoadStart` | `null` | Called before a valid image load begins. |
|
|
598
|
+
| `onImageLoaded` | `null` | Called as `(info, context)` once after a successful `loadImage`. Extra arguments are ignored by existing zero-argument JavaScript handlers. |
|
|
599
|
+
| `onImageCleared` | `null` | Called when a committed image is replaced or cleared. |
|
|
600
|
+
| `onImageChanged` | `null` | Called with a safe editor state snapshot after visible editor state changes. |
|
|
601
|
+
| `onBusyChange` | `null` | Called only when the public busy state changes. |
|
|
602
|
+
| `onEditorDisposed` | `null` | Called once when `dispose()` performs teardown. |
|
|
603
|
+
| `onMasksChanged` | `null` | Called with a shallow copy of current mask objects after the mask collection changes. |
|
|
604
|
+
| `onAnnotationsChanged` | `null` | Called with a shallow copy of current annotation objects after the annotation collection changes. |
|
|
605
|
+
| `onSelectionChange` | `null` | Called with selected object payload after selection changes. |
|
|
606
|
+
| `onError` | `null` | Called as `(error, message)` when the editor reports an error. |
|
|
607
|
+
| `onWarning` | `null` | Called as `(error, message)` when the editor reports a recoverable warning. |
|
|
608
|
+
| `label` | see source | `LabelConfig` for selected-mask labels (`getText`, `textOptions`, `create`). |
|
|
609
|
+
| `crop` | see source | `CropConfig` (`minWidth`, `minHeight`, `padding`, `hideMasksDuringCrop`, `preserveMasksAfterCrop`, `allowRotationOfCropRect`, `exportFileType`, `exportQuality`). `applyCrop()` preserves the current image format by default (`'source'`) and falls back to PNG when unknown. |
|
|
468
610
|
|
|
469
611
|
`crop.exportFileType` defaults to `'source'`. Supported explicit values are
|
|
470
612
|
`'png'`, `'jpeg'`, `'jpg'`, `'webp'`, and full image MIME strings. PNG is
|
|
@@ -477,14 +619,26 @@ preserve the current image MIME type when known and fall back to PNG when the
|
|
|
477
619
|
source format cannot be determined. JPEG/WebP commits use
|
|
478
620
|
`defaultMosaicConfig.outputQuality` when finite, otherwise `downsampleQuality`.
|
|
479
621
|
|
|
622
|
+
## Breaking changes in v2.2.0
|
|
623
|
+
|
|
624
|
+
- All editor-owned Fabric objects now require `editorObjectKind`.
|
|
625
|
+
- `isMaskObject()` is strict and rejects legacy objects with only `maskId`.
|
|
626
|
+
- `MaskObject.maskUid` is required.
|
|
627
|
+
- Serialized states without `editorObjectKind` are not migrated.
|
|
628
|
+
- Export option mergeMask was removed; use `mergeMasks`.
|
|
629
|
+
- Constructor option mergeMaskByDefault was removed; use `mergeMasksByDefault`.
|
|
630
|
+
- `ImageFileExportOptions` keeps `fileType` only; `format` remains limited to
|
|
631
|
+
`exportImageBase64`.
|
|
632
|
+
|
|
480
633
|
## Example workflow
|
|
481
634
|
|
|
482
635
|
1. Construct `ImageEditor` with options and call `init(idMap)` to wire it up.
|
|
483
636
|
2. Load an image via `loadImage(base64)` or the bound file input.
|
|
484
|
-
3. Adjust with `scaleImage`, `rotateImage`, `resetImageTransform`,
|
|
485
|
-
|
|
486
|
-
4. Add `createMask` calls
|
|
487
|
-
|
|
637
|
+
3. Adjust with `scaleImage`, `rotateImage`, `resetImageTransform`, Crop mode,
|
|
638
|
+
Mosaic mode, Text mode, or Draw mode.
|
|
639
|
+
4. Add `createMask` and annotation calls, then inspect via `maskList` and
|
|
640
|
+
`annotationList`.
|
|
641
|
+
5. Use `mergeMasks()` or `mergeAnnotations()` to bake overlays into the image, then
|
|
488
642
|
`exportImageBase64`, `exportImageFile`, or `downloadImage` to produce
|
|
489
643
|
the final output.
|
|
490
644
|
6. Call `dispose()` when the editor is unmounted.
|