Skip to content

Commit b7aef25

Browse files
committed
Clone multiple objects
1 parent d5b6eae commit b7aef25

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

src/lib/ImageEditor.svelte

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@
7474
};
7575
7676
const cloneSelected = () => {
77-
if (selectedObject) {
78-
ImageEditorUtils.cloneObject(fabricCanvas, selectedObject).then(() => undo.push(fabricCanvas, labelProps));
79-
}
77+
ImageEditorUtils.cloneSelection(fabricCanvas).then(() => undo.push(fabricCanvas, labelProps));
8078
};
8179
8280
const moveSelected = (direction: MoveDirection, ctrl?: boolean) => {
@@ -440,10 +438,15 @@
440438
</button>
441439
{/if}
442440

443-
{#if selectedObject && selectedCount === 1}
441+
442+
443+
{#if selectedCount > 0}
444444
<button class="btn btn-sm btn-secondary me-1" on:click={cloneSelected} title={$tr("editor.clone")}>
445445
<MdIcon icon="content_copy" />
446446
</button>
447+
{/if}
448+
449+
{#if selectedObject && selectedCount === 1}
447450
<GenericObjectParamsControls {selectedObject} valueUpdated={controlValueUpdated} />
448451
{/if}
449452

src/utils/image_editor_utils.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,36 @@ import { GRID_SIZE, OBJECT_DEFAULTS } from "../defaults";
33
import type { MoveDirection } from "../types";
44

55
export class ImageEditorUtils {
6-
static async cloneObject(canvas: fabric.Canvas, selected: fabric.FabricObject): Promise<void> {
7-
const obj = await selected.clone();
8-
obj.snapAngle = OBJECT_DEFAULTS.snapAngle;
9-
obj.top += GRID_SIZE;
10-
obj.left += GRID_SIZE;
11-
canvas.add(obj);
12-
canvas.setActiveObject(obj);
6+
static async cloneSelection(canvas: fabric.Canvas): Promise<void> {
7+
const clonedList: fabric.FabricObject[] = [];
8+
9+
const selection = canvas.getActiveObject();
10+
11+
if (selection === undefined) {
12+
return;
13+
}
14+
15+
let selected: fabric.FabricObject[] = canvas.getActiveObjects();
16+
17+
for (const obj of selected) {
18+
const cloned = await obj.clone();
19+
20+
if (selection instanceof fabric.ActiveSelection) {
21+
cloned.left += selection.left + selection.width / 2;
22+
cloned.top += selection.top + selection.height / 2;
23+
}
24+
25+
cloned.top += GRID_SIZE;
26+
cloned.left += GRID_SIZE;
27+
cloned.snapAngle = OBJECT_DEFAULTS.snapAngle;
28+
29+
clonedList.push(cloned);
30+
}
31+
32+
canvas.add(...clonedList);
33+
34+
const newSelection = new fabric.ActiveSelection(clonedList);
35+
canvas.setActiveObject(newSelection);
1336
}
1437

1538
static moveSelection(canvas: fabric.Canvas, direction: MoveDirection, ctrl?: boolean) {

0 commit comments

Comments
 (0)