From b7aef254a4d7f2fbbadd53abffd394f65ac6ec1e Mon Sep 17 00:00:00 2001 From: MultiMote Date: Fri, 11 Apr 2025 22:31:17 +0300 Subject: [PATCH] Clone multiple objects --- src/lib/ImageEditor.svelte | 11 ++++++---- src/utils/image_editor_utils.ts | 37 ++++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/lib/ImageEditor.svelte b/src/lib/ImageEditor.svelte index e3078c7..a81d662 100644 --- a/src/lib/ImageEditor.svelte +++ b/src/lib/ImageEditor.svelte @@ -74,9 +74,7 @@ }; const cloneSelected = () => { - if (selectedObject) { - ImageEditorUtils.cloneObject(fabricCanvas, selectedObject).then(() => undo.push(fabricCanvas, labelProps)); - } + ImageEditorUtils.cloneSelection(fabricCanvas).then(() => undo.push(fabricCanvas, labelProps)); }; const moveSelected = (direction: MoveDirection, ctrl?: boolean) => { @@ -440,10 +438,15 @@ {/if} - {#if selectedObject && selectedCount === 1} + + + {#if selectedCount > 0} + {/if} + + {#if selectedObject && selectedCount === 1} {/if} diff --git a/src/utils/image_editor_utils.ts b/src/utils/image_editor_utils.ts index 7ed11f9..9dabf48 100644 --- a/src/utils/image_editor_utils.ts +++ b/src/utils/image_editor_utils.ts @@ -3,13 +3,36 @@ import { GRID_SIZE, OBJECT_DEFAULTS } from "../defaults"; import type { MoveDirection } from "../types"; export class ImageEditorUtils { - static async cloneObject(canvas: fabric.Canvas, selected: fabric.FabricObject): Promise { - const obj = await selected.clone(); - obj.snapAngle = OBJECT_DEFAULTS.snapAngle; - obj.top += GRID_SIZE; - obj.left += GRID_SIZE; - canvas.add(obj); - canvas.setActiveObject(obj); + static async cloneSelection(canvas: fabric.Canvas): Promise { + const clonedList: fabric.FabricObject[] = []; + + const selection = canvas.getActiveObject(); + + if (selection === undefined) { + return; + } + + let selected: fabric.FabricObject[] = canvas.getActiveObjects(); + + for (const obj of selected) { + const cloned = await obj.clone(); + + if (selection instanceof fabric.ActiveSelection) { + cloned.left += selection.left + selection.width / 2; + cloned.top += selection.top + selection.height / 2; + } + + cloned.top += GRID_SIZE; + cloned.left += GRID_SIZE; + cloned.snapAngle = OBJECT_DEFAULTS.snapAngle; + + clonedList.push(cloned); + } + + canvas.add(...clonedList); + + const newSelection = new fabric.ActiveSelection(clonedList); + canvas.setActiveObject(newSelection); } static moveSelection(canvas: fabric.Canvas, direction: MoveDirection, ctrl?: boolean) {