@anu3ev/fabric-image-editor 0.1.46 → 0.1.48
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/dist/main.js +1126 -1324
- package/dist/{worker.js → worker.ts} +13 -3
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,65 +1,67 @@
|
|
|
1
|
-
var fe = Object.
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
1
|
+
var je = Object.defineProperty, fe = Object.defineProperties;
|
|
2
|
+
var be = Object.getOwnPropertyDescriptors;
|
|
3
|
+
var H = Object.getOwnPropertySymbols;
|
|
4
|
+
var ce = Object.prototype.hasOwnProperty, de = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var re = (c, e, t) => e in c ? je(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t, f = (c, e) => {
|
|
5
6
|
for (var t in e || (e = {}))
|
|
6
|
-
|
|
7
|
-
if (
|
|
8
|
-
for (var t of
|
|
9
|
-
|
|
10
|
-
return
|
|
11
|
-
};
|
|
12
|
-
var Y = (
|
|
7
|
+
ce.call(e, t) && re(c, t, e[t]);
|
|
8
|
+
if (H)
|
|
9
|
+
for (var t of H(e))
|
|
10
|
+
de.call(e, t) && re(c, t, e[t]);
|
|
11
|
+
return c;
|
|
12
|
+
}, le = (c, e) => fe(c, be(e));
|
|
13
|
+
var Y = (c, e) => {
|
|
13
14
|
var t = {};
|
|
14
|
-
for (var
|
|
15
|
-
|
|
16
|
-
if (
|
|
17
|
-
for (var
|
|
18
|
-
e.indexOf(
|
|
15
|
+
for (var s in c)
|
|
16
|
+
ce.call(c, s) && e.indexOf(s) < 0 && (t[s] = c[s]);
|
|
17
|
+
if (c != null && H)
|
|
18
|
+
for (var s of H(c))
|
|
19
|
+
e.indexOf(s) < 0 && de.call(c, s) && (t[s] = c[s]);
|
|
19
20
|
return t;
|
|
20
21
|
};
|
|
21
|
-
var
|
|
22
|
-
var
|
|
22
|
+
var I = (c, e, t) => new Promise((s, i) => {
|
|
23
|
+
var n = (d) => {
|
|
23
24
|
try {
|
|
24
|
-
o(t.next(
|
|
25
|
-
} catch (
|
|
26
|
-
|
|
25
|
+
o(t.next(d));
|
|
26
|
+
} catch (r) {
|
|
27
|
+
i(r);
|
|
27
28
|
}
|
|
28
|
-
},
|
|
29
|
+
}, a = (d) => {
|
|
29
30
|
try {
|
|
30
|
-
o(t.throw(
|
|
31
|
-
} catch (
|
|
32
|
-
|
|
31
|
+
o(t.throw(d));
|
|
32
|
+
} catch (r) {
|
|
33
|
+
i(r);
|
|
33
34
|
}
|
|
34
|
-
}, o = (
|
|
35
|
-
o((t = t.apply(
|
|
35
|
+
}, o = (d) => d.done ? s(d.value) : Promise.resolve(d.value).then(n, a);
|
|
36
|
+
o((t = t.apply(c, e)).next());
|
|
36
37
|
});
|
|
37
|
-
import { ActiveSelection as
|
|
38
|
+
import { ActiveSelection as v, util as R, controlsUtils as pe, InteractiveFabricObject as ye, loadSVGFromURL as Ie, FabricImage as U, Point as _, Rect as ve, Circle as Ae, Triangle as Se, Group as X, Canvas as Ce, Pattern as Ne } from "fabric";
|
|
38
39
|
import { create as De } from "jsondiffpatch";
|
|
39
|
-
import
|
|
40
|
-
var
|
|
41
|
-
for (var e = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 21, t = "",
|
|
42
|
-
t +=
|
|
40
|
+
import Le from "diff-match-patch";
|
|
41
|
+
var we = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", D = function() {
|
|
42
|
+
for (var e = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : 21, t = "", s = crypto.getRandomValues(new Uint8Array(e |= 0)); e--; )
|
|
43
|
+
t += we[s[e] & 63];
|
|
43
44
|
return t;
|
|
44
45
|
};
|
|
45
|
-
class
|
|
46
|
+
class z {
|
|
46
47
|
/**
|
|
47
48
|
* Конструктор принимает редактор и опции.
|
|
48
|
-
* @param
|
|
49
|
-
* @param
|
|
50
|
-
* @param
|
|
51
|
-
* @param
|
|
52
|
-
* @param
|
|
53
|
-
* @param
|
|
54
|
-
* @param
|
|
55
|
-
* @param
|
|
56
|
-
* @param
|
|
57
|
-
* @param
|
|
58
|
-
* @param
|
|
59
|
-
* @param
|
|
49
|
+
* @param params
|
|
50
|
+
* @param params.editor – редактор, содержащий canvas
|
|
51
|
+
* @param params.options — настройки редактора (см. defaults.js)
|
|
52
|
+
* @param params.options.canvasDragging — включить перетаскивание канваса
|
|
53
|
+
* @param params.options.mouseWheelZooming — включить зум колесом мыши
|
|
54
|
+
* @param params.options.bringToFrontOnSelection — поднимать объект на передний план при выборе
|
|
55
|
+
* @param params.options.copyObjectsByHotkey — копировать объекты по Ctrl+C
|
|
56
|
+
* @param params.options.pasteImageFromClipboard — вставлять изображения и объекты из буфера обмена
|
|
57
|
+
* @param params.options.undoRedoByHotKeys — отмена/повтор по Ctrl+Z/Ctrl+Y
|
|
58
|
+
* @param params.options.selectAllByHotkey — выделение всех объектов по Ctrl+A
|
|
59
|
+
* @param params.options.deleteObjectsByHotkey — удаление объектов по Delete
|
|
60
|
+
* @param params.options.resetObjectFitByDoubleClick — сброс фита объекта по двойному клику
|
|
61
|
+
* @param params.options.adaptCanvasToContainerOnResize — адаптировать канвас к размерам контейнера при изменении размеров окна
|
|
60
62
|
*/
|
|
61
63
|
constructor({ editor: e, options: t = {} }) {
|
|
62
|
-
this.isDragging = !1, this.lastMouseX = 0, this.lastMouseY = 0, this.isUndoRedoKeyPressed = !1, this.isSpacePressed = !1, this.canvasDragging = !1, this.mouseWheelZooming = !1, this.bringToFrontOnSelection = !1, this.resetObjectFitByDoubleClick = !1, this.copyObjectsByHotkey = !1, this.pasteImageFromClipboard = !1, this.undoRedoByHotKeys = !1, this.selectAllByHotkey = !1, this.deleteObjectsByHotkey = !1, this.adaptCanvasToContainerOnResize = !1, this.editor = e, this.canvas = e.canvas, this.options = t, this.handleContainerResizeBound =
|
|
64
|
+
this.isDragging = !1, this.lastMouseX = 0, this.lastMouseY = 0, this.isUndoRedoKeyPressed = !1, this.isSpacePressed = !1, this.canvasDragging = !1, this.mouseWheelZooming = !1, this.bringToFrontOnSelection = !1, this.resetObjectFitByDoubleClick = !1, this.copyObjectsByHotkey = !1, this.pasteImageFromClipboard = !1, this.undoRedoByHotKeys = !1, this.selectAllByHotkey = !1, this.deleteObjectsByHotkey = !1, this.adaptCanvasToContainerOnResize = !1, this.editor = e, this.canvas = e.canvas, this.options = t, this.handleContainerResizeBound = z.debounce(this.handleContainerResize.bind(this), 500), this.handleCopyEventBound = this.handleCopyEvent.bind(this), this.handlePasteEventBound = this.handlePasteEvent.bind(this), this.handleUndoRedoEventBound = this.handleUndoRedoEvent.bind(this), this.handleUndoRedoKeyUpBound = this.handleUndoRedoKeyUp.bind(this), this.handleSelectAllEventBound = this.handleSelectAllEvent.bind(this), this.handleDeleteObjectsEventBound = this.handleDeleteObjectsEvent.bind(this), this.handleSpaceKeyDownBound = this.handleSpaceKeyDown.bind(this), this.handleSpaceKeyUpBound = this.handleSpaceKeyUp.bind(this), this.handleObjectModifiedHistoryBound = z.debounce(this.handleObjectModifiedHistory.bind(this), 300), this.handleObjectRotatingHistoryBound = z.debounce(this.handleObjectRotatingHistory.bind(this), 300), this.handleObjectAddedHistoryBound = this.handleObjectAddedHistory.bind(this), this.handleObjectRemovedHistoryBound = this.handleObjectRemovedHistory.bind(this), this.handleOverlayUpdateBound = this.handleOverlayUpdate.bind(this), this.handleCanvasDragStartBound = this.handleCanvasDragStart.bind(this), this.handleCanvasDraggingBound = this.handleCanvasDragging.bind(this), this.handleCanvasDragEndBound = this.handleCanvasDragEnd.bind(this), this.handleMouseWheelZoomBound = this.handleMouseWheelZoom.bind(this), this.handleBringToFrontBound = this.handleBringToFront.bind(this), this.handleResetObjectFitBound = this.handleResetObjectFit.bind(this), this.handleLockedSelectionBound = this._filterLockedSelection.bind(this), this.init();
|
|
63
65
|
}
|
|
64
66
|
/**
|
|
65
67
|
* Инициализация всех обработчиков согласно опциям.
|
|
@@ -68,38 +70,38 @@ class R {
|
|
|
68
70
|
const {
|
|
69
71
|
adaptCanvasToContainerOnResize: e,
|
|
70
72
|
canvasDragging: t,
|
|
71
|
-
mouseWheelZooming:
|
|
72
|
-
bringToFrontOnSelection:
|
|
73
|
-
copyObjectsByHotkey:
|
|
74
|
-
pasteImageFromClipboard:
|
|
73
|
+
mouseWheelZooming: s,
|
|
74
|
+
bringToFrontOnSelection: i,
|
|
75
|
+
copyObjectsByHotkey: n,
|
|
76
|
+
pasteImageFromClipboard: a,
|
|
75
77
|
undoRedoByHotKeys: o,
|
|
76
|
-
selectAllByHotkey:
|
|
77
|
-
deleteObjectsByHotkey:
|
|
78
|
+
selectAllByHotkey: d,
|
|
79
|
+
deleteObjectsByHotkey: r,
|
|
78
80
|
resetObjectFitByDoubleClick: l
|
|
79
81
|
} = this.options;
|
|
80
|
-
t && (this.canvas.on("mouse:down", this.handleCanvasDragStartBound), this.canvas.on("mouse:move", this.handleCanvasDraggingBound), this.canvas.on("mouse:up", this.handleCanvasDragEndBound), document.addEventListener("keydown", this.handleSpaceKeyDownBound, { capture: !0 }), document.addEventListener("keyup", this.handleSpaceKeyUpBound, { capture: !0 })),
|
|
82
|
+
t && (this.canvas.on("mouse:down", this.handleCanvasDragStartBound), this.canvas.on("mouse:move", this.handleCanvasDraggingBound), this.canvas.on("mouse:up", this.handleCanvasDragEndBound), document.addEventListener("keydown", this.handleSpaceKeyDownBound, { capture: !0 }), document.addEventListener("keyup", this.handleSpaceKeyUpBound, { capture: !0 })), s && this.canvas.on("mouse:wheel", this.handleMouseWheelZoomBound), i && (this.canvas.on("selection:created", this.handleBringToFrontBound), this.canvas.on("selection:updated", this.handleBringToFrontBound)), l && this.canvas.on("mouse:dblclick", this.handleResetObjectFitBound), e && window.addEventListener("resize", this.handleContainerResizeBound, { capture: !0 }), n && document.addEventListener("keydown", this.handleCopyEventBound, { capture: !0 }), a && document.addEventListener("paste", this.handlePasteEventBound, { capture: !0 }), o && (document.addEventListener("keydown", this.handleUndoRedoEventBound, { capture: !0 }), document.addEventListener("keyup", this.handleUndoRedoKeyUpBound, { capture: !0 })), d && document.addEventListener("keydown", this.handleSelectAllEventBound, { capture: !0 }), r && document.addEventListener("keydown", this.handleDeleteObjectsEventBound, { capture: !0 }), this.canvas.on("object:modified", this.handleObjectModifiedHistoryBound), this.canvas.on("object:rotating", this.handleObjectRotatingHistoryBound), this.canvas.on("object:added", this.handleObjectAddedHistoryBound), this.canvas.on("object:removed", this.handleObjectRemovedHistoryBound), this.canvas.on("object:added", this.handleOverlayUpdateBound), this.canvas.on("selection:created", this.handleOverlayUpdateBound), this.canvas.on("selection:created", this.handleLockedSelectionBound), this.canvas.on("selection:updated", this.handleLockedSelectionBound);
|
|
81
83
|
}
|
|
82
84
|
/**
|
|
83
85
|
* При массовом выделении объектов удаляем из него залоченные.
|
|
84
|
-
* @param
|
|
85
|
-
* @param
|
|
86
|
-
* @param
|
|
86
|
+
* @param params - параметры события
|
|
87
|
+
* @param params.selected - массив выделенных объектов
|
|
88
|
+
* @param params.e - событие указателя (опционально)
|
|
87
89
|
*/
|
|
88
90
|
_filterLockedSelection({ selected: e, e: t }) {
|
|
89
|
-
if (!(e != null && e.length) || !(t instanceof MouseEvent) || e.length === 1 || !e.some((
|
|
90
|
-
const
|
|
91
|
-
if (
|
|
91
|
+
if (!(e != null && e.length) || !(t instanceof MouseEvent) || e.length === 1 || !e.some((a) => a.locked)) return;
|
|
92
|
+
const i = e.filter((a) => !a.locked);
|
|
93
|
+
if (i.length === 0) {
|
|
92
94
|
this.canvas.discardActiveObject();
|
|
93
95
|
return;
|
|
94
96
|
}
|
|
95
|
-
if (
|
|
96
|
-
this.canvas.setActiveObject(
|
|
97
|
+
if (i.length === 1) {
|
|
98
|
+
this.canvas.setActiveObject(i[0]);
|
|
97
99
|
return;
|
|
98
100
|
}
|
|
99
|
-
const
|
|
101
|
+
const n = new v(i, {
|
|
100
102
|
canvas: this.canvas
|
|
101
103
|
});
|
|
102
|
-
this.canvas.setActiveObject(
|
|
104
|
+
this.canvas.setActiveObject(n), this.canvas.requestRenderAll();
|
|
103
105
|
}
|
|
104
106
|
/**
|
|
105
107
|
* Обработчики для сохранения состояния редактора в истории.
|
|
@@ -134,58 +136,58 @@ class R {
|
|
|
134
136
|
}
|
|
135
137
|
/**
|
|
136
138
|
* Обработчик для Ctrl+C (копирование).
|
|
137
|
-
* @param
|
|
138
|
-
* @param
|
|
139
|
-
* @param
|
|
140
|
-
* @param
|
|
139
|
+
* @param event — объект события
|
|
140
|
+
* @param event.ctrlKey — зажата ли клавиша Ctrl
|
|
141
|
+
* @param event.metaKey — зажата ли клавиша Cmd (для Mac)
|
|
142
|
+
* @param event.code — код клавиши
|
|
141
143
|
*/
|
|
142
144
|
handleCopyEvent(e) {
|
|
143
|
-
const { ctrlKey: t, metaKey:
|
|
144
|
-
!t && !
|
|
145
|
+
const { ctrlKey: t, metaKey: s, code: i } = e;
|
|
146
|
+
!t && !s || i !== "KeyC" || (e.preventDefault(), this.editor.clipboardManager.copy());
|
|
145
147
|
}
|
|
146
148
|
/**
|
|
147
149
|
* Обработчик вставки объекта или изображения из буфера обмена.
|
|
148
|
-
* @param
|
|
150
|
+
* @param event — объект события
|
|
149
151
|
*/
|
|
150
152
|
handlePasteEvent(e) {
|
|
151
153
|
this.editor.clipboardManager.handlePasteEvent(e);
|
|
152
154
|
}
|
|
153
155
|
/**
|
|
154
156
|
* Обработчик для отмены/повтора (Ctrl+Z/Ctrl+Y).
|
|
155
|
-
*
|
|
156
|
-
* @param
|
|
157
|
-
* @param
|
|
158
|
-
* @param
|
|
157
|
+
* @param event — объект события
|
|
158
|
+
* @param event.ctrlKey — зажата ли клавиша Ctrl
|
|
159
|
+
* @param event.metaKey — зажата ли клавиша Cmd (для Mac)
|
|
160
|
+
* @param event.code — код клавиши
|
|
159
161
|
*/
|
|
160
162
|
handleUndoRedoEvent(e) {
|
|
161
|
-
return
|
|
162
|
-
const { ctrlKey: t, metaKey:
|
|
163
|
-
!t && !
|
|
163
|
+
return I(this, null, function* () {
|
|
164
|
+
const { ctrlKey: t, metaKey: s, code: i, repeat: n } = e;
|
|
165
|
+
!t && !s || n || !/Mac/i.test(navigator.userAgent) && this.isUndoRedoKeyPressed || (i === "KeyZ" ? (e.preventDefault(), this.isUndoRedoKeyPressed = !0, yield this.editor.historyManager.undo()) : i === "KeyY" && (e.preventDefault(), this.isUndoRedoKeyPressed = !0, yield this.editor.historyManager.redo()));
|
|
164
166
|
});
|
|
165
167
|
}
|
|
166
168
|
/**
|
|
167
169
|
* Обработчик для отпускания клавиш Ctrl+Z/Ctrl+Y.
|
|
168
|
-
* @param
|
|
169
|
-
* @param
|
|
170
|
+
* @param event — объект события
|
|
171
|
+
* @param event.code — код клавиши
|
|
170
172
|
*/
|
|
171
173
|
handleUndoRedoKeyUp({ code: e }) {
|
|
172
174
|
["KeyZ", "KeyY"].includes(e) && (this.isUndoRedoKeyPressed = !1);
|
|
173
175
|
}
|
|
174
176
|
/**
|
|
175
177
|
* Обработчик для выделения всех объектов (Ctrl+A).
|
|
176
|
-
* @param
|
|
177
|
-
* @param
|
|
178
|
-
* @param
|
|
179
|
-
* @param
|
|
178
|
+
* @param event — объект события
|
|
179
|
+
* @param event.ctrlKey — зажата ли клавиша Ctrl
|
|
180
|
+
* @param event.metaKey — зажата ли клавиша Cmd (для Mac)
|
|
181
|
+
* @param event.code — код клавиши
|
|
180
182
|
*/
|
|
181
183
|
handleSelectAllEvent(e) {
|
|
182
|
-
const { ctrlKey: t, metaKey:
|
|
183
|
-
!t && !
|
|
184
|
+
const { ctrlKey: t, metaKey: s, code: i } = e;
|
|
185
|
+
!t && !s || i !== "KeyA" || (e.preventDefault(), this.editor.selectionManager.selectAll());
|
|
184
186
|
}
|
|
185
187
|
/**
|
|
186
188
|
* Обработчик для удаления объектов (Delete).
|
|
187
|
-
* @param
|
|
188
|
-
* @param
|
|
189
|
+
* @param event — объект события
|
|
190
|
+
* @param event.code — код клавиши
|
|
189
191
|
*/
|
|
190
192
|
handleDeleteObjectsEvent(e) {
|
|
191
193
|
e.code === "Delete" && (e.preventDefault(), this.editor.deletionManager.deleteSelectedObjects());
|
|
@@ -193,17 +195,17 @@ class R {
|
|
|
193
195
|
/**
|
|
194
196
|
* Обработчик для нажатия пробела.
|
|
195
197
|
* Отключает выделение объектов и делает курсор "grab" для перетаскивания канваса.
|
|
196
|
-
* @param
|
|
197
|
-
* @param
|
|
198
|
+
* @param event — объект события
|
|
199
|
+
* @param event.code — код клавиши
|
|
198
200
|
*/
|
|
199
201
|
handleSpaceKeyDown(e) {
|
|
200
202
|
if (e.code !== "Space") return;
|
|
201
|
-
const { canvas: t, editor:
|
|
202
|
-
|
|
203
|
+
const { canvas: t, editor: s, isSpacePressed: i, isDragging: n } = this;
|
|
204
|
+
i || n || (this.isSpacePressed = !0, e.preventDefault(), t.set({
|
|
203
205
|
selection: !1,
|
|
204
206
|
defaultCursor: "grab"
|
|
205
|
-
}), t.setCursor("grab"),
|
|
206
|
-
|
|
207
|
+
}), t.setCursor("grab"), s.canvasManager.getObjects().forEach((a) => {
|
|
208
|
+
a.set({
|
|
207
209
|
selectable: !1,
|
|
208
210
|
evented: !1
|
|
209
211
|
});
|
|
@@ -213,8 +215,8 @@ class R {
|
|
|
213
215
|
* Обработчик для отпускания пробела.
|
|
214
216
|
* Завершает перетаскивание канваса, если оно активно.
|
|
215
217
|
* Включает выделение объектов и возвращает курсор в состояние "default".
|
|
216
|
-
* @param
|
|
217
|
-
* @param
|
|
218
|
+
* @param event — объект события
|
|
219
|
+
* @param event.code — код клавиши
|
|
218
220
|
*/
|
|
219
221
|
handleSpaceKeyUp(e) {
|
|
220
222
|
e.code === "Space" && (this.isSpacePressed = !1, this.isDragging && this.handleCanvasDragEnd(), this.canvas.set({
|
|
@@ -230,16 +232,16 @@ class R {
|
|
|
230
232
|
// --- Обработчики для событий canvas (Fabric) ---
|
|
231
233
|
/**
|
|
232
234
|
* Начало перетаскивания канваса (срабатывает при mouse:down и зажатом пробеле).
|
|
233
|
-
* @param
|
|
234
|
-
* @param
|
|
235
|
+
* @param options - событие указателя
|
|
236
|
+
* @param options.e — объект события (MouseEvent или TouchEvent)
|
|
235
237
|
*/
|
|
236
238
|
handleCanvasDragStart({ e }) {
|
|
237
239
|
!this.isSpacePressed || !(e instanceof MouseEvent) || (this.isDragging = !0, this.lastMouseX = e.clientX, this.lastMouseY = e.clientY, this.canvas.setCursor("grabbing"));
|
|
238
240
|
}
|
|
239
241
|
/**
|
|
240
242
|
* Перетаскивание канваса (mouse:move).
|
|
241
|
-
* @param
|
|
242
|
-
* @param
|
|
243
|
+
* @param options
|
|
244
|
+
* @param options.e — объект события
|
|
243
245
|
*
|
|
244
246
|
* TODO: Надо как-то ограничить область перетаскивания, чтобы канвас не уходил сильно далеко за пределы экрана
|
|
245
247
|
*/
|
|
@@ -257,18 +259,18 @@ class R {
|
|
|
257
259
|
}
|
|
258
260
|
/**
|
|
259
261
|
* Обработчик зума колесиком мыши. Работает при зажатом Ctrl или Cmd.
|
|
260
|
-
* @param
|
|
261
|
-
* @param
|
|
262
|
+
* @param options
|
|
263
|
+
* @param options.e - объект события
|
|
262
264
|
*/
|
|
263
265
|
handleMouseWheelZoom({ e }) {
|
|
264
266
|
if (!e.ctrlKey && !e.metaKey) return;
|
|
265
|
-
const
|
|
266
|
-
this.editor.transformManager.zoom(
|
|
267
|
+
const s = -e.deltaY * 1e-3;
|
|
268
|
+
this.editor.transformManager.zoom(s), e.preventDefault(), e.stopPropagation();
|
|
267
269
|
}
|
|
268
270
|
/**
|
|
269
271
|
* Обработчик, поднимающий выделенные объекты на передний план.
|
|
270
|
-
* @param
|
|
271
|
-
* @param
|
|
272
|
+
* @param event - объект события выделения
|
|
273
|
+
* @param event.selected - массив выбранных объектов
|
|
272
274
|
*/
|
|
273
275
|
handleBringToFront({ selected: e }) {
|
|
274
276
|
e != null && e.length && e.forEach((t) => {
|
|
@@ -277,7 +279,7 @@ class R {
|
|
|
277
279
|
}
|
|
278
280
|
/**
|
|
279
281
|
* Обработчик сброса объекта по двойному клику.
|
|
280
|
-
* @param
|
|
282
|
+
* @param options - объект события fabric
|
|
281
283
|
*/
|
|
282
284
|
handleResetObjectFit(e) {
|
|
283
285
|
const t = e == null ? void 0 : e.target;
|
|
@@ -296,17 +298,17 @@ class R {
|
|
|
296
298
|
* @returns новую обёртку-обработчик
|
|
297
299
|
*/
|
|
298
300
|
static debounce(e, t) {
|
|
299
|
-
let
|
|
300
|
-
return function(...
|
|
301
|
-
|
|
302
|
-
e.apply(this,
|
|
301
|
+
let s = null;
|
|
302
|
+
return function(...i) {
|
|
303
|
+
s !== null && clearTimeout(s), s = setTimeout(() => {
|
|
304
|
+
e.apply(this, i);
|
|
303
305
|
}, t);
|
|
304
306
|
};
|
|
305
307
|
}
|
|
306
308
|
}
|
|
307
|
-
class
|
|
309
|
+
class Ee {
|
|
308
310
|
/**
|
|
309
|
-
*
|
|
311
|
+
* Класс для динамической загрузки внешних модулей.
|
|
310
312
|
*/
|
|
311
313
|
constructor() {
|
|
312
314
|
this.cache = /* @__PURE__ */ new Map(), this.loaders = {
|
|
@@ -315,63 +317,50 @@ class Ne {
|
|
|
315
317
|
}
|
|
316
318
|
/**
|
|
317
319
|
* Загружает модуль по имени и сохраняет промис в кеше.
|
|
318
|
-
* @param
|
|
319
|
-
* @returns
|
|
320
|
+
* @param name — строковый литерал, например 'jspdf'.
|
|
321
|
+
* @returns Промис, который разрешается в загруженный модуль.
|
|
320
322
|
*/
|
|
321
323
|
loadModule(e) {
|
|
322
|
-
return this.loaders[e] ? (this.cache.has(e) || this.cache.set(e, this.loaders[e]()), this.cache.get(e)) : Promise.reject(new Error(
|
|
324
|
+
return this.loaders[e] ? (this.cache.has(e) || this.cache.set(e, this.loaders[e]()), this.cache.get(e)) : Promise.reject(new Error(`Unknown module "${e}"`));
|
|
323
325
|
}
|
|
324
326
|
}
|
|
325
|
-
class
|
|
327
|
+
class Oe {
|
|
326
328
|
/**
|
|
327
|
-
* @param
|
|
329
|
+
* @param scriptUrl — URL скрипта воркера.
|
|
328
330
|
* По-умолчанию использует файл рядом с этим модулем
|
|
329
331
|
*/
|
|
330
|
-
constructor() {
|
|
331
|
-
|
|
332
|
-
this.worker = new Worker(e, {
|
|
333
|
-
type: "module"
|
|
334
|
-
}), this._callbacks = /* @__PURE__ */ new Map(), this.worker.onmessage = this._handleMessage.bind(this);
|
|
332
|
+
constructor(e = new URL("" + new URL("worker.ts", import.meta.url).href, import.meta.url)) {
|
|
333
|
+
this.worker = new Worker(e, { type: "module" }), this._callbacks = /* @__PURE__ */ new Map(), this.worker.onmessage = this._handleMessage.bind(this);
|
|
335
334
|
}
|
|
336
335
|
/**
|
|
337
336
|
* Обработчик сообщений от воркера
|
|
338
|
-
* @param
|
|
339
|
-
* @param
|
|
340
|
-
* @param
|
|
341
|
-
* @param
|
|
342
|
-
* @param
|
|
343
|
-
* @param
|
|
344
|
-
* @returns
|
|
345
|
-
*/
|
|
346
|
-
_handleMessage(e) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
error: n
|
|
354
|
-
} = t, o = this._callbacks.get(a);
|
|
355
|
-
o && (s ? o.resolve(i) : o.reject(new Error(n)), this._callbacks.delete(a));
|
|
337
|
+
* @param data
|
|
338
|
+
* @param data.action - название действия
|
|
339
|
+
* @param data.requestId - уникальный идентификатор запроса
|
|
340
|
+
* @param data.success - успешность выполнения действия
|
|
341
|
+
* @param data.data - данные, которые вернул воркер
|
|
342
|
+
* @param data.error - ошибка, если она произошла
|
|
343
|
+
* @returns
|
|
344
|
+
*/
|
|
345
|
+
_handleMessage({ data: e }) {
|
|
346
|
+
const { requestId: t, success: s, data: i, error: n } = e, a = this._callbacks.get(t);
|
|
347
|
+
if (!a) {
|
|
348
|
+
console.warn(`No callback found for requestId: ${t}`);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
s ? a.resolve(i) : a.reject(new Error(n)), this._callbacks.delete(t);
|
|
356
352
|
}
|
|
357
353
|
/**
|
|
358
354
|
* Универсальный метод отправки команды в воркер
|
|
359
|
-
* @param
|
|
360
|
-
* @param
|
|
361
|
-
* @param
|
|
362
|
-
* @returns
|
|
363
|
-
*/
|
|
364
|
-
post(e, t) {
|
|
365
|
-
|
|
366
|
-
return new Promise((
|
|
367
|
-
this._callbacks.set(
|
|
368
|
-
resolve: i,
|
|
369
|
-
reject: n
|
|
370
|
-
}), this.worker.postMessage({
|
|
371
|
-
action: e,
|
|
372
|
-
payload: t,
|
|
373
|
-
requestId: s
|
|
374
|
-
}, a);
|
|
355
|
+
* @param action - название действия, которое нужно выполнить в воркере
|
|
356
|
+
* @param payload - данные, которые нужно отправить в воркер
|
|
357
|
+
* @param transferables - массив объектов, которые нужно передать в воркер
|
|
358
|
+
* @returns Promise, который будет выполнен, когда воркер вернет ответ
|
|
359
|
+
*/
|
|
360
|
+
post(e, t, s = []) {
|
|
361
|
+
const i = `${e}:${D(8)}`;
|
|
362
|
+
return new Promise((n, a) => {
|
|
363
|
+
this._callbacks.set(i, { resolve: n, reject: a }), this.worker.postMessage({ action: e, payload: t, requestId: i }, s);
|
|
375
364
|
});
|
|
376
365
|
}
|
|
377
366
|
/**
|
|
@@ -381,136 +370,112 @@ class Ee {
|
|
|
381
370
|
this.worker.terminate();
|
|
382
371
|
}
|
|
383
372
|
}
|
|
384
|
-
const
|
|
385
|
-
function
|
|
386
|
-
const
|
|
387
|
-
|
|
373
|
+
const C = 12, Te = 2, Q = 8, J = 20, ke = 100, $ = 20, K = 8, xe = 100, q = 32, ee = 1, Be = "#2B2D33", te = "#3D8BF4", se = "#FFFFFF";
|
|
374
|
+
function W(c, e, t, s, i) {
|
|
375
|
+
const n = C, a = Te;
|
|
376
|
+
c.save(), c.translate(e, t), c.rotate(R.degreesToRadians(i.angle)), c.fillStyle = se, c.strokeStyle = te, c.lineWidth = ee, c.beginPath(), c.roundRect(-12 / 2, -12 / 2, n, n, a), c.fill(), c.stroke(), c.restore();
|
|
388
377
|
}
|
|
389
|
-
function
|
|
390
|
-
const
|
|
391
|
-
|
|
378
|
+
function he(c, e, t, s, i) {
|
|
379
|
+
const n = Q, a = J, o = ke;
|
|
380
|
+
c.save(), c.translate(e, t), c.rotate(R.degreesToRadians(i.angle)), c.fillStyle = se, c.strokeStyle = te, c.lineWidth = ee, c.beginPath(), c.roundRect(-8 / 2, -20 / 2, n, a, o), c.fill(), c.stroke(), c.restore();
|
|
392
381
|
}
|
|
393
|
-
function
|
|
394
|
-
const
|
|
395
|
-
|
|
382
|
+
function ge(c, e, t, s, i) {
|
|
383
|
+
const n = $, a = K, o = xe;
|
|
384
|
+
c.save(), c.translate(e, t), c.rotate(R.degreesToRadians(i.angle)), c.fillStyle = se, c.strokeStyle = te, c.lineWidth = ee, c.beginPath(), c.roundRect(-20 / 2, -8 / 2, n, a, o), c.fill(), c.stroke(), c.restore();
|
|
396
385
|
}
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
function
|
|
400
|
-
const
|
|
401
|
-
|
|
386
|
+
const Ue = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE4Ljc1IDQuMzc1djMuNzVhLjYyNS42MjUgMCAwIDEtLjYyNS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDEgMC0xLjI1aDIuMTRsLTIuMDc3LTEuOTAzLS4wMi0uMDE5YTYuMjUgNi4yNSAwIDEgMC0uMTMgOC45NjcuNjI2LjYyNiAwIDAgMSAuODYuOTA5QTcuNDU2IDcuNDU2IDAgMCAxIDEwIDE3LjVoLS4xMDNhNy41IDcuNSAwIDEgMSA1LjM5Ni0xMi44MTJMMTcuNSA2LjcwM1Y0LjM3NWEuNjI1LjYyNSAwIDAgMSAxLjI1IDBaIi8+PC9zdmc+", ue = new Image();
|
|
387
|
+
ue.src = Ue;
|
|
388
|
+
function Ze(c, e, t, s, i) {
|
|
389
|
+
const a = q / 2;
|
|
390
|
+
c.save(), c.translate(e, t), c.rotate(R.degreesToRadians(i.angle)), c.fillStyle = Be, c.beginPath(), c.arc(0, 0, a, 0, 2 * Math.PI), c.fill(), c.drawImage(ue, -16 / 2, -16 / 2, a, a), c.restore();
|
|
402
391
|
}
|
|
403
|
-
const
|
|
392
|
+
const ze = {
|
|
404
393
|
// Угловые точки
|
|
405
394
|
tl: {
|
|
406
|
-
render:
|
|
407
|
-
sizeX:
|
|
408
|
-
sizeY:
|
|
395
|
+
render: W,
|
|
396
|
+
sizeX: C,
|
|
397
|
+
sizeY: C,
|
|
409
398
|
offsetX: 0,
|
|
410
399
|
offsetY: 0
|
|
411
400
|
},
|
|
412
401
|
tr: {
|
|
413
|
-
render:
|
|
414
|
-
sizeX:
|
|
415
|
-
sizeY:
|
|
402
|
+
render: W,
|
|
403
|
+
sizeX: C,
|
|
404
|
+
sizeY: C,
|
|
416
405
|
offsetX: 0,
|
|
417
406
|
offsetY: 0
|
|
418
407
|
},
|
|
419
408
|
bl: {
|
|
420
|
-
render:
|
|
421
|
-
sizeX:
|
|
422
|
-
sizeY:
|
|
409
|
+
render: W,
|
|
410
|
+
sizeX: C,
|
|
411
|
+
sizeY: C,
|
|
423
412
|
offsetX: 0,
|
|
424
413
|
offsetY: 0
|
|
425
414
|
},
|
|
426
415
|
br: {
|
|
427
|
-
render:
|
|
428
|
-
sizeX:
|
|
429
|
-
sizeY:
|
|
416
|
+
render: W,
|
|
417
|
+
sizeX: C,
|
|
418
|
+
sizeY: C,
|
|
430
419
|
offsetX: 0,
|
|
431
420
|
offsetY: 0
|
|
432
421
|
},
|
|
433
422
|
// Середина вертикалей
|
|
434
423
|
ml: {
|
|
435
|
-
render:
|
|
436
|
-
sizeX:
|
|
437
|
-
sizeY:
|
|
424
|
+
render: he,
|
|
425
|
+
sizeX: Q,
|
|
426
|
+
sizeY: J,
|
|
438
427
|
offsetX: 0,
|
|
439
428
|
offsetY: 0
|
|
440
429
|
},
|
|
441
430
|
mr: {
|
|
442
|
-
render:
|
|
443
|
-
sizeX:
|
|
444
|
-
sizeY:
|
|
431
|
+
render: he,
|
|
432
|
+
sizeX: Q,
|
|
433
|
+
sizeY: J,
|
|
445
434
|
offsetX: 0,
|
|
446
435
|
offsetY: 0
|
|
447
436
|
},
|
|
448
437
|
// Середина горизонталей
|
|
449
438
|
mt: {
|
|
450
|
-
render:
|
|
451
|
-
sizeX:
|
|
452
|
-
sizeY:
|
|
439
|
+
render: ge,
|
|
440
|
+
sizeX: $,
|
|
441
|
+
sizeY: K,
|
|
453
442
|
offsetX: 0,
|
|
454
443
|
offsetY: 0
|
|
455
444
|
},
|
|
456
445
|
mb: {
|
|
457
|
-
render:
|
|
458
|
-
sizeX:
|
|
459
|
-
sizeY:
|
|
446
|
+
render: ge,
|
|
447
|
+
sizeX: $,
|
|
448
|
+
sizeY: K,
|
|
460
449
|
offsetX: 0,
|
|
461
450
|
offsetY: 0
|
|
462
451
|
},
|
|
463
452
|
// Специальный «rotate» контрол
|
|
464
453
|
mtr: {
|
|
465
|
-
render:
|
|
466
|
-
sizeX:
|
|
467
|
-
sizeY:
|
|
454
|
+
render: Ze,
|
|
455
|
+
sizeX: q,
|
|
456
|
+
sizeY: q,
|
|
468
457
|
offsetX: 0,
|
|
469
458
|
offsetY: -32
|
|
470
459
|
}
|
|
471
460
|
};
|
|
472
|
-
class
|
|
461
|
+
class Re {
|
|
473
462
|
static apply() {
|
|
474
|
-
const e =
|
|
475
|
-
Object.entries(
|
|
463
|
+
const e = pe.createObjectDefaultControls();
|
|
464
|
+
Object.entries(ze).forEach(([t, s]) => {
|
|
476
465
|
Object.assign(e[t], {
|
|
477
|
-
render:
|
|
478
|
-
sizeX:
|
|
479
|
-
sizeY:
|
|
480
|
-
offsetX:
|
|
481
|
-
offsetY:
|
|
482
|
-
}), t === "mtr" && (e[t].cursorStyle = "grab", e[t].mouseDownHandler = (
|
|
466
|
+
render: s.render,
|
|
467
|
+
sizeX: s.sizeX,
|
|
468
|
+
sizeY: s.sizeY,
|
|
469
|
+
offsetX: s.offsetX,
|
|
470
|
+
offsetY: s.offsetY
|
|
471
|
+
}), t === "mtr" && (e[t].cursorStyle = "grab", e[t].mouseDownHandler = (n, a, o, d) => {
|
|
483
472
|
var l;
|
|
484
|
-
(l =
|
|
473
|
+
(l = a.target.canvas) == null || l.setCursor("grabbing");
|
|
485
474
|
});
|
|
486
|
-
}),
|
|
475
|
+
}), ye.ownDefaults.controls = e;
|
|
487
476
|
}
|
|
488
477
|
}
|
|
489
|
-
|
|
490
|
-
function ge(r, e, t, a, s, i, n) {
|
|
491
|
-
try {
|
|
492
|
-
var o = r[i](n), c = o.value;
|
|
493
|
-
} catch (d) {
|
|
494
|
-
return void t(d);
|
|
495
|
-
}
|
|
496
|
-
o.done ? e(c) : Promise.resolve(c).then(a, s);
|
|
497
|
-
}
|
|
498
|
-
function Ge(r) {
|
|
499
|
-
return function() {
|
|
500
|
-
var e = this, t = arguments;
|
|
501
|
-
return new Promise(function(a, s) {
|
|
502
|
-
var i = r.apply(e, t);
|
|
503
|
-
function n(c) {
|
|
504
|
-
ge(i, a, s, n, o, "next", c);
|
|
505
|
-
}
|
|
506
|
-
function o(c) {
|
|
507
|
-
ge(i, a, s, n, o, "throw", c);
|
|
508
|
-
}
|
|
509
|
-
n(void 0);
|
|
510
|
-
});
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
const z = {
|
|
478
|
+
const He = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNi44NzUgMi41YS42MjUuNjI1IDAgMCAwLS42MjUuNjI0VjYuMjVIMy4xMjVhLjYyNS42MjUgMCAwIDAtLjYyNS42MjV2MTBjMCAuMzQ1LjI4LjYyNS42MjUuNjI1aDEwYy4zNDUgMCAuNjI1LS4yOC42MjUtLjYyNXYtMy4xMjZoMy4xMjVjLjM0NSAwIC42MjUtLjI4LjYyNS0uNjI1di0xMGEuNjI1LjYyNSAwIDAgMC0uNjI1LS42MjVoLTEwWm02Ljg3NSAxMGgyLjVWMy43NUg3LjV2Mi41aDUuNjI1Yy4zNDUgMCAuNjI1LjI4LjYyNS42MjV2NS42MjRabS0xMCAzLjc1VjcuNWg4Ljc1djguNzVIMy43NVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", Ye = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDcuNWMwLS42OS41Ni0xLjI1IDEuMjUtMS4yNWgxMi41Yy42OSAwIDEuMjUuNTYgMS4yNSAxLjI1djguNzVjMCAuNjktLjU2IDEuMjUtMS4yNSAxLjI1SDMuNzVjLS42OSAwLTEuMjUtLjU2LTEuMjUtMS4yNVY3LjVabTEzLjc1IDBIMy43NXY4Ljc1aDEyLjVWNy41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTAgMS44NzVhMi4xODggMi4xODggMCAwIDAtMi4xODggMi4xODh2Mi44MTJhLjYyNS42MjUgMCAxIDEtMS4yNSAwVjQuMDYyYTMuNDM3IDMuNDM3IDAgMSAxIDYuODc1IDB2Mi44MTNhLjYyNS42MjUgMCAxIDEtMS4yNSAwVjQuMDYyQTIuMTg4IDIuMTg4IDAgMCAwIDEwIDEuODc2WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEwIDEyLjgxM2EuOTM3LjkzNyAwIDEgMCAwLTEuODc1LjkzNy45MzcgMCAwIDAgMCAxLjg3NFoiLz48L3N2Zz4=", We = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE2LjI1IDYuMjVINy41VjQuMzc1YTIuNSAyLjUgMCAwIDEgMi41LTIuNWMxLjIgMCAyLjI4MS44NiAyLjUxMiAyYS42MjUuNjI1IDAgMCAwIDEuMjI2LS4yNWMtLjM1NC0xLjczOC0xLjkyNS0zLTMuNzM4LTNhMy43NTQgMy43NTQgMCAwIDAtMy43NSAzLjc1VjYuMjVoLTIuNUExLjI1IDEuMjUgMCAwIDAgMi41IDcuNXY4Ljc1YTEuMjUgMS4yNSAwIDAgMCAxLjI1IDEuMjVoMTIuNWExLjI1IDEuMjUgMCAwIDAgMS4yNS0xLjI1VjcuNWExLjI1IDEuMjUgMCAwIDAtMS4yNS0xLjI1Wm0wIDEwSDMuNzVWNy41aDEyLjV2OC43NVptLTUuMzEzLTQuMzc1YS45MzcuOTM3IDAgMSAxLTEuODc0IDAgLjkzNy45MzcgMCAwIDEgMS44NzQgMFoiLz48L3N2Zz4K", _e = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTIuNSA4LjEyNSAxMCAxMi41bDcuNS00LjM3NUwxMCAzLjc1IDIuNSA4LjEyNVoiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05LjY4NSAzLjIxYS42MjUuNjI1IDAgMCAxIC42MyAwbDcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOGw3LjUtNC4zNzVaTTMuNzQgOC4xMjUgMTAgMTEuNzc2bDYuMjYtMy42NTFMMTAgNC40NzQgMy43NCA4LjEyNVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTUuNCA5LjQ2YS42MjUuNjI1IDAgMCAxIC42MyAwTDEwIDExLjc3NmwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCA5LjQ2Wm0tMS42NiAyLjQxNUwxMCAxNS41MjZsNi4yNi0zLjY1MS0xLjk3NC0xLjE1MS0zLjk3MSAyLjMxNmEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtMy45Ny0yLjMxNi0xLjk3NSAxLjE1MVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", Pe = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOS42ODUgMy4yMWEuNjI1LjYyNSAwIDAgMSAuNjMgMGw3LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhsNy41LTQuMzc1Wk0zLjc0IDguMTI1IDEwIDExLjc3Nmw2LjI2LTMuNjUxTDEwIDQuNDc0IDMuNzQgOC4xMjVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjcxNCAxMCAxMCAxMi41bDQuMjg2LTIuNSAzLjIxNCAxLjg3NUwxMCAxNi4yNWwtNy41LTQuMzc1TDUuNzE0IDEwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS40IDkuNDZhLjYyNS42MjUgMCAwIDEgLjYzIDBMMTAgMTEuNzc2bDMuOTctMi4zMTZhLjYyNS42MjUgMCAwIDEgLjYzIDBsMy4yMTUgMS44NzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhMNS40IDkuNDZabS0xLjY2IDIuNDE1TDEwIDE1LjUyNmw2LjI2LTMuNjUxLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2LTEuOTc1IDEuMTUxWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+", Fe = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTIuNSA2LjI1IDcuNSA0LjM3NSA3LjUtNC4zNzVMMTAgMS44NzUgMi41IDYuMjVaIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOS42ODUgMS4zMzVhLjYyNS42MjUgMCAwIDEgLjYzIDBsNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4bDcuNS00LjM3NVpNMy43NCA2LjI1IDEwIDkuOTAxbDYuMjYtMy42NTFMMTAgMi41OTkgMy43NCA2LjI1WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS40IDExLjMzNWEuNjI1LjYyNSAwIDAgMSAuNjMgMEwxMCAxMy42NTFsMy45Ny0yLjMxNmEuNjI1LjYyNSAwIDAgMSAuNjMgMGwzLjIxNSAxLjg3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOEw1LjQgMTEuMzM1Wk0zLjc0IDEzLjc1IDEwIDE3LjQwMWw2LjI2LTMuNjUxLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2TDMuNzQgMTMuNzVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjQgNy41ODVhLjYyNS42MjUgMCAwIDEgLjYzIDBMMTAgOS45MDFsMy45Ny0yLjMxNmEuNjI1LjYyNSAwIDAgMSAuNjMgMGwzLjIxNSAxLjg3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOEw1LjQgNy41ODVaTTMuNzQgMTAgMTAgMTMuNjUxIDE2LjI2IDEwbC0xLjk3NC0xLjE1MS0zLjk3MSAyLjMxNmEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtMy45Ny0yLjMxNkwzLjc0IDEwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+", Ve = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS45NiAxMy40MzVhLjYyNS42MjUgMCAwIDEgLjg1NS0uMjI1TDEwIDE3LjQwMWw3LjE4NS00LjE5YS42MjUuNjI1IDAgMCAxIC42MyAxLjA3OWwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEtLjIyNS0uODU1Wk05LjY4NSAxLjMzNWEuNjI1LjYyNSAwIDAgMSAuNjMgMGw3LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhsNy41LTQuMzc1Wk0zLjc0IDYuMjUgMTAgOS45MDFsNi4yNi0zLjY1MUwxMCAyLjU5OSAzLjc0IDYuMjVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Im01LjcxNCAxMS44NzUgNC4yODYgMi41IDQuMjg2LTIuNUwxNy41IDEzLjc1IDEwIDE4LjEyNSAyLjUgMTMuNzVsMy4yMTQtMS44NzVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjQgMTEuMzM1YS42MjUuNjI1IDAgMCAxIC42MyAwTDEwIDEzLjY1MWwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCAxMS4zMzVaTTMuNzQgMTMuNzUgMTAgMTcuNDAxbDYuMjYtMy42NTEtMS45NzQtMS4xNTEtMy45NzEgMi4zMTZhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTMuOTctMi4zMTZMMy43NCAxMy43NVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTUuNCA3LjU4NWEuNjI1LjYyNSAwIDAgMSAuNjMgMEwxMCA5LjkwMWwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCA3LjU4NVpNMy43NCAxMCAxMCAxMy42NTEgMTYuMjYgMTBsLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2TDMuNzQgMTBaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=", Ge = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI0VDNEU0MCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOC4xMjUgMS4yNUExLjg3NSAxLjg3NSAwIDAgMCA2LjI1IDMuMTI1di42MjVIMy4xMjVhLjYyNS42MjUgMCAwIDAgMCAxLjI1aC42MjV2MTEuMjVBMS4yNSAxLjI1IDAgMCAwIDUgMTcuNWgxMGExLjI1IDEuMjUgMCAwIDAgMS4yNS0xLjI1VjVoLjYyNWEuNjI1LjYyNSAwIDAgMCAwLTEuMjVIMTMuNzV2LS42MjVhMS44NzUgMS44NzUgMCAwIDAtMS44NzUtMS44NzVoLTMuNzVabTQuMzc1IDIuNXYtLjYyNWEuNjI1LjYyNSAwIDAgMC0uNjI1LS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDAtLjYyNS42MjV2LjYyNWg1Wk01IDE2LjI1VjVoMTB2MTEuMjVINVpNOC4xMjUgNy41Yy4zNDUgMCAuNjI1LjI4LjYyNS42MjV2NWEuNjI1LjYyNSAwIDEgMS0xLjI1IDB2LTVjMC0uMzQ1LjI4LS42MjUuNjI1LS42MjVabTQuMzc1IDUuNjI1di01YS42MjUuNjI1IDAgMCAwLTEuMjUgMHY1YS42MjUuNjI1IDAgMSAwIDEuMjUgMFoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", Z = {
|
|
514
479
|
style: {
|
|
515
480
|
position: "absolute",
|
|
516
481
|
display: "none",
|
|
@@ -545,263 +510,189 @@ const z = {
|
|
|
545
510
|
name: "Разблокировать",
|
|
546
511
|
handle: "unlock"
|
|
547
512
|
}],
|
|
548
|
-
actions: [
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
513
|
+
actions: [
|
|
514
|
+
{
|
|
515
|
+
name: "Создать копию",
|
|
516
|
+
handle: "copyPaste"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
name: "Заблокировать",
|
|
520
|
+
handle: "lock"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
name: "На передний план",
|
|
524
|
+
handle: "bringToFront"
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
name: "На задний план",
|
|
528
|
+
handle: "sendToBack"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
name: "На один уровень вверх",
|
|
532
|
+
handle: "bringForward"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "На один уровень вниз",
|
|
536
|
+
handle: "sendBackwards"
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
name: "Удалить",
|
|
540
|
+
handle: "delete"
|
|
541
|
+
}
|
|
542
|
+
],
|
|
570
543
|
offsetTop: 50,
|
|
571
544
|
icons: {
|
|
572
|
-
copyPaste:
|
|
573
|
-
delete:
|
|
574
|
-
lock:
|
|
575
|
-
unlock:
|
|
576
|
-
bringToFront:
|
|
577
|
-
sendToBack:
|
|
578
|
-
bringForward:
|
|
545
|
+
copyPaste: He,
|
|
546
|
+
delete: Ge,
|
|
547
|
+
lock: Ye,
|
|
548
|
+
unlock: We,
|
|
549
|
+
bringToFront: Fe,
|
|
550
|
+
sendToBack: Ve,
|
|
551
|
+
bringForward: _e,
|
|
579
552
|
sendBackwards: Pe
|
|
580
553
|
},
|
|
581
554
|
handlers: {
|
|
582
|
-
copyPaste: function() {
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
return r.apply(this, arguments);
|
|
588
|
-
}
|
|
589
|
-
return e;
|
|
590
|
-
}(),
|
|
591
|
-
delete: (r) => {
|
|
592
|
-
r.deletionManager.deleteSelectedObjects();
|
|
555
|
+
copyPaste: (c) => I(void 0, null, function* () {
|
|
556
|
+
yield c.clipboardManager.copy(), yield c.clipboardManager.paste();
|
|
557
|
+
}),
|
|
558
|
+
delete: (c) => {
|
|
559
|
+
c.deletionManager.deleteSelectedObjects();
|
|
593
560
|
},
|
|
594
|
-
lock: (
|
|
595
|
-
|
|
561
|
+
lock: (c) => {
|
|
562
|
+
c.objectLockManager.lockObject();
|
|
596
563
|
},
|
|
597
|
-
unlock: (
|
|
598
|
-
|
|
564
|
+
unlock: (c) => {
|
|
565
|
+
c.objectLockManager.unlockObject();
|
|
599
566
|
},
|
|
600
|
-
bringForward: (
|
|
601
|
-
|
|
567
|
+
bringForward: (c) => {
|
|
568
|
+
c.layerManager.bringForward();
|
|
602
569
|
},
|
|
603
|
-
bringToFront: (
|
|
604
|
-
|
|
570
|
+
bringToFront: (c) => {
|
|
571
|
+
c.layerManager.bringToFront();
|
|
605
572
|
},
|
|
606
|
-
sendToBack: (
|
|
607
|
-
|
|
573
|
+
sendToBack: (c) => {
|
|
574
|
+
c.layerManager.sendToBack();
|
|
608
575
|
},
|
|
609
|
-
sendBackwards: (
|
|
610
|
-
|
|
576
|
+
sendBackwards: (c) => {
|
|
577
|
+
c.layerManager.sendBackwards();
|
|
611
578
|
}
|
|
612
579
|
}
|
|
613
580
|
};
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
var a = Object.getOwnPropertySymbols(r);
|
|
618
|
-
e && (a = a.filter(function(s) {
|
|
619
|
-
return Object.getOwnPropertyDescriptor(r, s).enumerable;
|
|
620
|
-
})), t.push.apply(t, a);
|
|
621
|
-
}
|
|
622
|
-
return t;
|
|
623
|
-
}
|
|
624
|
-
function p(r) {
|
|
625
|
-
for (var e = 1; e < arguments.length; e++) {
|
|
626
|
-
var t = arguments[e] != null ? arguments[e] : {};
|
|
627
|
-
e % 2 ? ue(Object(t), !0).forEach(function(a) {
|
|
628
|
-
Xe(r, a, t[a]);
|
|
629
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(r, Object.getOwnPropertyDescriptors(t)) : ue(Object(t)).forEach(function(a) {
|
|
630
|
-
Object.defineProperty(r, a, Object.getOwnPropertyDescriptor(t, a));
|
|
631
|
-
});
|
|
581
|
+
class Xe {
|
|
582
|
+
constructor({ editor: e }) {
|
|
583
|
+
this.currentTarget = null, this.currentLocked = !1, this.isTransforming = !1, this.editor = e, this.canvas = e.canvas, this.options = e.options, this._initToolbar();
|
|
632
584
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
var t = r[Symbol.toPrimitive];
|
|
645
|
-
if (t !== void 0) {
|
|
646
|
-
var a = t.call(r, e);
|
|
647
|
-
if (typeof a != "object") return a;
|
|
648
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
649
|
-
}
|
|
650
|
-
return (e === "string" ? String : Number)(r);
|
|
651
|
-
}
|
|
652
|
-
class $e {
|
|
653
|
-
/**
|
|
654
|
-
* @param {object} options
|
|
655
|
-
* @param {ImageEditor} options.editor - экземпляр редактора с доступом к canvas
|
|
656
|
-
*/
|
|
657
|
-
constructor(e) {
|
|
658
|
-
var {
|
|
659
|
-
editor: t
|
|
660
|
-
} = e;
|
|
661
|
-
if (this.options = t.options, !!this.options.showToolbar) {
|
|
662
|
-
this.editor = t, this.canvas = t.canvas;
|
|
663
|
-
var a = this.options.toolbar || {};
|
|
664
|
-
this.config = p(p(p({}, z), a), {}, {
|
|
665
|
-
style: p(p({}, z.style), a.style || {}),
|
|
666
|
-
btnStyle: p(p({}, z.btnStyle), a.btnStyle || {}),
|
|
667
|
-
icons: p(p({}, z.icons), a.icons || {}),
|
|
668
|
-
handlers: p(p({}, z.handlers), a.handlers || {})
|
|
669
|
-
}), this.currentTarget = null, this.currentLocked = null, this.isTransforming = !1, this._onMouseDown = this._handleMouseDown.bind(this), this._onObjectMoving = this._startTransform.bind(this), this._onObjectScaling = this._startTransform.bind(this), this._onObjectRotating = this._startTransform.bind(this), this._onMouseUp = this._endTransform.bind(this), this._onObjectModified = this._endTransform.bind(this), this._onSelectionChange = this._updateToolbar.bind(this), this._onSelectionClear = () => {
|
|
670
|
-
this.el.style.display = "none";
|
|
671
|
-
}, this._createDOM(), this._bindEvents();
|
|
672
|
-
}
|
|
585
|
+
_initToolbar() {
|
|
586
|
+
if (!this.options.showToolbar) return;
|
|
587
|
+
const e = this.options.toolbar || {};
|
|
588
|
+
this.config = le(f(f({}, Z), e), {
|
|
589
|
+
style: f(f({}, Z.style), e.style || {}),
|
|
590
|
+
btnStyle: f(f({}, Z.btnStyle), e.btnStyle || {}),
|
|
591
|
+
icons: f(f({}, Z.icons), e.icons || {}),
|
|
592
|
+
handlers: f(f({}, Z.handlers), e.handlers || {})
|
|
593
|
+
}), this.currentTarget = null, this.currentLocked = !1, this.isTransforming = !1, this._onMouseDown = this._handleMouseDown.bind(this), this._onObjectMoving = this._startTransform.bind(this), this._onObjectScaling = this._startTransform.bind(this), this._onObjectRotating = this._startTransform.bind(this), this._onMouseUp = this._endTransform.bind(this), this._onObjectModified = this._endTransform.bind(this), this._onSelectionChange = this._updateToolbar.bind(this), this._onSelectionClear = () => {
|
|
594
|
+
this.el.style.display = "none";
|
|
595
|
+
}, this._createDOM(), this._bindEvents();
|
|
673
596
|
}
|
|
674
597
|
/**
|
|
675
598
|
* Создаёт DOM элемент панели инструментов и добавляет его в canvas
|
|
676
|
-
* @private
|
|
677
599
|
*/
|
|
678
600
|
_createDOM() {
|
|
679
|
-
|
|
680
|
-
style: e
|
|
681
|
-
} = this.config;
|
|
601
|
+
const { style: e } = this.config;
|
|
682
602
|
this.el = document.createElement("div"), Object.assign(this.el.style, e), this.canvas.wrapperEl.appendChild(this.el), this._onBtnOver = (t) => {
|
|
683
|
-
|
|
684
|
-
|
|
603
|
+
const i = t.target.closest("button");
|
|
604
|
+
i && Object.assign(i.style, this.config.btnHover);
|
|
685
605
|
}, this._onBtnOut = (t) => {
|
|
686
|
-
|
|
687
|
-
|
|
606
|
+
const i = t.target.closest("button");
|
|
607
|
+
i && Object.assign(i.style, this.config.btnStyle);
|
|
688
608
|
}, this.el.addEventListener("mouseover", this._onBtnOver), this.el.addEventListener("mouseout", this._onBtnOut);
|
|
689
609
|
}
|
|
690
610
|
/**
|
|
691
611
|
* Отрисовывает кнопки панели инструментов
|
|
692
|
-
* @
|
|
693
|
-
* @param
|
|
694
|
-
* @param
|
|
695
|
-
* @param {string} actions[].handle - название обработчика
|
|
612
|
+
* @param actions - массив действий для отрисовки
|
|
613
|
+
* @param actions[].name - название действия
|
|
614
|
+
* @param actions[].handle - название обработчика
|
|
696
615
|
*/
|
|
697
616
|
_renderButtons(e) {
|
|
698
|
-
var t = this;
|
|
699
617
|
this.el.innerHTML = "";
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
handlers: l
|
|
708
|
-
} = t.config, h = document.createElement("button");
|
|
709
|
-
h.innerHTML = c[o] ? '<img src="'.concat(c[o], '" title="').concat(n, '" />') : n, Object.assign(h.style, d), h.onclick = () => {
|
|
710
|
-
var g;
|
|
711
|
-
return (g = l[o]) === null || g === void 0 ? void 0 : g.call(l, t.editor);
|
|
712
|
-
}, t.el.appendChild(h);
|
|
713
|
-
};
|
|
714
|
-
for (var s of e)
|
|
715
|
-
a();
|
|
618
|
+
for (const t of e) {
|
|
619
|
+
const { name: s, handle: i } = t, { icons: n = {}, btnStyle: a, handlers: o = {} } = this.config, d = document.createElement("button");
|
|
620
|
+
d.innerHTML = n[i] ? `<img src="${n[i]}" title="${s}" />` : s, Object.assign(d.style, a), d.onclick = () => {
|
|
621
|
+
var r;
|
|
622
|
+
return (r = o[i]) == null ? void 0 : r.call(o, this.editor);
|
|
623
|
+
}, this.el.appendChild(d);
|
|
624
|
+
}
|
|
716
625
|
}
|
|
717
626
|
/**
|
|
718
627
|
* Привязывает события к canvas
|
|
719
|
-
* @private
|
|
720
628
|
*/
|
|
721
629
|
_bindEvents() {
|
|
722
|
-
this.canvas.on("mouse:down", this._onMouseDown), this.canvas.on("object:moving", this._onObjectMoving), this.canvas.on("object:scaling", this._onObjectScaling), this.canvas.on("object:rotating", this._onObjectRotating), this.canvas.on("mouse:up", this._onMouseUp), this.canvas.on("object:modified", this._onObjectModified), this.canvas.on("selection:created", this._onSelectionChange), this.canvas.on("selection:updated", this._onSelectionChange), this.canvas.on("
|
|
630
|
+
this.canvas.on("mouse:down", this._onMouseDown), this.canvas.on("object:moving", this._onObjectMoving), this.canvas.on("object:scaling", this._onObjectScaling), this.canvas.on("object:rotating", this._onObjectRotating), this.canvas.on("mouse:up", this._onMouseUp), this.canvas.on("object:modified", this._onObjectModified), this.canvas.on("selection:created", this._onSelectionChange), this.canvas.on("selection:updated", this._onSelectionChange), this.canvas.on("after:render", this._onSelectionChange), this.canvas.on("selection:cleared", this._onSelectionClear);
|
|
723
631
|
}
|
|
724
632
|
/**
|
|
725
633
|
* На время трансформации скрываем тулбар
|
|
726
|
-
* @private
|
|
727
|
-
* @param {Object} opt - объект события
|
|
728
634
|
*/
|
|
729
635
|
_handleMouseDown(e) {
|
|
730
636
|
var t;
|
|
731
|
-
(t = e.transform)
|
|
637
|
+
(t = e.transform) != null && t.actionPerformed && this._startTransform();
|
|
732
638
|
}
|
|
733
639
|
/**
|
|
734
640
|
* Начало трансформации объекта
|
|
735
|
-
* @private
|
|
736
641
|
*/
|
|
737
642
|
_startTransform() {
|
|
738
643
|
this.isTransforming = !0, this.el.style.display = "none";
|
|
739
644
|
}
|
|
740
645
|
/**
|
|
741
646
|
* Завершение трансформации объекта
|
|
742
|
-
* @private
|
|
743
647
|
*/
|
|
744
648
|
_endTransform() {
|
|
745
649
|
this.isTransforming = !1, this._updatePos();
|
|
746
650
|
}
|
|
747
651
|
/**
|
|
748
652
|
* Обновляет панель инструментов в зависимости от выделенного объекта и его состояния
|
|
749
|
-
* @private
|
|
750
653
|
*/
|
|
751
654
|
_updateToolbar() {
|
|
752
|
-
if (
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
}
|
|
758
|
-
var t = !!e.locked;
|
|
759
|
-
if (e !== this.currentTarget || t !== this.currentLocked) {
|
|
760
|
-
this.currentTarget = e, this.currentLocked = t;
|
|
761
|
-
var a = t ? this.config.lockedActions : this.config.actions;
|
|
762
|
-
this._renderButtons(a);
|
|
763
|
-
}
|
|
764
|
-
this._updatePos();
|
|
655
|
+
if (this.isTransforming) return;
|
|
656
|
+
const e = this.canvas.getActiveObject();
|
|
657
|
+
if (!e) {
|
|
658
|
+
this.el.style.display = "none", this.currentTarget = null;
|
|
659
|
+
return;
|
|
765
660
|
}
|
|
661
|
+
const t = !!e.locked;
|
|
662
|
+
if (e !== this.currentTarget || t !== this.currentLocked) {
|
|
663
|
+
this.currentTarget = e, this.currentLocked = t;
|
|
664
|
+
const s = t ? this.config.lockedActions : this.config.actions;
|
|
665
|
+
this._renderButtons(s != null ? s : []);
|
|
666
|
+
}
|
|
667
|
+
this._updatePos();
|
|
766
668
|
}
|
|
767
669
|
/**
|
|
768
670
|
* Обновляет позицию панели инструментов в зависимости от положения выделенного объекта
|
|
769
|
-
* @private
|
|
770
671
|
*/
|
|
771
672
|
_updatePos() {
|
|
772
|
-
if (
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
}
|
|
778
|
-
var {
|
|
779
|
-
el: t,
|
|
780
|
-
config: a,
|
|
781
|
-
canvas: s
|
|
782
|
-
} = this;
|
|
783
|
-
e.setCoords();
|
|
784
|
-
var i = s.getZoom(), [, , , , n, o] = s.viewportTransform, {
|
|
785
|
-
x: c
|
|
786
|
-
} = e.getCenterPoint(), {
|
|
787
|
-
top: d,
|
|
788
|
-
height: l
|
|
789
|
-
} = e.getBoundingRect(!1, !0), h = c * i + n, g = h - t.offsetWidth / 2, u = (d + l) * i + o + a.offsetTop;
|
|
790
|
-
Object.assign(t.style, {
|
|
791
|
-
left: "".concat(g, "px"),
|
|
792
|
-
top: "".concat(u, "px"),
|
|
793
|
-
display: "flex"
|
|
794
|
-
});
|
|
673
|
+
if (this.isTransforming) return;
|
|
674
|
+
const e = this.canvas.getActiveObject();
|
|
675
|
+
if (!e) {
|
|
676
|
+
this.el.style.display = "none";
|
|
677
|
+
return;
|
|
795
678
|
}
|
|
679
|
+
const { el: t, config: s, canvas: i } = this;
|
|
680
|
+
e.setCoords();
|
|
681
|
+
const n = i.getZoom(), [, , , , a, o] = i.viewportTransform, { x: d } = e.getCenterPoint(), { top: r, height: l } = e.getBoundingRect(), g = d * n + a - t.offsetWidth / 2, u = s.offsetTop || 0, m = (r + l) * n + o + u;
|
|
682
|
+
Object.assign(t.style, {
|
|
683
|
+
left: `${g}px`,
|
|
684
|
+
top: `${m}px`,
|
|
685
|
+
display: "flex"
|
|
686
|
+
});
|
|
796
687
|
}
|
|
797
688
|
/**
|
|
798
689
|
* Удаляет слушатели событий и DOM элемент панели инструментов
|
|
799
690
|
*/
|
|
800
691
|
destroy() {
|
|
801
|
-
this.el.removeEventListener("mouseover", this._onBtnOver), this.el.removeEventListener("mouseout", this._onBtnOut), this.canvas.off("mouse:down", this._onMouseDown), this.canvas.off("object:moving", this._onObjectMoving), this.canvas.off("object:scaling", this._onObjectScaling), this.canvas.off("object:rotating", this._onObjectRotating), this.canvas.off("mouse:up", this._onMouseUp), this.canvas.off("object:modified", this._onObjectModified), this.canvas.off("selection:created", this._onSelectionChange), this.canvas.off("selection:updated", this._onSelectionChange), this.canvas.off("
|
|
692
|
+
this.el.removeEventListener("mouseover", this._onBtnOver), this.el.removeEventListener("mouseout", this._onBtnOut), this.canvas.off("mouse:down", this._onMouseDown), this.canvas.off("object:moving", this._onObjectMoving), this.canvas.off("object:scaling", this._onObjectScaling), this.canvas.off("object:rotating", this._onObjectRotating), this.canvas.off("mouse:up", this._onMouseUp), this.canvas.off("object:modified", this._onObjectModified), this.canvas.off("selection:created", this._onSelectionChange), this.canvas.off("selection:updated", this._onSelectionChange), this.canvas.off("after:render", this._onSelectionChange), this.canvas.off("selection:cleared", this._onSelectionClear), this.el.remove();
|
|
802
693
|
}
|
|
803
694
|
}
|
|
804
|
-
class
|
|
695
|
+
class Qe {
|
|
805
696
|
constructor({ editor: e }) {
|
|
806
697
|
this.editor = e, this.canvas = e.canvas, this._historySuspendCount = 0, this.baseState = null, this.patches = [], this.currentIndex = 0, this.maxHistoryLength = e.options.maxHistoryLength, this.totalChangesCount = 0, this.baseStateChangesCount = 0, this._createDiffPatcher();
|
|
807
698
|
}
|
|
@@ -837,7 +728,7 @@ class Ke {
|
|
|
837
728
|
includeValueOnMove: !1
|
|
838
729
|
},
|
|
839
730
|
textDiff: {
|
|
840
|
-
diffMatchPatch:
|
|
731
|
+
diffMatchPatch: Le,
|
|
841
732
|
minLength: 60
|
|
842
733
|
}
|
|
843
734
|
});
|
|
@@ -852,14 +743,12 @@ class Ke {
|
|
|
852
743
|
}
|
|
853
744
|
/**
|
|
854
745
|
* Проверяет, есть ли в редакторе несохранённые изменения
|
|
855
|
-
* @returns {boolean}
|
|
856
746
|
*/
|
|
857
747
|
hasUnsavedChanges() {
|
|
858
748
|
return this.totalChangesCount > 0;
|
|
859
749
|
}
|
|
860
750
|
/**
|
|
861
751
|
* Получает текущую позицию в общей истории изменений
|
|
862
|
-
* @returns {number}
|
|
863
752
|
*/
|
|
864
753
|
getCurrentChangePosition() {
|
|
865
754
|
return this.baseStateChangesCount + this.currentIndex;
|
|
@@ -868,11 +757,11 @@ class Ke {
|
|
|
868
757
|
* Получаем полное состояние, применяя все диффы к базовому состоянию.
|
|
869
758
|
*/
|
|
870
759
|
getFullState() {
|
|
871
|
-
const { baseState: e, currentIndex: t, patches:
|
|
872
|
-
let
|
|
873
|
-
for (let
|
|
874
|
-
|
|
875
|
-
return console.log("getFullState state",
|
|
760
|
+
const { baseState: e, currentIndex: t, patches: s } = this;
|
|
761
|
+
let i = JSON.parse(JSON.stringify(e));
|
|
762
|
+
for (let n = 0; n < t; n += 1)
|
|
763
|
+
i = this.diffPatcher.patch(i, s[n].diff);
|
|
764
|
+
return console.log("getFullState state", i), i;
|
|
876
765
|
}
|
|
877
766
|
/**
|
|
878
767
|
* Сохраняем текущее состояние в виде диффа от последнего сохранённого полного состояния.
|
|
@@ -900,28 +789,28 @@ class Ke {
|
|
|
900
789
|
this.baseState = e, this.patches = [], this.currentIndex = 0, console.log("Базовое состояние сохранено.");
|
|
901
790
|
return;
|
|
902
791
|
}
|
|
903
|
-
const t = this.getFullState(),
|
|
904
|
-
if (!
|
|
792
|
+
const t = this.getFullState(), s = this.diffPatcher.diff(t, e);
|
|
793
|
+
if (!s) {
|
|
905
794
|
console.log("Нет изменений для сохранения.");
|
|
906
795
|
return;
|
|
907
796
|
}
|
|
908
|
-
console.log("baseState", this.baseState), this.currentIndex < this.patches.length && this.patches.splice(this.currentIndex), console.log("diff",
|
|
797
|
+
console.log("baseState", this.baseState), this.currentIndex < this.patches.length && this.patches.splice(this.currentIndex), console.log("diff", s), this.totalChangesCount += 1, this.patches.push({ id: D(), diff: s }), this.currentIndex += 1, this.patches.length > this.maxHistoryLength && (this.baseState = this.diffPatcher.patch(this.baseState, this.patches[0].diff), this.patches.shift(), this.currentIndex -= 1, this.baseStateChangesCount += 1), console.log("Состояние сохранено. Текущий индекс истории:", this.currentIndex);
|
|
909
798
|
}
|
|
910
799
|
/**
|
|
911
800
|
* Функция загрузки состояния в канвас.
|
|
912
|
-
* @param
|
|
801
|
+
* @param fullState - полное состояние канваса
|
|
913
802
|
* @fires editor:history-state-loaded
|
|
914
803
|
*/
|
|
915
804
|
loadStateFromFullState(e) {
|
|
916
|
-
return
|
|
805
|
+
return I(this, null, function* () {
|
|
917
806
|
if (!e) return;
|
|
918
807
|
console.log("loadStateFromFullState fullState", e);
|
|
919
|
-
const { canvas: t, canvasManager:
|
|
808
|
+
const { canvas: t, canvasManager: s, interactionBlocker: i } = this.editor, { width: n, height: a } = t;
|
|
920
809
|
yield t.loadFromJSON(e);
|
|
921
|
-
const o = t.getObjects().find((
|
|
922
|
-
o && (this.editor.montageArea = o, (
|
|
923
|
-
const
|
|
924
|
-
|
|
810
|
+
const o = t.getObjects().find((r) => r.id === "montage-area");
|
|
811
|
+
o && (this.editor.montageArea = o, (n !== e.width || a !== e.height) && s.updateCanvasAndFitObjects());
|
|
812
|
+
const d = t.getObjects().find((r) => r.id === "overlay-mask");
|
|
813
|
+
d && (i.overlayMask = d, i.overlayMask.visible = !1), t.renderAll(), t.fire("editor:history-state-loaded", {
|
|
925
814
|
fullState: e,
|
|
926
815
|
currentIndex: this.currentIndex,
|
|
927
816
|
totalChangesCount: this.totalChangesCount,
|
|
@@ -936,7 +825,7 @@ class Ke {
|
|
|
936
825
|
* @fires editor:undo
|
|
937
826
|
*/
|
|
938
827
|
undo() {
|
|
939
|
-
return
|
|
828
|
+
return I(this, null, function* () {
|
|
940
829
|
if (!this.skipHistory) {
|
|
941
830
|
if (this.currentIndex <= 0) {
|
|
942
831
|
console.log("Нет предыдущих состояний для отмены.");
|
|
@@ -973,7 +862,7 @@ class Ke {
|
|
|
973
862
|
* @fires editor:redo
|
|
974
863
|
*/
|
|
975
864
|
redo() {
|
|
976
|
-
return
|
|
865
|
+
return I(this, null, function* () {
|
|
977
866
|
if (!this.skipHistory) {
|
|
978
867
|
if (this.currentIndex >= this.patches.length) {
|
|
979
868
|
console.log("Нет состояний для повтора.");
|
|
@@ -1006,8 +895,8 @@ class Ke {
|
|
|
1006
895
|
});
|
|
1007
896
|
}
|
|
1008
897
|
}
|
|
1009
|
-
const
|
|
1010
|
-
class
|
|
898
|
+
const Je = 0.1, $e = 2, Ke = 0.1, qe = 90, x = 16, B = 16, O = 4096, T = 4096;
|
|
899
|
+
class N {
|
|
1011
900
|
constructor({ editor: e }) {
|
|
1012
901
|
this.editor = e, this.options = e.options, this._createdBlobUrls = [], this.acceptContentTypes = this.editor.options.acceptContentTypes, this.acceptFormats = this.getAllowedFormatsFromContentTypes();
|
|
1013
902
|
}
|
|
@@ -1023,81 +912,82 @@ class C {
|
|
|
1023
912
|
* @param options.withoutSave - Не сохранять в историю изменений
|
|
1024
913
|
* @returns возвращает Promise с объектом изображения или null в случае ошибки
|
|
1025
914
|
*/
|
|
1026
|
-
importImage(
|
|
1027
|
-
return
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
915
|
+
importImage(e) {
|
|
916
|
+
return I(this, null, function* () {
|
|
917
|
+
const {
|
|
918
|
+
source: t,
|
|
919
|
+
scale: s = `image-${this.options.scaleType}`,
|
|
920
|
+
withoutSave: i = !1
|
|
921
|
+
} = e;
|
|
922
|
+
if (!t) return null;
|
|
923
|
+
const { canvas: n, montageArea: a, transformManager: o, historyManager: d, errorManager: r } = this.editor, l = yield this.getContentType(t), h = N.getFormatFromContentType(l), { acceptContentTypes: g, acceptFormats: u } = this;
|
|
1034
924
|
if (!this.isAllowedContentType(l)) {
|
|
1035
925
|
const m = `Неверный contentType для изображения: ${l}. Ожидается один из: ${this.acceptContentTypes.join(", ")}.`;
|
|
1036
|
-
return
|
|
926
|
+
return r.emitError({
|
|
1037
927
|
origin: "ImageManager",
|
|
1038
928
|
method: "importImage",
|
|
1039
929
|
code: "INVALID_CONTENT_TYPE",
|
|
1040
930
|
message: m,
|
|
1041
|
-
data: { source:
|
|
931
|
+
data: { source: t, format: h, contentType: l, acceptContentTypes: g, acceptFormats: u }
|
|
1042
932
|
}), null;
|
|
1043
933
|
}
|
|
1044
|
-
|
|
934
|
+
d.suspendHistory();
|
|
1045
935
|
try {
|
|
1046
936
|
let m, M;
|
|
1047
|
-
if (
|
|
1048
|
-
m = URL.createObjectURL(
|
|
1049
|
-
else if (typeof
|
|
1050
|
-
const
|
|
1051
|
-
m = URL.createObjectURL(
|
|
937
|
+
if (t instanceof File)
|
|
938
|
+
m = URL.createObjectURL(t);
|
|
939
|
+
else if (typeof t == "string") {
|
|
940
|
+
const A = yield (yield fetch(t, { mode: "cors" })).blob();
|
|
941
|
+
m = URL.createObjectURL(A);
|
|
1052
942
|
} else
|
|
1053
|
-
return
|
|
943
|
+
return r.emitError({
|
|
1054
944
|
origin: "ImageManager",
|
|
1055
945
|
method: "importImage",
|
|
1056
946
|
code: "INVALID_SOURCE_TYPE",
|
|
1057
947
|
message: "Неверный тип источника изображения. Ожидается URL или объект File.",
|
|
1058
|
-
data: { source:
|
|
948
|
+
data: { source: t, format: h, contentType: l, acceptContentTypes: g, acceptFormats: u }
|
|
1059
949
|
}), null;
|
|
1060
950
|
if (this._createdBlobUrls.push(m), h === "svg") {
|
|
1061
|
-
const
|
|
1062
|
-
M =
|
|
951
|
+
const y = yield Ie(m);
|
|
952
|
+
M = R.groupSVGElements(y.objects, y.options);
|
|
1063
953
|
} else
|
|
1064
|
-
M = yield
|
|
1065
|
-
const { width: j, height:
|
|
1066
|
-
if (M instanceof
|
|
1067
|
-
const
|
|
1068
|
-
let
|
|
1069
|
-
if (
|
|
1070
|
-
const
|
|
1071
|
-
this._createdBlobUrls.push(
|
|
1072
|
-
} else if (
|
|
1073
|
-
const
|
|
1074
|
-
this._createdBlobUrls.push(
|
|
954
|
+
M = yield U.fromURL(m, { crossOrigin: "anonymous" });
|
|
955
|
+
const { width: j, height: b } = M;
|
|
956
|
+
if (M instanceof U) {
|
|
957
|
+
const y = M.getElement();
|
|
958
|
+
let A = "";
|
|
959
|
+
if (y instanceof HTMLImageElement ? A = y.src : y instanceof HTMLCanvasElement && (A = y.toDataURL()), b > T || j > O) {
|
|
960
|
+
const w = yield this.resizeImageToBoundaries(A, "max"), E = URL.createObjectURL(w);
|
|
961
|
+
this._createdBlobUrls.push(E), M = yield U.fromURL(E, { crossOrigin: "anonymous" });
|
|
962
|
+
} else if (b < B || j < x) {
|
|
963
|
+
const w = yield this.resizeImageToBoundaries(A, "min"), E = URL.createObjectURL(w);
|
|
964
|
+
this._createdBlobUrls.push(E), M = yield U.fromURL(E, { crossOrigin: "anonymous" });
|
|
1075
965
|
}
|
|
1076
966
|
}
|
|
1077
|
-
if (M.set("id", `${M.type}-${D()}`), M.set("format", h),
|
|
967
|
+
if (M.set("id", `${M.type}-${D()}`), M.set("format", h), s === "scale-montage")
|
|
1078
968
|
this.editor.canvasManager.scaleMontageAreaToImage({ object: M, withoutSave: !0 });
|
|
1079
969
|
else {
|
|
1080
|
-
const { width:
|
|
1081
|
-
|
|
970
|
+
const { width: y, height: A } = a, w = this.calculateScaleFactor({ imageObject: M, scaleType: s });
|
|
971
|
+
s === "image-contain" && w < 1 ? o.fitObject({ object: M, type: "contain", withoutSave: !0 }) : s === "image-cover" && (j > y || b > A) && o.fitObject({ object: M, type: "cover", withoutSave: !0 });
|
|
1082
972
|
}
|
|
1083
|
-
|
|
1084
|
-
const
|
|
973
|
+
n.add(M), n.centerObject(M), n.setActiveObject(M), n.renderAll(), d.resumeHistory(), i || d.saveState();
|
|
974
|
+
const L = {
|
|
1085
975
|
image: M,
|
|
1086
976
|
format: h,
|
|
1087
977
|
contentType: l,
|
|
1088
|
-
scale:
|
|
1089
|
-
withoutSave:
|
|
1090
|
-
source:
|
|
978
|
+
scale: s,
|
|
979
|
+
withoutSave: i,
|
|
980
|
+
source: t
|
|
1091
981
|
};
|
|
1092
|
-
return
|
|
982
|
+
return n.fire("editor:image-imported", L), L;
|
|
1093
983
|
} catch (m) {
|
|
1094
|
-
return
|
|
984
|
+
return r.emitError({
|
|
1095
985
|
origin: "ImageManager",
|
|
1096
986
|
method: "importImage",
|
|
1097
987
|
code: "IMPORT_FAILED",
|
|
1098
988
|
message: `Ошибка импорта изображения: ${m.message}`,
|
|
1099
|
-
data: { source:
|
|
1100
|
-
}),
|
|
989
|
+
data: { source: t, format: h, contentType: l, scale: s, withoutSave: i }
|
|
990
|
+
}), d.resumeHistory(), null;
|
|
1101
991
|
}
|
|
1102
992
|
});
|
|
1103
993
|
}
|
|
@@ -1105,29 +995,29 @@ class C {
|
|
|
1105
995
|
* Функция для ресайза изображения до максимальных размеров,
|
|
1106
996
|
* если оно их превышает. Сохраняет пропорции.
|
|
1107
997
|
*
|
|
1108
|
-
* @param
|
|
1109
|
-
* @param
|
|
1110
|
-
* @returns
|
|
998
|
+
* @param dataURL - dataURL изображения
|
|
999
|
+
* @param size ('max | min') - максимальный или минимальный размер
|
|
1000
|
+
* @returns возвращает Promise с Blob-объектом уменьшенного изображения
|
|
1111
1001
|
*/
|
|
1112
1002
|
resizeImageToBoundaries(e, t = "max") {
|
|
1113
|
-
return
|
|
1114
|
-
let
|
|
1115
|
-
t === "min" && (
|
|
1116
|
-
const
|
|
1003
|
+
return I(this, null, function* () {
|
|
1004
|
+
let s = `Размер изображения больше максимального размера канваса, поэтому оно будет уменьшено до максимальных размеров c сохранением пропорций: ${O}x${T}`;
|
|
1005
|
+
t === "min" && (s = `Размер изображения меньше минимального размера канваса, поэтому оно будет увеличено до минимальных размеров c сохранением пропорций: ${x}x${B}`);
|
|
1006
|
+
const i = {
|
|
1117
1007
|
dataURL: e,
|
|
1118
1008
|
sizeType: t,
|
|
1119
1009
|
maxWidth: O,
|
|
1120
1010
|
maxHeight: T,
|
|
1121
|
-
minWidth:
|
|
1122
|
-
minHeight:
|
|
1011
|
+
minWidth: x,
|
|
1012
|
+
minHeight: B
|
|
1123
1013
|
};
|
|
1124
1014
|
return this.editor.errorManager.emitWarning({
|
|
1125
1015
|
origin: "ImageManager",
|
|
1126
1016
|
method: "resizeImageToBoundaries",
|
|
1127
1017
|
code: "IMAGE_RESIZE_WARNING",
|
|
1128
|
-
message:
|
|
1129
|
-
data:
|
|
1130
|
-
}), this.editor.workerManager.post("resizeImage",
|
|
1018
|
+
message: s,
|
|
1019
|
+
data: i
|
|
1020
|
+
}), this.editor.workerManager.post("resizeImage", i);
|
|
1131
1021
|
});
|
|
1132
1022
|
}
|
|
1133
1023
|
/**
|
|
@@ -1142,101 +1032,101 @@ class C {
|
|
|
1142
1032
|
* @fires editor:canvas-exported
|
|
1143
1033
|
*/
|
|
1144
1034
|
exportCanvasAsImageFile() {
|
|
1145
|
-
return
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1035
|
+
return I(this, arguments, function* (e = {}) {
|
|
1036
|
+
const {
|
|
1037
|
+
fileName: t = "image.png",
|
|
1038
|
+
contentType: s = "image/png",
|
|
1039
|
+
exportAsBase64: i = !1,
|
|
1040
|
+
exportAsBlob: n = !1
|
|
1041
|
+
} = e, { canvas: a, montageArea: o, workerManager: d } = this.editor;
|
|
1152
1042
|
try {
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
const { left:
|
|
1156
|
-
["image/jpg", "image/jpeg"].includes(
|
|
1157
|
-
const
|
|
1158
|
-
|
|
1159
|
-
const
|
|
1160
|
-
if (
|
|
1161
|
-
const
|
|
1162
|
-
|
|
1163
|
-
const
|
|
1164
|
-
image:
|
|
1165
|
-
exportAsBase64:
|
|
1166
|
-
exportAsBlob:
|
|
1167
|
-
fileName:
|
|
1043
|
+
const r = s === "application/pdf", l = r ? "image/jpg" : s, h = N.getFormatFromContentType(l);
|
|
1044
|
+
o.setCoords();
|
|
1045
|
+
const { left: g, top: u, width: m, height: M } = o.getBoundingRect(), j = yield a.clone(["id", "format", "locked"]);
|
|
1046
|
+
["image/jpg", "image/jpeg"].includes(l) && (j.backgroundColor = "#ffffff");
|
|
1047
|
+
const b = j.getObjects().find((p) => p.id === o.id);
|
|
1048
|
+
b && (b.visible = !1), j.viewportTransform = [1, 0, 0, 1, -g, -u], j.setDimensions({ width: m, height: M }, { backstoreOnly: !0 }), j.renderAll();
|
|
1049
|
+
const L = j.getObjects().filter((p) => p.format).every((p) => p.format === "svg");
|
|
1050
|
+
if (h === "svg" && L) {
|
|
1051
|
+
const p = j.toSVG();
|
|
1052
|
+
j.dispose();
|
|
1053
|
+
const S = {
|
|
1054
|
+
image: N._exportSVGStringAsFile(p, {
|
|
1055
|
+
exportAsBase64: i,
|
|
1056
|
+
exportAsBlob: n,
|
|
1057
|
+
fileName: t
|
|
1168
1058
|
}),
|
|
1169
1059
|
format: "svg",
|
|
1170
1060
|
contentType: "image/svg+xml",
|
|
1171
|
-
fileName:
|
|
1061
|
+
fileName: t.replace(/\.[^/.]+$/, ".svg")
|
|
1172
1062
|
};
|
|
1173
|
-
return
|
|
1063
|
+
return a.fire("editor:canvas-exported", S), S;
|
|
1174
1064
|
}
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
|
|
1065
|
+
const y = yield new Promise((p, k) => {
|
|
1066
|
+
j.getElement().toBlob((S) => {
|
|
1067
|
+
S ? p(S) : k(new Error("Failed to create Blob from canvas"));
|
|
1178
1068
|
});
|
|
1179
1069
|
});
|
|
1180
|
-
if (
|
|
1181
|
-
const
|
|
1182
|
-
image:
|
|
1183
|
-
format:
|
|
1184
|
-
contentType:
|
|
1185
|
-
fileName:
|
|
1070
|
+
if (j.dispose(), n) {
|
|
1071
|
+
const p = {
|
|
1072
|
+
image: y,
|
|
1073
|
+
format: h,
|
|
1074
|
+
contentType: l,
|
|
1075
|
+
fileName: t
|
|
1186
1076
|
};
|
|
1187
|
-
return
|
|
1077
|
+
return a.fire("editor:canvas-exported", p), p;
|
|
1188
1078
|
}
|
|
1189
|
-
const
|
|
1079
|
+
const A = yield createImageBitmap(y), w = yield d.post(
|
|
1190
1080
|
"toDataURL",
|
|
1191
|
-
{ format:
|
|
1192
|
-
[
|
|
1081
|
+
{ format: h, quality: 1, bitmap: A },
|
|
1082
|
+
[A]
|
|
1193
1083
|
);
|
|
1194
|
-
if (
|
|
1195
|
-
const
|
|
1196
|
-
orientation:
|
|
1084
|
+
if (r) {
|
|
1085
|
+
const k = m * 0.264583, S = M * 0.264583, Me = (yield this.editor.moduleLoader.loadModule("jspdf")).jsPDF, G = new Me({
|
|
1086
|
+
orientation: k > S ? "landscape" : "portrait",
|
|
1197
1087
|
unit: "mm",
|
|
1198
|
-
format: [
|
|
1088
|
+
format: [k, S]
|
|
1199
1089
|
});
|
|
1200
|
-
if (G.addImage(
|
|
1201
|
-
const
|
|
1090
|
+
if (G.addImage(String(w), "JPG", 0, 0, k, S), i) {
|
|
1091
|
+
const oe = {
|
|
1202
1092
|
image: G.output("datauristring"),
|
|
1203
1093
|
format: "pdf",
|
|
1204
1094
|
contentType: "application/pdf",
|
|
1205
|
-
fileName:
|
|
1095
|
+
fileName: t
|
|
1206
1096
|
};
|
|
1207
|
-
return
|
|
1097
|
+
return a.fire("editor:canvas-exported", oe), oe;
|
|
1208
1098
|
}
|
|
1209
|
-
const
|
|
1210
|
-
image: new File([
|
|
1099
|
+
const me = G.output("blob"), ae = {
|
|
1100
|
+
image: new File([me], t, { type: "application/pdf" }),
|
|
1211
1101
|
format: "pdf",
|
|
1212
1102
|
contentType: "application/pdf",
|
|
1213
|
-
fileName:
|
|
1103
|
+
fileName: t
|
|
1214
1104
|
};
|
|
1215
|
-
return
|
|
1105
|
+
return a.fire("editor:canvas-exported", ae), ae;
|
|
1216
1106
|
}
|
|
1217
|
-
if (
|
|
1218
|
-
const
|
|
1219
|
-
image:
|
|
1220
|
-
format:
|
|
1221
|
-
contentType:
|
|
1222
|
-
fileName:
|
|
1107
|
+
if (i) {
|
|
1108
|
+
const p = {
|
|
1109
|
+
image: w,
|
|
1110
|
+
format: h,
|
|
1111
|
+
contentType: l,
|
|
1112
|
+
fileName: t
|
|
1223
1113
|
};
|
|
1224
|
-
return
|
|
1114
|
+
return a.fire("editor:canvas-exported", p), p;
|
|
1225
1115
|
}
|
|
1226
|
-
const
|
|
1227
|
-
image: new File([
|
|
1228
|
-
format:
|
|
1229
|
-
contentType:
|
|
1230
|
-
fileName:
|
|
1116
|
+
const E = h === "svg" && !L ? t.replace(/\.[^/.]+$/, ".png") : t, ne = {
|
|
1117
|
+
image: new File([y], E, { type: l }),
|
|
1118
|
+
format: h,
|
|
1119
|
+
contentType: l,
|
|
1120
|
+
fileName: E
|
|
1231
1121
|
};
|
|
1232
|
-
return
|
|
1233
|
-
} catch (
|
|
1122
|
+
return a.fire("editor:canvas-exported", ne), ne;
|
|
1123
|
+
} catch (r) {
|
|
1234
1124
|
return this.editor.errorManager.emitError({
|
|
1235
1125
|
origin: "ImageManager",
|
|
1236
1126
|
method: "exportCanvasAsImageFile",
|
|
1237
1127
|
code: "IMAGE_EXPORT_FAILED",
|
|
1238
|
-
message: `Ошибка экспорта изображения: ${
|
|
1239
|
-
data: { contentType:
|
|
1128
|
+
message: `Ошибка экспорта изображения: ${r.message}`,
|
|
1129
|
+
data: { contentType: s, fileName: t, exportAsBase64: i, exportAsBlob: n }
|
|
1240
1130
|
}), null;
|
|
1241
1131
|
}
|
|
1242
1132
|
});
|
|
@@ -1253,86 +1143,86 @@ class C {
|
|
|
1253
1143
|
* @fires editor:object-exported
|
|
1254
1144
|
*/
|
|
1255
1145
|
exportObjectAsImageFile() {
|
|
1256
|
-
return
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
if (!
|
|
1146
|
+
return I(this, arguments, function* (e = {}) {
|
|
1147
|
+
const {
|
|
1148
|
+
object: t,
|
|
1149
|
+
fileName: s = "image.png",
|
|
1150
|
+
contentType: i = "image/png",
|
|
1151
|
+
exportAsBase64: n = !1,
|
|
1152
|
+
exportAsBlob: a = !1
|
|
1153
|
+
} = e, { canvas: o, workerManager: d } = this.editor, r = t || o.getActiveObject();
|
|
1154
|
+
if (!r)
|
|
1265
1155
|
return this.editor.errorManager.emitError({
|
|
1266
1156
|
origin: "ImageManager",
|
|
1267
1157
|
method: "exportObjectAsImageFile",
|
|
1268
1158
|
code: "NO_OBJECT_SELECTED",
|
|
1269
1159
|
message: "Не выбран объект для экспорта",
|
|
1270
|
-
data: { contentType:
|
|
1160
|
+
data: { contentType: i, fileName: s, exportAsBase64: n, exportAsBlob: a }
|
|
1271
1161
|
}), null;
|
|
1272
1162
|
try {
|
|
1273
|
-
const
|
|
1274
|
-
if (
|
|
1275
|
-
const
|
|
1276
|
-
exportAsBase64:
|
|
1277
|
-
exportAsBlob:
|
|
1278
|
-
fileName:
|
|
1279
|
-
}),
|
|
1280
|
-
object:
|
|
1281
|
-
image:
|
|
1282
|
-
format:
|
|
1163
|
+
const l = N.getFormatFromContentType(i);
|
|
1164
|
+
if (l === "svg") {
|
|
1165
|
+
const M = r.toSVG(), j = N._exportSVGStringAsFile(M, {
|
|
1166
|
+
exportAsBase64: n,
|
|
1167
|
+
exportAsBlob: a,
|
|
1168
|
+
fileName: s
|
|
1169
|
+
}), b = {
|
|
1170
|
+
object: r,
|
|
1171
|
+
image: j,
|
|
1172
|
+
format: l,
|
|
1283
1173
|
contentType: "image/svg+xml",
|
|
1284
|
-
fileName:
|
|
1174
|
+
fileName: s.replace(/\.[^/.]+$/, ".svg")
|
|
1285
1175
|
};
|
|
1286
|
-
return
|
|
1176
|
+
return o.fire("editor:object-exported", b), b;
|
|
1287
1177
|
}
|
|
1288
|
-
if (
|
|
1289
|
-
const
|
|
1178
|
+
if (n && r instanceof U) {
|
|
1179
|
+
const M = yield createImageBitmap(r.getElement()), j = yield d.post(
|
|
1290
1180
|
"toDataURL",
|
|
1291
1181
|
{
|
|
1292
|
-
format:
|
|
1182
|
+
format: l,
|
|
1293
1183
|
quality: 1,
|
|
1294
|
-
bitmap:
|
|
1184
|
+
bitmap: M
|
|
1295
1185
|
},
|
|
1296
|
-
[
|
|
1297
|
-
),
|
|
1298
|
-
object:
|
|
1299
|
-
image:
|
|
1300
|
-
format:
|
|
1301
|
-
contentType:
|
|
1302
|
-
fileName:
|
|
1186
|
+
[M]
|
|
1187
|
+
), b = {
|
|
1188
|
+
object: r,
|
|
1189
|
+
image: j,
|
|
1190
|
+
format: l,
|
|
1191
|
+
contentType: i,
|
|
1192
|
+
fileName: s
|
|
1303
1193
|
};
|
|
1304
|
-
return
|
|
1194
|
+
return o.fire("editor:object-exported", b), b;
|
|
1305
1195
|
}
|
|
1306
|
-
const
|
|
1307
|
-
|
|
1308
|
-
|
|
1196
|
+
const h = r.toCanvasElement(), g = yield new Promise((M, j) => {
|
|
1197
|
+
h.toBlob((b) => {
|
|
1198
|
+
b ? M(b) : j(new Error("Failed to create Blob from canvas"));
|
|
1309
1199
|
});
|
|
1310
1200
|
});
|
|
1311
|
-
if (
|
|
1312
|
-
const
|
|
1313
|
-
object:
|
|
1314
|
-
image:
|
|
1315
|
-
format:
|
|
1316
|
-
contentType:
|
|
1317
|
-
fileName:
|
|
1201
|
+
if (a) {
|
|
1202
|
+
const M = {
|
|
1203
|
+
object: r,
|
|
1204
|
+
image: g,
|
|
1205
|
+
format: l,
|
|
1206
|
+
contentType: i,
|
|
1207
|
+
fileName: s
|
|
1318
1208
|
};
|
|
1319
|
-
return
|
|
1209
|
+
return o.fire("editor:object-exported", M), M;
|
|
1320
1210
|
}
|
|
1321
|
-
const
|
|
1322
|
-
object:
|
|
1323
|
-
image:
|
|
1324
|
-
format:
|
|
1325
|
-
contentType:
|
|
1326
|
-
fileName:
|
|
1211
|
+
const u = new File([g], s, { type: i }), m = {
|
|
1212
|
+
object: r,
|
|
1213
|
+
image: u,
|
|
1214
|
+
format: l,
|
|
1215
|
+
contentType: i,
|
|
1216
|
+
fileName: s
|
|
1327
1217
|
};
|
|
1328
|
-
return
|
|
1329
|
-
} catch (
|
|
1218
|
+
return o.fire("editor:object-exported", m), m;
|
|
1219
|
+
} catch (l) {
|
|
1330
1220
|
return this.editor.errorManager.emitError({
|
|
1331
1221
|
origin: "ImageManager",
|
|
1332
1222
|
method: "exportObjectAsImageFile",
|
|
1333
1223
|
code: "IMAGE_EXPORT_FAILED",
|
|
1334
|
-
message: `Ошибка экспорта объекта: ${
|
|
1335
|
-
data: { contentType:
|
|
1224
|
+
message: `Ошибка экспорта объекта: ${l.message}`,
|
|
1225
|
+
data: { contentType: i, fileName: s, exportAsBase64: n, exportAsBlob: a }
|
|
1336
1226
|
}), null;
|
|
1337
1227
|
}
|
|
1338
1228
|
});
|
|
@@ -1348,7 +1238,7 @@ class C {
|
|
|
1348
1238
|
* @returns массив допустимых форматов изображений
|
|
1349
1239
|
*/
|
|
1350
1240
|
getAllowedFormatsFromContentTypes() {
|
|
1351
|
-
return this.acceptContentTypes.map((e) =>
|
|
1241
|
+
return this.acceptContentTypes.map((e) => N.getFormatFromContentType(e)).filter((e) => e);
|
|
1352
1242
|
}
|
|
1353
1243
|
/**
|
|
1354
1244
|
* Проверяет, является ли contentType допустимым типом изображения.
|
|
@@ -1364,7 +1254,7 @@ class C {
|
|
|
1364
1254
|
* @public
|
|
1365
1255
|
*/
|
|
1366
1256
|
getContentType(e) {
|
|
1367
|
-
return
|
|
1257
|
+
return I(this, null, function* () {
|
|
1368
1258
|
return typeof e == "string" ? this.getContentTypeFromUrl(e) : e.type || "application/octet-stream";
|
|
1369
1259
|
});
|
|
1370
1260
|
}
|
|
@@ -1375,15 +1265,15 @@ class C {
|
|
|
1375
1265
|
* @public
|
|
1376
1266
|
*/
|
|
1377
1267
|
getContentTypeFromUrl(e) {
|
|
1378
|
-
return
|
|
1268
|
+
return I(this, null, function* () {
|
|
1379
1269
|
if (e.startsWith("data:")) {
|
|
1380
1270
|
const t = e.match(/^data:([^;]+)/);
|
|
1381
1271
|
return t ? t[1] : "application/octet-stream";
|
|
1382
1272
|
}
|
|
1383
1273
|
try {
|
|
1384
|
-
const
|
|
1385
|
-
if (
|
|
1386
|
-
return
|
|
1274
|
+
const s = (yield fetch(e, { method: "HEAD" })).headers.get("content-type");
|
|
1275
|
+
if (s && s.startsWith("image/"))
|
|
1276
|
+
return s.split(";")[0];
|
|
1387
1277
|
} catch (t) {
|
|
1388
1278
|
console.warn("HEAD запрос неудачен, определяем тип по расширению:", t);
|
|
1389
1279
|
}
|
|
@@ -1393,19 +1283,19 @@ class C {
|
|
|
1393
1283
|
/**
|
|
1394
1284
|
* Определяет contentType по расширению файла в URL
|
|
1395
1285
|
* @param url - URL файла
|
|
1396
|
-
* @returns
|
|
1286
|
+
* @returns MIME-тип
|
|
1397
1287
|
* @public
|
|
1398
1288
|
*/
|
|
1399
1289
|
getContentTypeFromExtension(e) {
|
|
1400
1290
|
var t;
|
|
1401
1291
|
try {
|
|
1402
|
-
const
|
|
1403
|
-
return this.acceptContentTypes.forEach((
|
|
1404
|
-
const o =
|
|
1405
|
-
o && (
|
|
1406
|
-
}),
|
|
1407
|
-
} catch (
|
|
1408
|
-
return console.warn("Не удалось определить расширение из URL:", e,
|
|
1292
|
+
const i = (t = new URL(e).pathname.split(".").pop()) == null ? void 0 : t.toLowerCase(), n = {};
|
|
1293
|
+
return this.acceptContentTypes.forEach((a) => {
|
|
1294
|
+
const o = N.getFormatFromContentType(a);
|
|
1295
|
+
o && (n[o] = a);
|
|
1296
|
+
}), i && n[i] || "application/octet-stream";
|
|
1297
|
+
} catch (s) {
|
|
1298
|
+
return console.warn("Не удалось определить расширение из URL:", e, s), "application/octet-stream";
|
|
1409
1299
|
}
|
|
1410
1300
|
}
|
|
1411
1301
|
/**
|
|
@@ -1419,10 +1309,10 @@ class C {
|
|
|
1419
1309
|
imageObject: e,
|
|
1420
1310
|
scaleType: t = "contain"
|
|
1421
1311
|
}) {
|
|
1422
|
-
const { montageArea:
|
|
1423
|
-
if (!
|
|
1424
|
-
const
|
|
1425
|
-
return t === "contain" || t === "image-contain" ? Math.min(
|
|
1312
|
+
const { montageArea: s } = this.editor;
|
|
1313
|
+
if (!s || !e) return 1;
|
|
1314
|
+
const i = s.width, n = s.height, { width: a, height: o } = e;
|
|
1315
|
+
return t === "contain" || t === "image-contain" ? Math.min(i / a, n / o) : t === "cover" || t === "image-cover" ? Math.max(i / a, n / o) : 1;
|
|
1426
1316
|
}
|
|
1427
1317
|
/**
|
|
1428
1318
|
* Преобразует SVG-строку в Blob, файл, или base64
|
|
@@ -1437,10 +1327,10 @@ class C {
|
|
|
1437
1327
|
*/
|
|
1438
1328
|
static _exportSVGStringAsFile(e, {
|
|
1439
1329
|
exportAsBase64: t,
|
|
1440
|
-
exportAsBlob:
|
|
1441
|
-
fileName:
|
|
1330
|
+
exportAsBlob: s,
|
|
1331
|
+
fileName: i = "image.svg"
|
|
1442
1332
|
} = {}) {
|
|
1443
|
-
return
|
|
1333
|
+
return s ? new Blob([e], { type: "image/svg+xml" }) : t ? `data:image/svg+xml;base64,${window.btoa(encodeURIComponent(e))}` : new File([e], i.replace(/\.[^/.]+$/, ".svg"), { type: "image/svg+xml" });
|
|
1444
1334
|
}
|
|
1445
1335
|
/**
|
|
1446
1336
|
* Извлекает чистый формат (subtype) из contentType,
|
|
@@ -1454,72 +1344,72 @@ class C {
|
|
|
1454
1344
|
return t ? t[1] : "";
|
|
1455
1345
|
}
|
|
1456
1346
|
}
|
|
1457
|
-
class
|
|
1347
|
+
class et {
|
|
1458
1348
|
/**
|
|
1459
|
-
* @param
|
|
1460
|
-
* @param
|
|
1349
|
+
* @param options
|
|
1350
|
+
* @param options.editor – экземпляр редактора
|
|
1461
1351
|
*/
|
|
1462
1352
|
constructor({ editor: e }) {
|
|
1463
1353
|
this.editor = e;
|
|
1464
1354
|
}
|
|
1465
1355
|
/**
|
|
1466
1356
|
* Устанавливаем внутреннюю ширину канваса (для экспорта)
|
|
1467
|
-
* @param
|
|
1468
|
-
* @param
|
|
1469
|
-
* @param
|
|
1470
|
-
* @param
|
|
1471
|
-
* @param
|
|
1357
|
+
* @param width - ширина канваса
|
|
1358
|
+
* @param options
|
|
1359
|
+
* @param options.preserveProportional - Сохранить пропорции
|
|
1360
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1361
|
+
* @param options.adaptCanvasToContainer - Адаптировать канвас к контейнеру
|
|
1472
1362
|
* @fires editor:resolution-width-changed
|
|
1473
1363
|
*/
|
|
1474
|
-
setResolutionWidth(e, { preserveProportional: t, withoutSave:
|
|
1364
|
+
setResolutionWidth(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer: i } = {}) {
|
|
1475
1365
|
var m;
|
|
1476
1366
|
if (!e) return;
|
|
1477
1367
|
const {
|
|
1478
|
-
canvas:
|
|
1479
|
-
montageArea:
|
|
1368
|
+
canvas: n,
|
|
1369
|
+
montageArea: a,
|
|
1480
1370
|
options: { canvasBackstoreWidth: o }
|
|
1481
|
-
} = this.editor, { width:
|
|
1482
|
-
if (!o || o === "auto" ||
|
|
1483
|
-
const M = l /
|
|
1371
|
+
} = this.editor, { width: d, height: r } = a, l = Math.max(Math.min(Number(e), O), x);
|
|
1372
|
+
if (!o || o === "auto" || i ? this.adaptCanvasToContainer() : o ? this.setCanvasBackstoreWidth(Number(o)) : this.setCanvasBackstoreWidth(l), a.set({ width: l }), (m = n.clipPath) == null || m.set({ width: l }), t) {
|
|
1373
|
+
const M = l / d, j = r * M;
|
|
1484
1374
|
this.setResolutionHeight(j);
|
|
1485
1375
|
return;
|
|
1486
1376
|
}
|
|
1487
|
-
const { left: h, top: g } = this.getObjectDefaultCoords(
|
|
1488
|
-
|
|
1377
|
+
const { left: h, top: g } = this.getObjectDefaultCoords(a), u = n.getZoom();
|
|
1378
|
+
n.setViewportTransform([u, 0, 0, u, h, g]), this.centerMontageArea(), s || this.editor.historyManager.saveState(), n.fire("editor:resolution-width-changed", {
|
|
1489
1379
|
width: l,
|
|
1490
1380
|
preserveProportional: t,
|
|
1491
|
-
withoutSave:
|
|
1492
|
-
adaptCanvasToContainer:
|
|
1381
|
+
withoutSave: s,
|
|
1382
|
+
adaptCanvasToContainer: i
|
|
1493
1383
|
});
|
|
1494
1384
|
}
|
|
1495
1385
|
/**
|
|
1496
1386
|
* Устанавливаем внутреннюю высоту канваса (для экспорта)
|
|
1497
|
-
* @param
|
|
1498
|
-
* @param
|
|
1499
|
-
* @param
|
|
1500
|
-
* @param
|
|
1501
|
-
* @param
|
|
1387
|
+
* @param height - высота канваса
|
|
1388
|
+
* @param options
|
|
1389
|
+
* @param options.preserveProportional - Сохранить пропорции
|
|
1390
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1391
|
+
* @param options.adaptCanvasToContainer - Адаптировать канвас к контейнеру
|
|
1502
1392
|
* @fires editor:resolution-height-changed
|
|
1503
1393
|
*/
|
|
1504
|
-
setResolutionHeight(e, { preserveProportional: t, withoutSave:
|
|
1394
|
+
setResolutionHeight(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer: i } = {}) {
|
|
1505
1395
|
var m;
|
|
1506
1396
|
if (!e) return;
|
|
1507
1397
|
const {
|
|
1508
|
-
canvas:
|
|
1509
|
-
montageArea:
|
|
1398
|
+
canvas: n,
|
|
1399
|
+
montageArea: a,
|
|
1510
1400
|
options: { canvasBackstoreHeight: o }
|
|
1511
|
-
} = this.editor, { width:
|
|
1512
|
-
if (!o || o === "auto" ||
|
|
1513
|
-
const M = l /
|
|
1401
|
+
} = this.editor, { width: d, height: r } = a, l = Math.max(Math.min(Number(e), T), B);
|
|
1402
|
+
if (!o || o === "auto" || i ? this.adaptCanvasToContainer() : o ? this.setCanvasBackstoreHeight(Number(o)) : this.setCanvasBackstoreHeight(l), a.set({ height: l }), (m = n.clipPath) == null || m.set({ height: l }), t) {
|
|
1403
|
+
const M = l / r, j = d * M;
|
|
1514
1404
|
this.setResolutionWidth(j);
|
|
1515
1405
|
return;
|
|
1516
1406
|
}
|
|
1517
|
-
const { left: h, top: g } = this.getObjectDefaultCoords(
|
|
1518
|
-
|
|
1407
|
+
const { left: h, top: g } = this.getObjectDefaultCoords(a), u = n.getZoom();
|
|
1408
|
+
n.setViewportTransform([u, 0, 0, u, h, g]), this.centerMontageArea(), s || this.editor.historyManager.saveState(), n.fire("editor:resolution-height-changed", {
|
|
1519
1409
|
height: l,
|
|
1520
1410
|
preserveProportional: t,
|
|
1521
|
-
withoutSave:
|
|
1522
|
-
adaptCanvasToContainer:
|
|
1411
|
+
withoutSave: s,
|
|
1412
|
+
adaptCanvasToContainer: i
|
|
1523
1413
|
});
|
|
1524
1414
|
}
|
|
1525
1415
|
/**
|
|
@@ -1527,51 +1417,50 @@ class st {
|
|
|
1527
1417
|
* и устанавливает правильный viewportTransform.
|
|
1528
1418
|
*/
|
|
1529
1419
|
centerMontageArea() {
|
|
1530
|
-
var
|
|
1531
|
-
const { canvas: e, montageArea: t } = this.editor,
|
|
1420
|
+
var d;
|
|
1421
|
+
const { canvas: e, montageArea: t } = this.editor, s = e.getWidth(), i = e.getHeight(), n = e.getZoom(), a = new _(s / 2, i / 2);
|
|
1532
1422
|
t.set({
|
|
1533
|
-
left:
|
|
1534
|
-
top:
|
|
1535
|
-
}), (
|
|
1536
|
-
left:
|
|
1537
|
-
top:
|
|
1423
|
+
left: s / 2,
|
|
1424
|
+
top: i / 2
|
|
1425
|
+
}), (d = e.clipPath) == null || d.set({
|
|
1426
|
+
left: s / 2,
|
|
1427
|
+
top: i / 2
|
|
1538
1428
|
}), e.renderAll();
|
|
1539
1429
|
const o = e.viewportTransform;
|
|
1540
|
-
o[4] =
|
|
1430
|
+
o[4] = s / 2 - a.x * n, o[5] = i / 2 - a.y * n, e.setViewportTransform(o), e.renderAll();
|
|
1541
1431
|
}
|
|
1542
1432
|
/**
|
|
1543
1433
|
* Метод для получения координат объекта с учетом текущего зума
|
|
1544
|
-
* @param
|
|
1545
|
-
* @returns
|
|
1434
|
+
* @param object - объект, координаты которого нужно получить
|
|
1435
|
+
* @returns координаты объекта
|
|
1546
1436
|
*/
|
|
1547
1437
|
getObjectDefaultCoords(e) {
|
|
1548
|
-
const { canvas: t } = this.editor,
|
|
1549
|
-
if (!
|
|
1438
|
+
const { canvas: t } = this.editor, s = e || t.getActiveObject();
|
|
1439
|
+
if (!s)
|
|
1550
1440
|
return this.editor.errorManager.emitError({
|
|
1551
1441
|
origin: "CanvasManager",
|
|
1552
1442
|
method: "getObjectDefaultCoords",
|
|
1553
1443
|
code: "NO_ACTIVE_OBJECT",
|
|
1554
1444
|
message: "Не выбран объект для получения координат"
|
|
1555
1445
|
}), { left: 0, top: 0 };
|
|
1556
|
-
const { width:
|
|
1557
|
-
return { left: o, top:
|
|
1446
|
+
const { width: i, height: n } = s, a = t.getZoom(), o = (i - i * a) / 2, d = (n - n * a) / 2;
|
|
1447
|
+
return { left: o, top: d };
|
|
1558
1448
|
}
|
|
1559
1449
|
/**
|
|
1560
1450
|
* Устанавливаем ширину канваса в backstore (для экспорта)
|
|
1561
|
-
* @param {Number} width
|
|
1562
1451
|
*/
|
|
1563
1452
|
setCanvasBackstoreWidth(e) {
|
|
1564
1453
|
if (!e || typeof e != "number") return;
|
|
1565
|
-
const t = Math.max(Math.min(e, O),
|
|
1454
|
+
const t = Math.max(Math.min(e, O), x);
|
|
1566
1455
|
this.editor.canvas.setDimensions({ width: t }, { backstoreOnly: !0 });
|
|
1567
1456
|
}
|
|
1568
1457
|
/**
|
|
1569
1458
|
* Устанавливаем высоту канваса в backstore (для экспорта)
|
|
1570
|
-
* @param
|
|
1459
|
+
* @param height
|
|
1571
1460
|
*/
|
|
1572
1461
|
setCanvasBackstoreHeight(e) {
|
|
1573
1462
|
if (!e || typeof e != "number") return;
|
|
1574
|
-
const t = Math.max(Math.min(e, T),
|
|
1463
|
+
const t = Math.max(Math.min(e, T), B);
|
|
1575
1464
|
this.editor.canvas.setDimensions({ height: t }, { backstoreOnly: !0 });
|
|
1576
1465
|
}
|
|
1577
1466
|
/**
|
|
@@ -1580,8 +1469,8 @@ class st {
|
|
|
1580
1469
|
* с учётом минимальных и максимальных значений.
|
|
1581
1470
|
*/
|
|
1582
1471
|
adaptCanvasToContainer() {
|
|
1583
|
-
const { canvas: e } = this.editor, t = e.editorContainer,
|
|
1584
|
-
console.log("adaptCanvasToContainer newWidth",
|
|
1472
|
+
const { canvas: e } = this.editor, t = e.editorContainer, s = t.clientWidth, i = t.clientHeight, n = Math.max(Math.min(s, O), x), a = Math.max(Math.min(i, T), B);
|
|
1473
|
+
console.log("adaptCanvasToContainer newWidth", n), console.log("adaptCanvasToContainer newHeight", a), e.setDimensions({ width: n, height: a }, { backstoreOnly: !0 });
|
|
1585
1474
|
}
|
|
1586
1475
|
/**
|
|
1587
1476
|
* Обновляет размеры канваса и вписывает объекты в монтажную область.
|
|
@@ -1592,15 +1481,15 @@ class st {
|
|
|
1592
1481
|
const {
|
|
1593
1482
|
canvas: e,
|
|
1594
1483
|
selectionManager: t,
|
|
1595
|
-
transformManager:
|
|
1484
|
+
transformManager: s,
|
|
1596
1485
|
montageArea: {
|
|
1597
|
-
width:
|
|
1598
|
-
height:
|
|
1486
|
+
width: i,
|
|
1487
|
+
height: n
|
|
1599
1488
|
}
|
|
1600
1489
|
} = this.editor;
|
|
1601
|
-
this.setResolutionWidth(
|
|
1602
|
-
width:
|
|
1603
|
-
height:
|
|
1490
|
+
this.setResolutionWidth(i, { adaptCanvasToContainer: !0, withoutSave: !0 }), this.setResolutionHeight(n, { adaptCanvasToContainer: !0, withoutSave: !0 }), this.centerMontageArea(), t.selectAll(), s.fitObject({ fitAsOneObject: !0, withoutSave: !0 }), e.fire("editor:canvas-updated", {
|
|
1491
|
+
width: i,
|
|
1492
|
+
height: n
|
|
1604
1493
|
});
|
|
1605
1494
|
}
|
|
1606
1495
|
/**
|
|
@@ -1612,20 +1501,20 @@ class st {
|
|
|
1612
1501
|
*
|
|
1613
1502
|
* Метод нужно вызывать после zoomToPoint.
|
|
1614
1503
|
*
|
|
1615
|
-
* @param
|
|
1504
|
+
* @param zoom — текущее значение zoom (например, 1, 1.2, 2 и т.д.)
|
|
1616
1505
|
*/
|
|
1617
1506
|
updateCssDimensionsForZoom(e) {
|
|
1618
|
-
const { canvas: t, montageArea:
|
|
1619
|
-
if (!(
|
|
1620
|
-
const o =
|
|
1507
|
+
const { canvas: t, montageArea: s } = this.editor, i = s.width * e, n = s.height * e, a = t.wrapperEl.parentNode;
|
|
1508
|
+
if (!(a instanceof HTMLElement)) return;
|
|
1509
|
+
const o = i <= a.clientWidth ? "100%" : i, d = n <= a.clientHeight ? "100%" : n;
|
|
1621
1510
|
t.setDimensions(
|
|
1622
|
-
{ width: o, height:
|
|
1511
|
+
{ width: o, height: d },
|
|
1623
1512
|
{ cssOnly: !0 }
|
|
1624
1513
|
);
|
|
1625
1514
|
}
|
|
1626
1515
|
/**
|
|
1627
1516
|
* Устанавливаем CSS ширину канваса для отображения
|
|
1628
|
-
* @param
|
|
1517
|
+
* @param width
|
|
1629
1518
|
* @fires editor:display-canvas-width-changed
|
|
1630
1519
|
*/
|
|
1631
1520
|
setCanvasCSSWidth(e) {
|
|
@@ -1637,7 +1526,7 @@ class st {
|
|
|
1637
1526
|
}
|
|
1638
1527
|
/**
|
|
1639
1528
|
* Устанавливаем CSS высоту канваса для отображения
|
|
1640
|
-
* @param
|
|
1529
|
+
* @param height
|
|
1641
1530
|
* @fires editor:display-canvas-height-changed
|
|
1642
1531
|
*/
|
|
1643
1532
|
setCanvasCSSHeight(e) {
|
|
@@ -1649,7 +1538,7 @@ class st {
|
|
|
1649
1538
|
}
|
|
1650
1539
|
/**
|
|
1651
1540
|
* Устанавливаем CSS ширину обертки канваса для отображения
|
|
1652
|
-
* @param
|
|
1541
|
+
* @param width
|
|
1653
1542
|
* @fires editor:display-wrapper-width-changed
|
|
1654
1543
|
*/
|
|
1655
1544
|
setCanvasWrapperWidth(e) {
|
|
@@ -1661,7 +1550,7 @@ class st {
|
|
|
1661
1550
|
}
|
|
1662
1551
|
/**
|
|
1663
1552
|
* Устанавливаем CSS высоту обертки канваса для отображения
|
|
1664
|
-
* @param
|
|
1553
|
+
* @param height
|
|
1665
1554
|
* @fires editor:display-wrapper-height-changed
|
|
1666
1555
|
*/
|
|
1667
1556
|
setCanvasWrapperHeight(e) {
|
|
@@ -1673,7 +1562,7 @@ class st {
|
|
|
1673
1562
|
}
|
|
1674
1563
|
/**
|
|
1675
1564
|
* Устанавливаем CSS ширину контейнера редактора для отображения
|
|
1676
|
-
* @param
|
|
1565
|
+
* @param width
|
|
1677
1566
|
* @fires editor:display-container-width-changed
|
|
1678
1567
|
*/
|
|
1679
1568
|
setEditorContainerWidth(e) {
|
|
@@ -1685,7 +1574,7 @@ class st {
|
|
|
1685
1574
|
}
|
|
1686
1575
|
/**
|
|
1687
1576
|
* Устанавливаем CSS высоту контейнера редактора для отображения
|
|
1688
|
-
* @param
|
|
1577
|
+
* @param height
|
|
1689
1578
|
* @fires editor:display-container-height-changed
|
|
1690
1579
|
*/
|
|
1691
1580
|
setEditorContainerHeight(e) {
|
|
@@ -1697,79 +1586,79 @@ class st {
|
|
|
1697
1586
|
}
|
|
1698
1587
|
/**
|
|
1699
1588
|
* Устанавливаем CSS ширину или высоту канваса для отображения
|
|
1700
|
-
* @param
|
|
1701
|
-
* @param
|
|
1589
|
+
* @param options
|
|
1590
|
+
* @param options.element - элемент, для которого устанавливаем размеры:
|
|
1702
1591
|
* canvas (upper & lower), wrapper, container
|
|
1703
|
-
* @param
|
|
1704
|
-
* @param
|
|
1592
|
+
* @param options.dimension - размер, который нужно установить: width или height
|
|
1593
|
+
* @param options.value - значение размера (строка или число)
|
|
1705
1594
|
* @fires editor:display-{element}-{dimension}-changed
|
|
1706
1595
|
*/
|
|
1707
|
-
setDisplayDimension({ element: e = "canvas", dimension: t, value:
|
|
1708
|
-
if (!
|
|
1709
|
-
const { canvas:
|
|
1596
|
+
setDisplayDimension({ element: e = "canvas", dimension: t, value: s } = {}) {
|
|
1597
|
+
if (!s) return;
|
|
1598
|
+
const { canvas: i, options: { editorContainer: n } } = this.editor, a = [];
|
|
1710
1599
|
switch (e) {
|
|
1711
1600
|
case "canvas":
|
|
1712
|
-
|
|
1601
|
+
a.push(i.lowerCanvasEl, i.upperCanvasEl);
|
|
1713
1602
|
break;
|
|
1714
1603
|
case "wrapper":
|
|
1715
|
-
|
|
1604
|
+
a.push(i.wrapperEl);
|
|
1716
1605
|
break;
|
|
1717
1606
|
case "container":
|
|
1718
|
-
|
|
1607
|
+
a.push(n);
|
|
1719
1608
|
break;
|
|
1720
1609
|
default:
|
|
1721
|
-
|
|
1610
|
+
a.push(i.lowerCanvasEl, i.upperCanvasEl);
|
|
1722
1611
|
}
|
|
1723
1612
|
const o = t === "width" ? "width" : "height";
|
|
1724
|
-
if (typeof
|
|
1725
|
-
|
|
1726
|
-
|
|
1613
|
+
if (typeof s == "string") {
|
|
1614
|
+
a.forEach((r) => {
|
|
1615
|
+
r.style[o] = s;
|
|
1727
1616
|
});
|
|
1728
1617
|
return;
|
|
1729
1618
|
}
|
|
1730
|
-
if (isNaN(
|
|
1731
|
-
const
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
}),
|
|
1619
|
+
if (isNaN(s)) return;
|
|
1620
|
+
const d = `${s}px`;
|
|
1621
|
+
a.forEach((r) => {
|
|
1622
|
+
r.style[o] = d;
|
|
1623
|
+
}), i.fire(`editor:display-${e}-${o}-changed`, {
|
|
1735
1624
|
element: e,
|
|
1736
|
-
value:
|
|
1625
|
+
value: s
|
|
1737
1626
|
});
|
|
1738
1627
|
}
|
|
1739
1628
|
/**
|
|
1740
1629
|
* Если изображение вписывается в допустимые значения, то масштабируем под него канвас
|
|
1741
|
-
* @param
|
|
1742
|
-
* @param
|
|
1743
|
-
* @param
|
|
1744
|
-
* @param
|
|
1630
|
+
* @param options
|
|
1631
|
+
* @param options.object - Объект с изображением, которое нужно масштабировать
|
|
1632
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1633
|
+
* @param options.preserveAspectRatio - Сохранять изначальные пропорции монтажной области
|
|
1745
1634
|
* @fires editor:montage-area-scaled-to-image
|
|
1746
1635
|
*/
|
|
1747
|
-
scaleMontageAreaToImage({ object: e, preserveAspectRatio: t, withoutSave:
|
|
1636
|
+
scaleMontageAreaToImage({ object: e, preserveAspectRatio: t, withoutSave: s } = {}) {
|
|
1748
1637
|
const {
|
|
1749
|
-
canvas:
|
|
1750
|
-
montageArea:
|
|
1751
|
-
transformManager:
|
|
1638
|
+
canvas: i,
|
|
1639
|
+
montageArea: n,
|
|
1640
|
+
transformManager: a,
|
|
1752
1641
|
options: {
|
|
1753
1642
|
montageAreaWidth: o,
|
|
1754
|
-
montageAreaHeight:
|
|
1643
|
+
montageAreaHeight: d
|
|
1755
1644
|
}
|
|
1756
|
-
} = this.editor,
|
|
1757
|
-
if (!
|
|
1758
|
-
const { width: l, height: h } =
|
|
1645
|
+
} = this.editor, r = e || i.getActiveObject();
|
|
1646
|
+
if (!r || r.type !== "image" && r.format !== "svg") return;
|
|
1647
|
+
const { width: l, height: h } = r;
|
|
1759
1648
|
let g = Math.min(l, O), u = Math.min(h, T);
|
|
1760
1649
|
if (t) {
|
|
1761
1650
|
const {
|
|
1762
1651
|
width: m,
|
|
1763
1652
|
height: M
|
|
1764
|
-
} =
|
|
1765
|
-
g = m *
|
|
1653
|
+
} = n, j = l / m, b = h / M, L = Math.max(j, b);
|
|
1654
|
+
g = m * L, u = M * L;
|
|
1766
1655
|
}
|
|
1767
|
-
this.setResolutionWidth(g, { withoutSave: !0 }), this.setResolutionHeight(u, { withoutSave: !0 }), (l > o || h >
|
|
1768
|
-
object:
|
|
1656
|
+
this.setResolutionWidth(g, { withoutSave: !0 }), this.setResolutionHeight(u, { withoutSave: !0 }), (l > o || h > d) && a.calculateAndApplyDefaultZoom(), a.resetObject(r, { withoutSave: !0 }), i.centerObject(r), i.renderAll(), s || this.editor.historyManager.saveState(), i.fire("editor:montage-area-scaled-to-image", {
|
|
1657
|
+
object: r,
|
|
1769
1658
|
width: g,
|
|
1770
1659
|
height: u,
|
|
1771
1660
|
preserveAspectRatio: t,
|
|
1772
|
-
withoutSave:
|
|
1661
|
+
withoutSave: s
|
|
1773
1662
|
});
|
|
1774
1663
|
}
|
|
1775
1664
|
/**
|
|
@@ -1777,89 +1666,89 @@ class st {
|
|
|
1777
1666
|
* @fires editor:cleared
|
|
1778
1667
|
*/
|
|
1779
1668
|
clearCanvas() {
|
|
1780
|
-
const { canvas: e, montageArea: t, historyManager:
|
|
1781
|
-
|
|
1669
|
+
const { canvas: e, montageArea: t, historyManager: s } = this.editor;
|
|
1670
|
+
s.suspendHistory(), e.clear(), e.add(t), e.renderAll(), s.resumeHistory(), s.saveState(), e == null || e.fire("editor:cleared");
|
|
1782
1671
|
}
|
|
1783
1672
|
/**
|
|
1784
1673
|
* Установка зума и масштаба для канваса и сброс трансформации всех объектов
|
|
1785
|
-
* @param
|
|
1786
|
-
* @param
|
|
1674
|
+
* @param options
|
|
1675
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1787
1676
|
* @fires editor:default-scale-set
|
|
1788
1677
|
*/
|
|
1789
1678
|
setDefaultScale({ withoutSave: e } = {}) {
|
|
1790
1679
|
const {
|
|
1791
1680
|
canvas: t,
|
|
1792
|
-
transformManager:
|
|
1793
|
-
historyManager:
|
|
1681
|
+
transformManager: s,
|
|
1682
|
+
historyManager: i,
|
|
1794
1683
|
options: {
|
|
1795
|
-
montageAreaWidth:
|
|
1796
|
-
montageAreaHeight:
|
|
1684
|
+
montageAreaWidth: n,
|
|
1685
|
+
montageAreaHeight: a
|
|
1797
1686
|
}
|
|
1798
1687
|
} = this.editor;
|
|
1799
|
-
|
|
1688
|
+
s.resetZoom(), this.setResolutionWidth(n, { withoutSave: !0 }), this.setResolutionHeight(a, { withoutSave: !0 }), t.renderAll(), s.resetObjects(), e || i.saveState(), t.fire("editor:default-scale-set");
|
|
1800
1689
|
}
|
|
1801
1690
|
/**
|
|
1802
1691
|
* Получение всех объектов внутри монтажной области редактора
|
|
1803
|
-
* @returns
|
|
1692
|
+
* @returns массив объектов
|
|
1804
1693
|
*/
|
|
1805
1694
|
getObjects() {
|
|
1806
|
-
const { canvas: e, montageArea: t, interactionBlocker: { overlayMask:
|
|
1807
|
-
return e.getObjects().filter((
|
|
1695
|
+
const { canvas: e, montageArea: t, interactionBlocker: { overlayMask: s } } = this.editor;
|
|
1696
|
+
return e.getObjects().filter((n) => n.id !== t.id && n.id !== (s == null ? void 0 : s.id));
|
|
1808
1697
|
}
|
|
1809
1698
|
}
|
|
1810
|
-
class
|
|
1699
|
+
class tt {
|
|
1811
1700
|
constructor({ editor: e }) {
|
|
1812
|
-
this.editor = e, this.options = e.options, this.minZoom = this.options.minZoom ||
|
|
1701
|
+
this.editor = e, this.options = e.options, this.minZoom = this.options.minZoom || Je, this.maxZoom = this.options.maxZoom || $e, this.defaultZoom = this.options.defaultScale, this.maxZoomFactor = this.options.maxZoomFactor;
|
|
1813
1702
|
}
|
|
1814
1703
|
/**
|
|
1815
1704
|
* Метод рассчитывает и применяет зум по умолчанию для монтажной области редактора.
|
|
1816
1705
|
* Зум рассчитывается исходя из размеров контейнера редактора и текущих размеров монтажной области.
|
|
1817
1706
|
* Расчёт происходит таким образом, чтобы монтажная область визуально целиком помещалась в контейнер редактора.
|
|
1818
1707
|
* Если scale не передан, то используется значение из options.defaultScale.
|
|
1819
|
-
* @param
|
|
1708
|
+
* @param scale - Желаемый масштаб относительно размеров контейнера редактора.
|
|
1820
1709
|
*/
|
|
1821
1710
|
calculateAndApplyDefaultZoom(e = this.options.defaultScale) {
|
|
1822
|
-
const { canvas: t } = this.editor,
|
|
1823
|
-
this.defaultZoom = Math.min(
|
|
1711
|
+
const { canvas: t } = this.editor, s = t.editorContainer, i = s.clientWidth, n = s.clientHeight, { width: a, height: o } = this.editor.montageArea, d = i / a * e, r = n / o * e;
|
|
1712
|
+
this.defaultZoom = Math.min(d, r);
|
|
1824
1713
|
const { defaultZoom: l, maxZoomFactor: h, minZoom: g, maxZoom: u } = this;
|
|
1825
1714
|
this.minZoom = Math.min(l / h, g), this.maxZoom = Math.max(l * h, u), this.setZoom();
|
|
1826
1715
|
}
|
|
1827
1716
|
/**
|
|
1828
1717
|
* Увеличение/уменьшение масштаба
|
|
1829
|
-
* @param
|
|
1830
|
-
* @param
|
|
1831
|
-
* @param
|
|
1832
|
-
* @param
|
|
1718
|
+
* @param scale - Шаг зума
|
|
1719
|
+
* @param options - Координаты зума (по умолчанию центр канваса)
|
|
1720
|
+
* @param options.pointX - Координата X точки зума
|
|
1721
|
+
* @param options.pointY - Координата Y точки зума
|
|
1833
1722
|
* @fires editor:zoom-changed
|
|
1834
1723
|
* Если передавать координаты курсора, то нужно быть аккуратнее, так как юзер может выйти за пределы рабочей области
|
|
1835
1724
|
*/
|
|
1836
|
-
zoom(e =
|
|
1725
|
+
zoom(e = Ke, t = {}) {
|
|
1837
1726
|
var g, u;
|
|
1838
1727
|
if (!e) return;
|
|
1839
|
-
const { minZoom:
|
|
1840
|
-
let h = Number((
|
|
1841
|
-
h >
|
|
1842
|
-
currentZoom:
|
|
1728
|
+
const { minZoom: s, maxZoom: i } = this, { canvas: n } = this.editor, a = n.getZoom(), o = n.getCenterPoint(), d = (g = t.pointX) != null ? g : o.x, r = (u = t.pointY) != null ? u : o.y, l = new _(d, r);
|
|
1729
|
+
let h = Number((a + Number(e)).toFixed(2));
|
|
1730
|
+
h > i && (h = i), h < s && (h = s), n.zoomToPoint(l, h), console.log({
|
|
1731
|
+
currentZoom: a,
|
|
1843
1732
|
zoom: h,
|
|
1844
1733
|
point: l
|
|
1845
|
-
}),
|
|
1846
|
-
currentZoom:
|
|
1734
|
+
}), n.fire("editor:zoom-changed", {
|
|
1735
|
+
currentZoom: n.getZoom(),
|
|
1847
1736
|
zoom: h,
|
|
1848
1737
|
point: l
|
|
1849
1738
|
});
|
|
1850
1739
|
}
|
|
1851
1740
|
/**
|
|
1852
1741
|
* Установка зума
|
|
1853
|
-
* @param
|
|
1742
|
+
* @param zoom - Зум
|
|
1854
1743
|
* @fires editor:zoom-changed
|
|
1855
1744
|
*/
|
|
1856
1745
|
setZoom(e = this.defaultZoom) {
|
|
1857
|
-
const { minZoom: t, maxZoom:
|
|
1858
|
-
let
|
|
1859
|
-
e >
|
|
1860
|
-
currentZoom:
|
|
1861
|
-
zoom:
|
|
1862
|
-
point:
|
|
1746
|
+
const { minZoom: t, maxZoom: s } = this, { canvas: i } = this.editor, n = new _(i.getCenterPoint());
|
|
1747
|
+
let a = e;
|
|
1748
|
+
e > s && (a = s), e < t && (a = t), i.zoomToPoint(n, a), i.fire("editor:zoom-changed", {
|
|
1749
|
+
currentZoom: i.getZoom(),
|
|
1750
|
+
zoom: a,
|
|
1751
|
+
point: n
|
|
1863
1752
|
});
|
|
1864
1753
|
}
|
|
1865
1754
|
/**
|
|
@@ -1867,7 +1756,7 @@ class it {
|
|
|
1867
1756
|
* @fires editor:zoom-changed
|
|
1868
1757
|
*/
|
|
1869
1758
|
resetZoom() {
|
|
1870
|
-
const { canvas: e } = this.editor, t = new
|
|
1759
|
+
const { canvas: e } = this.editor, t = new _(e.getCenterPoint());
|
|
1871
1760
|
e.zoomToPoint(t, this.defaultZoom), this.editor.canvas.fire("editor:zoom-changed", {
|
|
1872
1761
|
currentZoom: e.getZoom(),
|
|
1873
1762
|
point: t
|
|
@@ -1875,105 +1764,108 @@ class it {
|
|
|
1875
1764
|
}
|
|
1876
1765
|
/**
|
|
1877
1766
|
* Поворот объекта на заданный угол
|
|
1878
|
-
* @param
|
|
1879
|
-
* @param
|
|
1880
|
-
* @param
|
|
1767
|
+
* @param angle
|
|
1768
|
+
* @param options
|
|
1769
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1881
1770
|
* @fires editor:object-rotated
|
|
1882
1771
|
*/
|
|
1883
|
-
rotate(e =
|
|
1884
|
-
const { canvas:
|
|
1885
|
-
if (!
|
|
1886
|
-
const
|
|
1887
|
-
|
|
1888
|
-
object:
|
|
1772
|
+
rotate(e = qe, { withoutSave: t } = {}) {
|
|
1773
|
+
const { canvas: s, historyManager: i } = this.editor, n = s.getActiveObject();
|
|
1774
|
+
if (!n) return;
|
|
1775
|
+
const a = n.angle + e;
|
|
1776
|
+
n.rotate(a), n.setCoords(), s.renderAll(), t || i.saveState(), s.fire("editor:object-rotated", {
|
|
1777
|
+
object: n,
|
|
1889
1778
|
withoutSave: t,
|
|
1890
|
-
angle:
|
|
1779
|
+
angle: a
|
|
1891
1780
|
});
|
|
1892
1781
|
}
|
|
1893
1782
|
/**
|
|
1894
1783
|
* Отразить по горизонтали
|
|
1895
|
-
* @param
|
|
1896
|
-
* @param
|
|
1784
|
+
* @param options
|
|
1785
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1897
1786
|
* @fires editor:object-flipped-x
|
|
1898
1787
|
*/
|
|
1899
1788
|
flipX({ withoutSave: e } = {}) {
|
|
1900
|
-
const { canvas: t, historyManager:
|
|
1901
|
-
|
|
1902
|
-
object:
|
|
1789
|
+
const { canvas: t, historyManager: s } = this.editor, i = t.getActiveObject();
|
|
1790
|
+
i && (i.flipX = !i.flipX, t.renderAll(), e || s.saveState(), t.fire("editor:object-flipped-x", {
|
|
1791
|
+
object: i,
|
|
1903
1792
|
withoutSave: e
|
|
1904
1793
|
}));
|
|
1905
1794
|
}
|
|
1906
1795
|
/**
|
|
1907
1796
|
* Отразить по вертикали
|
|
1908
|
-
* @param
|
|
1909
|
-
* @param
|
|
1797
|
+
* @param options
|
|
1798
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1910
1799
|
* @fires editor:object-flipped-y
|
|
1911
1800
|
*/
|
|
1912
1801
|
flipY({ withoutSave: e } = {}) {
|
|
1913
|
-
const { canvas: t, historyManager:
|
|
1914
|
-
|
|
1915
|
-
object:
|
|
1802
|
+
const { canvas: t, historyManager: s } = this.editor, i = t.getActiveObject();
|
|
1803
|
+
i && (i.flipY = !i.flipY, t.renderAll(), e || s.saveState(), t.fire("editor:object-flipped-y", {
|
|
1804
|
+
object: i,
|
|
1916
1805
|
withoutSave: e
|
|
1917
1806
|
}));
|
|
1918
1807
|
}
|
|
1919
1808
|
/**
|
|
1920
1809
|
* Установка прозрачности объекта
|
|
1921
|
-
* @param
|
|
1810
|
+
* @param options
|
|
1811
|
+
* @param options.object - Объект, для которого нужно установить прозрачность
|
|
1812
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1813
|
+
* @param options.opacity - Прозрачность от 0 до 1
|
|
1922
1814
|
* @fires editor:object-opacity-changed
|
|
1923
1815
|
*/
|
|
1924
1816
|
setActiveObjectOpacity({
|
|
1925
1817
|
object: e,
|
|
1926
1818
|
opacity: t = 1,
|
|
1927
|
-
withoutSave:
|
|
1819
|
+
withoutSave: s
|
|
1928
1820
|
} = {}) {
|
|
1929
|
-
const { canvas:
|
|
1930
|
-
|
|
1821
|
+
const { canvas: i, historyManager: n } = this.editor, a = e || i.getActiveObject();
|
|
1822
|
+
a && (a instanceof v ? a.getObjects().forEach((o) => {
|
|
1931
1823
|
o.set("opacity", t);
|
|
1932
|
-
}) :
|
|
1933
|
-
object:
|
|
1824
|
+
}) : a.set("opacity", t), i.renderAll(), s || n.saveState(), i.fire("editor:object-opacity-changed", {
|
|
1825
|
+
object: a,
|
|
1934
1826
|
opacity: t,
|
|
1935
|
-
withoutSave:
|
|
1827
|
+
withoutSave: s
|
|
1936
1828
|
}));
|
|
1937
1829
|
}
|
|
1938
1830
|
/**
|
|
1939
1831
|
* Масштабирование объекта
|
|
1940
|
-
* @param
|
|
1941
|
-
* @param
|
|
1942
|
-
* @param
|
|
1832
|
+
* @param options
|
|
1833
|
+
* @param options.object - Объект с изображением, которое нужно масштабировать
|
|
1834
|
+
* @param options.type - Тип масштабирования
|
|
1943
1835
|
* 'contain' - скейлит картинку, чтобы она вмещалась
|
|
1944
1836
|
* 'cover' - скейлит картинку, чтобы она вписалась в размер канвас
|
|
1945
|
-
* @param
|
|
1946
|
-
* @param
|
|
1837
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1838
|
+
* @param options.fitAsOneObject - Масштабировать все объекты в активной группе как один объект
|
|
1947
1839
|
* @fires editor:image-fitted
|
|
1948
1840
|
*/
|
|
1949
1841
|
fitObject({
|
|
1950
1842
|
object: e,
|
|
1951
1843
|
type: t = this.options.scaleType,
|
|
1952
|
-
withoutSave:
|
|
1953
|
-
fitAsOneObject:
|
|
1844
|
+
withoutSave: s,
|
|
1845
|
+
fitAsOneObject: i
|
|
1954
1846
|
} = {}) {
|
|
1955
|
-
const { canvas:
|
|
1956
|
-
if (
|
|
1957
|
-
if (
|
|
1958
|
-
const
|
|
1959
|
-
|
|
1960
|
-
const g =
|
|
1961
|
-
h.scale(g),
|
|
1847
|
+
const { canvas: n, imageManager: a, historyManager: o } = this.editor, d = e || n.getActiveObject();
|
|
1848
|
+
if (d) {
|
|
1849
|
+
if (d.set("angle", 0), d instanceof v && !i) {
|
|
1850
|
+
const r = d.getObjects();
|
|
1851
|
+
n.discardActiveObject(), r.forEach((h) => {
|
|
1852
|
+
const g = a.calculateScaleFactor({ imageObject: h, scaleType: t });
|
|
1853
|
+
h.scale(g), n.centerObject(h);
|
|
1962
1854
|
});
|
|
1963
|
-
const l = new
|
|
1964
|
-
|
|
1855
|
+
const l = new v(r, { canvas: n });
|
|
1856
|
+
n.setActiveObject(l);
|
|
1965
1857
|
} else {
|
|
1966
|
-
const
|
|
1967
|
-
imageObject:
|
|
1858
|
+
const r = a.calculateScaleFactor({
|
|
1859
|
+
imageObject: d,
|
|
1968
1860
|
scaleType: t
|
|
1969
1861
|
});
|
|
1970
|
-
|
|
1862
|
+
d.scale(r), n.centerObject(d);
|
|
1971
1863
|
}
|
|
1972
|
-
|
|
1973
|
-
object:
|
|
1864
|
+
n.renderAll(), s || o.saveState(), n.fire("editor:object-fitted", {
|
|
1865
|
+
object: d,
|
|
1974
1866
|
type: t,
|
|
1975
|
-
withoutSave:
|
|
1976
|
-
fitAsOneObject:
|
|
1867
|
+
withoutSave: s,
|
|
1868
|
+
fitAsOneObject: i
|
|
1977
1869
|
});
|
|
1978
1870
|
}
|
|
1979
1871
|
}
|
|
@@ -1987,66 +1879,54 @@ class it {
|
|
|
1987
1879
|
}
|
|
1988
1880
|
/**
|
|
1989
1881
|
* Сброс масштаба объекта до дефолтного
|
|
1990
|
-
* @param
|
|
1991
|
-
* @param
|
|
1992
|
-
* @param
|
|
1993
|
-
* @param
|
|
1994
|
-
* @returns
|
|
1882
|
+
* @param object
|
|
1883
|
+
* @param options
|
|
1884
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
1885
|
+
* @param options.alwaysFitObject - вписывать объект в рабочую область даже если он меньше рабочей области
|
|
1995
1886
|
* @fires editor:object-reset
|
|
1996
1887
|
*/
|
|
1997
|
-
resetObject(e, { alwaysFitObject: t = !1, withoutSave:
|
|
1888
|
+
resetObject(e, { alwaysFitObject: t = !1, withoutSave: s = !1 } = {}) {
|
|
1998
1889
|
const {
|
|
1999
|
-
canvas:
|
|
2000
|
-
montageArea:
|
|
2001
|
-
imageManager:
|
|
1890
|
+
canvas: i,
|
|
1891
|
+
montageArea: n,
|
|
1892
|
+
imageManager: a,
|
|
2002
1893
|
historyManager: o,
|
|
2003
|
-
options: { scaleType:
|
|
2004
|
-
} = this.editor,
|
|
2005
|
-
if (!
|
|
2006
|
-
if (o.suspendHistory(),
|
|
1894
|
+
options: { scaleType: d }
|
|
1895
|
+
} = this.editor, r = e || i.getActiveObject();
|
|
1896
|
+
if (!r || r.locked) return;
|
|
1897
|
+
if (o.suspendHistory(), r.type === "image" || r.format === "svg" || r.set({
|
|
2007
1898
|
scaleX: 1,
|
|
2008
1899
|
scaleY: 1,
|
|
2009
1900
|
flipX: !1,
|
|
2010
1901
|
flipY: !1,
|
|
2011
1902
|
angle: 0
|
|
2012
1903
|
}), t)
|
|
2013
|
-
this.fitObject({ object:
|
|
1904
|
+
this.fitObject({ object: r, withoutSave: !0, fitAsOneObject: !0 });
|
|
2014
1905
|
else {
|
|
2015
|
-
const { width: h, height: g } =
|
|
2016
|
-
imageObject:
|
|
2017
|
-
scaleType:
|
|
1906
|
+
const { width: h, height: g } = n, { width: u, height: m } = r, M = a.calculateScaleFactor({
|
|
1907
|
+
imageObject: r,
|
|
1908
|
+
scaleType: d
|
|
2018
1909
|
});
|
|
2019
|
-
|
|
1910
|
+
d === "contain" && M < 1 || d === "cover" && (u > h || m > g) ? this.fitObject({ object: r, withoutSave: !0, fitAsOneObject: !0 }) : r.set({ scaleX: 1, scaleY: 1 });
|
|
2020
1911
|
}
|
|
2021
|
-
|
|
2022
|
-
object:
|
|
2023
|
-
withoutSave:
|
|
1912
|
+
r.set({ flipX: !1, flipY: !1, angle: 0 }), i.centerObject(r), i.renderAll(), o.resumeHistory(), s || o.saveState(), i.fire("editor:object-reset", {
|
|
1913
|
+
object: r,
|
|
1914
|
+
withoutSave: s,
|
|
2024
1915
|
alwaysFitObject: t
|
|
2025
1916
|
});
|
|
2026
1917
|
}
|
|
2027
1918
|
}
|
|
2028
|
-
class
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
* @param {ImageEditor} options.editor – экземпляр редактора
|
|
2032
|
-
*/
|
|
2033
|
-
constructor(e) {
|
|
2034
|
-
var {
|
|
2035
|
-
editor: t
|
|
2036
|
-
} = e;
|
|
2037
|
-
this.editor = t, this.isBlocked = !1, this.overlayMask = null, this._createOverlay();
|
|
1919
|
+
class st {
|
|
1920
|
+
constructor({ editor: e }) {
|
|
1921
|
+
this.editor = e, this.isBlocked = !1, this.overlayMask = null, this._createOverlay();
|
|
2038
1922
|
}
|
|
2039
1923
|
/**
|
|
2040
1924
|
* Создаёт overlay для блокировки монтажной области
|
|
2041
|
-
* @private
|
|
2042
|
-
* @returns {void}
|
|
2043
1925
|
*/
|
|
2044
1926
|
_createOverlay() {
|
|
2045
|
-
|
|
1927
|
+
const {
|
|
2046
1928
|
historyManager: e,
|
|
2047
|
-
options: {
|
|
2048
|
-
overlayMaskColor: t = "rgba(0,0,0,0.5)"
|
|
2049
|
-
}
|
|
1929
|
+
options: { overlayMaskColor: t = "rgba(0,0,0,0.5)" }
|
|
2050
1930
|
} = this.editor;
|
|
2051
1931
|
e.suspendHistory(), this.overlayMask = this.editor.shapeManager.addRectangle({
|
|
2052
1932
|
fill: t,
|
|
@@ -2057,156 +1937,104 @@ class nt {
|
|
|
2057
1937
|
hasControls: !1,
|
|
2058
1938
|
visible: !1,
|
|
2059
1939
|
id: "overlay-mask"
|
|
2060
|
-
}, {
|
|
2061
|
-
withoutSelection: !0
|
|
2062
|
-
}), e.resumeHistory();
|
|
1940
|
+
}, { withoutSelection: !0 }), e.resumeHistory();
|
|
2063
1941
|
}
|
|
2064
1942
|
/**
|
|
2065
1943
|
* Обновляет размеры и позицию overlay, выносит его на передний план
|
|
2066
|
-
* @returns {void}
|
|
2067
1944
|
*/
|
|
2068
1945
|
refresh() {
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
}
|
|
2074
|
-
if (!(!t || !this.overlayMask)) {
|
|
2075
|
-
a.suspendHistory(), t.setCoords();
|
|
2076
|
-
var {
|
|
2077
|
-
left: s,
|
|
2078
|
-
top: i,
|
|
2079
|
-
width: n,
|
|
2080
|
-
height: o
|
|
2081
|
-
} = t.getBoundingRect();
|
|
2082
|
-
this.overlayMask.set({
|
|
2083
|
-
left: s,
|
|
2084
|
-
top: i,
|
|
2085
|
-
width: n,
|
|
2086
|
-
height: o
|
|
2087
|
-
}), e.discardActiveObject(), this.editor.layerManager.bringToFront(this.overlayMask, {
|
|
2088
|
-
withoutSave: !0
|
|
2089
|
-
}), a.resumeHistory();
|
|
2090
|
-
}
|
|
1946
|
+
const { canvas: e, montageArea: t, historyManager: s } = this.editor;
|
|
1947
|
+
if (!t || !this.overlayMask) return;
|
|
1948
|
+
s.suspendHistory(), t.setCoords();
|
|
1949
|
+
const { left: i, top: n, width: a, height: o } = t.getBoundingRect();
|
|
1950
|
+
this.overlayMask.set({ left: i, top: n, width: a, height: o }), e.discardActiveObject(), this.editor.layerManager.bringToFront(this.overlayMask, { withoutSave: !0 }), s.resumeHistory();
|
|
2091
1951
|
}
|
|
2092
1952
|
/**
|
|
2093
1953
|
* Выключает редактор:
|
|
2094
1954
|
* - убирает все селекты, события мыши, скейл/драг–н–дроп
|
|
2095
1955
|
* - делает все объекты не‑evented и не‑selectable
|
|
2096
1956
|
* - делает видимым overlayMask поверх всех объектов в монтажной области
|
|
2097
|
-
* @returns {void}
|
|
2098
1957
|
*/
|
|
2099
1958
|
block() {
|
|
2100
|
-
if (!this.
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
} = this.editor;
|
|
2106
|
-
a.suspendHistory(), this.isBlocked = !0, e.discardActiveObject(), e.selection = !1, e.skipTargetFind = !0, t.getObjects().forEach((s) => {
|
|
2107
|
-
s.evented = !1, s.selectable = !1;
|
|
2108
|
-
}), e.upperCanvasEl.style.pointerEvents = "none", e.lowerCanvasEl.style.pointerEvents = "none", this.overlayMask.visible = !0, this.refresh(), e.fire("editor:disabled"), a.resumeHistory();
|
|
2109
|
-
}
|
|
1959
|
+
if (this.isBlocked || !this.overlayMask) return;
|
|
1960
|
+
const { canvas: e, canvasManager: t, historyManager: s } = this.editor;
|
|
1961
|
+
s.suspendHistory(), this.isBlocked = !0, e.discardActiveObject(), e.selection = !1, e.skipTargetFind = !0, t.getObjects().forEach((i) => {
|
|
1962
|
+
i.evented = !1, i.selectable = !1;
|
|
1963
|
+
}), e.upperCanvasEl.style.pointerEvents = "none", e.lowerCanvasEl.style.pointerEvents = "none", this.overlayMask.visible = !0, this.refresh(), e.fire("editor:disabled"), s.resumeHistory();
|
|
2110
1964
|
}
|
|
2111
1965
|
/**
|
|
2112
1966
|
* Включает редактор
|
|
2113
|
-
* @returns {void}
|
|
2114
1967
|
*/
|
|
2115
1968
|
unblock() {
|
|
2116
|
-
if (this.isBlocked)
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
} = this.editor;
|
|
2122
|
-
a.suspendHistory(), this.isBlocked = !1, e.selection = !0, e.skipTargetFind = !1, t.getObjects().forEach((s) => {
|
|
2123
|
-
s.evented = !0, s.selectable = !0;
|
|
2124
|
-
}), e.upperCanvasEl.style.pointerEvents = "", e.lowerCanvasEl.style.pointerEvents = "", this.overlayMask.visible = !1, e.requestRenderAll(), e.fire("editor:enabled"), a.resumeHistory();
|
|
2125
|
-
}
|
|
1969
|
+
if (!this.isBlocked || !this.overlayMask) return;
|
|
1970
|
+
const { canvas: e, canvasManager: t, historyManager: s } = this.editor;
|
|
1971
|
+
s.suspendHistory(), this.isBlocked = !1, e.selection = !0, e.skipTargetFind = !1, t.getObjects().forEach((i) => {
|
|
1972
|
+
i.evented = !0, i.selectable = !0;
|
|
1973
|
+
}), e.upperCanvasEl.style.pointerEvents = "", e.lowerCanvasEl.style.pointerEvents = "", this.overlayMask.visible = !1, e.requestRenderAll(), e.fire("editor:enabled"), s.resumeHistory();
|
|
2126
1974
|
}
|
|
2127
1975
|
}
|
|
2128
|
-
class
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
* @param {ImageEditor} options.editor - экземпляр редактора с доступом к canvas
|
|
2132
|
-
*/
|
|
2133
|
-
constructor(e) {
|
|
2134
|
-
var {
|
|
2135
|
-
editor: t
|
|
2136
|
-
} = e;
|
|
2137
|
-
this.editor = t;
|
|
1976
|
+
class P {
|
|
1977
|
+
constructor({ editor: e }) {
|
|
1978
|
+
this.editor = e;
|
|
2138
1979
|
}
|
|
2139
1980
|
/**
|
|
2140
1981
|
* Поднять объект навверх по оси Z
|
|
2141
|
-
* @param
|
|
2142
|
-
* @param
|
|
2143
|
-
* @param
|
|
1982
|
+
* @param object
|
|
1983
|
+
* @param options
|
|
1984
|
+
* @param options.withoutSave - Не сохранять действие в истории изменений
|
|
2144
1985
|
* @fires editor:object-bring-to-front
|
|
2145
1986
|
*/
|
|
2146
|
-
bringToFront(e) {
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
}
|
|
2153
|
-
|
|
2154
|
-
var i = e || a.getActiveObject();
|
|
2155
|
-
i && (i.type === "activeselection" ? i.getObjects().forEach((n) => {
|
|
2156
|
-
a.bringObjectToFront(n);
|
|
2157
|
-
}) : a.bringObjectToFront(i), a.renderAll(), s.resumeHistory(), t || s.saveState(), a.fire("editor:object-bring-to-front", {
|
|
2158
|
-
object: i,
|
|
1987
|
+
bringToFront(e, { withoutSave: t } = {}) {
|
|
1988
|
+
const { canvas: s, historyManager: i } = this.editor;
|
|
1989
|
+
i.suspendHistory();
|
|
1990
|
+
const n = e || s.getActiveObject();
|
|
1991
|
+
n && (n instanceof v ? n.getObjects().forEach((a) => {
|
|
1992
|
+
s.bringObjectToFront(a);
|
|
1993
|
+
}) : s.bringObjectToFront(n), s.renderAll(), i.resumeHistory(), t || i.saveState(), s.fire("editor:object-bring-to-front", {
|
|
1994
|
+
object: n,
|
|
2159
1995
|
withoutSave: t
|
|
2160
1996
|
}));
|
|
2161
1997
|
}
|
|
2162
1998
|
/**
|
|
2163
1999
|
* Поднять объект на один уровень вверх по оси Z
|
|
2164
|
-
* @param
|
|
2165
|
-
* @param
|
|
2166
|
-
* @param
|
|
2000
|
+
* @param object
|
|
2001
|
+
* @param options
|
|
2002
|
+
* @param options.withoutSave - Не сохранять действие в истории изменений
|
|
2167
2003
|
* @fires editor:object-bring-forward
|
|
2168
2004
|
*/
|
|
2169
|
-
bringForward(e) {
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
} = this.editor;
|
|
2176
|
-
s.suspendHistory();
|
|
2177
|
-
var i = e || a.getActiveObject();
|
|
2178
|
-
i && (i.type === "activeselection" ? F._moveSelectionForward(a, i) : a.bringObjectForward(i), a.renderAll(), s.resumeHistory(), t || s.saveState(), a.fire("editor:object-bring-forward", {
|
|
2179
|
-
object: i,
|
|
2005
|
+
bringForward(e, { withoutSave: t } = {}) {
|
|
2006
|
+
const { canvas: s, historyManager: i } = this.editor;
|
|
2007
|
+
i.suspendHistory();
|
|
2008
|
+
const n = e || s.getActiveObject();
|
|
2009
|
+
n && (n instanceof v ? P._moveSelectionForward(s, n) : s.bringObjectForward(n), s.renderAll(), i.resumeHistory(), t || i.saveState(), s.fire("editor:object-bring-forward", {
|
|
2010
|
+
object: n,
|
|
2180
2011
|
withoutSave: t
|
|
2181
2012
|
}));
|
|
2182
2013
|
}
|
|
2183
2014
|
/**
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
sendToBack(e) {
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
historyManager: i,
|
|
2197
|
-
interactionBlocker: {
|
|
2198
|
-
overlayMask: n
|
|
2199
|
-
}
|
|
2015
|
+
* Отправить объект на задний план по оси Z
|
|
2016
|
+
* @param object
|
|
2017
|
+
* @param options
|
|
2018
|
+
* @param options.withoutSave - Не сохранять действие в истории изменений
|
|
2019
|
+
* @fires editor:object-send-to-back
|
|
2020
|
+
*/
|
|
2021
|
+
sendToBack(e, { withoutSave: t } = {}) {
|
|
2022
|
+
const {
|
|
2023
|
+
canvas: s,
|
|
2024
|
+
montageArea: i,
|
|
2025
|
+
historyManager: n,
|
|
2026
|
+
interactionBlocker: { overlayMask: a }
|
|
2200
2027
|
} = this.editor;
|
|
2201
|
-
|
|
2202
|
-
|
|
2028
|
+
n.suspendHistory();
|
|
2029
|
+
const o = e || s.getActiveObject();
|
|
2203
2030
|
if (o) {
|
|
2204
|
-
if (o
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2031
|
+
if (o instanceof v) {
|
|
2032
|
+
const d = o.getObjects();
|
|
2033
|
+
for (let r = d.length - 1; r >= 0; r -= 1)
|
|
2034
|
+
s.sendObjectToBack(d[r]);
|
|
2035
|
+
} else
|
|
2036
|
+
s.sendObjectToBack(o);
|
|
2037
|
+
s.sendObjectToBack(i), a && s.sendObjectToBack(a), s.renderAll(), n.resumeHistory(), t || n.saveState(), s.fire("editor:object-send-to-back", {
|
|
2210
2038
|
object: o,
|
|
2211
2039
|
withoutSave: t
|
|
2212
2040
|
});
|
|
@@ -2214,97 +2042,87 @@ class F {
|
|
|
2214
2042
|
}
|
|
2215
2043
|
/**
|
|
2216
2044
|
* Отправить объект на один уровень ниже по оси Z
|
|
2217
|
-
* @param
|
|
2218
|
-
* @param
|
|
2219
|
-
* @param
|
|
2045
|
+
* @param object
|
|
2046
|
+
* @param options
|
|
2047
|
+
* @param options.withoutSave - Не сохранять действие в истории изменений
|
|
2220
2048
|
*/
|
|
2221
|
-
sendBackwards(e) {
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
historyManager: i,
|
|
2228
|
-
interactionBlocker: {
|
|
2229
|
-
overlayMask: n
|
|
2230
|
-
}
|
|
2049
|
+
sendBackwards(e, { withoutSave: t } = {}) {
|
|
2050
|
+
const {
|
|
2051
|
+
canvas: s,
|
|
2052
|
+
montageArea: i,
|
|
2053
|
+
historyManager: n,
|
|
2054
|
+
interactionBlocker: { overlayMask: a }
|
|
2231
2055
|
} = this.editor;
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
o && (o
|
|
2056
|
+
n.suspendHistory();
|
|
2057
|
+
const o = e || s.getActiveObject();
|
|
2058
|
+
o && (o instanceof v ? P._moveSelectionBackwards(s, o) : s.sendObjectBackwards(o), s.sendObjectToBack(i), a && s.sendObjectToBack(a), s.renderAll(), n.resumeHistory(), t || n.saveState(), s.fire("editor:object-send-backwards", {
|
|
2235
2059
|
object: o,
|
|
2236
2060
|
withoutSave: t
|
|
2237
2061
|
}));
|
|
2238
2062
|
}
|
|
2239
2063
|
/**
|
|
2240
2064
|
* Сдвигает выделенные объекты на один уровень вверх относительно ближайшего верхнего объекта
|
|
2241
|
-
* @param
|
|
2242
|
-
* @param
|
|
2243
|
-
* @returns {void}
|
|
2244
|
-
* @private
|
|
2065
|
+
* @param canvas - экземпляр холста
|
|
2066
|
+
* @param activeSelection - активное выделение
|
|
2245
2067
|
*/
|
|
2246
2068
|
static _moveSelectionForward(e, t) {
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
obj: l,
|
|
2256
|
-
index: a.indexOf(l)
|
|
2257
|
-
})).sort((l, h) => h.index - l.index);
|
|
2258
|
-
d.forEach((l) => {
|
|
2259
|
-
var h = a.indexOf(l.obj);
|
|
2260
|
-
h < n && (e.moveObjectTo(l.obj, n), n = h);
|
|
2261
|
-
});
|
|
2069
|
+
const s = e.getObjects(), i = t.getObjects(), n = i.map((o) => s.indexOf(o));
|
|
2070
|
+
let a = -1;
|
|
2071
|
+
for (let o = 0; o < s.length; o += 1) {
|
|
2072
|
+
const d = s[o];
|
|
2073
|
+
if (!i.includes(d) && n.some((r) => o > r)) {
|
|
2074
|
+
a = o;
|
|
2075
|
+
break;
|
|
2076
|
+
}
|
|
2262
2077
|
}
|
|
2078
|
+
a !== -1 && i.map((d) => ({ obj: d, index: s.indexOf(d) })).sort((d, r) => r.index - d.index).forEach((d) => {
|
|
2079
|
+
const r = s.indexOf(d.obj);
|
|
2080
|
+
r < a && (e.moveObjectTo(d.obj, a), a = r);
|
|
2081
|
+
});
|
|
2263
2082
|
}
|
|
2264
2083
|
/**
|
|
2265
2084
|
* Сдвигает выделенные объекты на один уровень вниз относительно ближайшего нижнего объекта
|
|
2266
|
-
* @param
|
|
2267
|
-
* @param
|
|
2268
|
-
* @returns {void}
|
|
2269
|
-
* @private
|
|
2085
|
+
* @param canvas - экземпляр холста
|
|
2086
|
+
* @param activeSelection - активное выделение
|
|
2270
2087
|
*/
|
|
2271
2088
|
static _moveSelectionBackwards(e, t) {
|
|
2272
|
-
|
|
2273
|
-
|
|
2089
|
+
const s = e.getObjects(), i = t.getObjects(), n = Math.min(...i.map((a) => s.indexOf(a)));
|
|
2090
|
+
for (let a = i.length - 1; a >= 0; a -= 1)
|
|
2091
|
+
e.moveObjectTo(i[a], n - 1);
|
|
2274
2092
|
}
|
|
2275
2093
|
}
|
|
2276
|
-
class
|
|
2094
|
+
class it {
|
|
2277
2095
|
/**
|
|
2278
2096
|
* Менеджер фигур для редактора.
|
|
2279
|
-
* @param
|
|
2280
|
-
* @param
|
|
2097
|
+
* @param options - Опции и настройки менеджера фигур.
|
|
2098
|
+
* @param options.editor - Ссылка на экземпляр редактора.
|
|
2281
2099
|
*/
|
|
2282
2100
|
constructor({ editor: e }) {
|
|
2283
2101
|
this.editor = e;
|
|
2284
2102
|
}
|
|
2285
2103
|
/**
|
|
2286
2104
|
* Добавление прямоугольника
|
|
2287
|
-
* @param
|
|
2288
|
-
* @param
|
|
2289
|
-
* @param
|
|
2290
|
-
* @param
|
|
2291
|
-
* @param
|
|
2292
|
-
* @param
|
|
2293
|
-
* @param
|
|
2294
|
-
* @param
|
|
2105
|
+
* @param shapeOptions
|
|
2106
|
+
* @param shapeOptions.id - Уникальный идентификатор фигуры
|
|
2107
|
+
* @param shapeOptions.left - Координата X
|
|
2108
|
+
* @param shapeOptions.top - Координата Y
|
|
2109
|
+
* @param shapeOptions.width - Ширина
|
|
2110
|
+
* @param shapeOptions.height - Высота
|
|
2111
|
+
* @param shapeOptions.fill - Цвет заливки
|
|
2112
|
+
* @param shapeOptions.rest - Остальные параметры
|
|
2295
2113
|
*
|
|
2296
|
-
* @param
|
|
2297
|
-
* @param
|
|
2298
|
-
* @param
|
|
2114
|
+
* @param flags - Флаги для управления поведением
|
|
2115
|
+
* @param flags.withoutSelection - Не выделять объект
|
|
2116
|
+
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2299
2117
|
*/
|
|
2300
|
-
addRectangle(l = {}, { withoutSelection:
|
|
2118
|
+
addRectangle(l = {}, { withoutSelection: d, withoutAdding: r } = {}) {
|
|
2301
2119
|
var h = l, {
|
|
2302
2120
|
id: e = `rect-${D()}`,
|
|
2303
2121
|
left: t,
|
|
2304
|
-
top:
|
|
2305
|
-
width:
|
|
2306
|
-
height:
|
|
2307
|
-
fill:
|
|
2122
|
+
top: s,
|
|
2123
|
+
width: i = 100,
|
|
2124
|
+
height: n = 100,
|
|
2125
|
+
fill: a = "blue"
|
|
2308
2126
|
} = h, o = Y(h, [
|
|
2309
2127
|
"id",
|
|
2310
2128
|
"left",
|
|
@@ -2313,80 +2131,80 @@ class ot {
|
|
|
2313
2131
|
"height",
|
|
2314
2132
|
"fill"
|
|
2315
2133
|
]);
|
|
2316
|
-
const { canvas: g } = this.editor, u = new
|
|
2134
|
+
const { canvas: g } = this.editor, u = new ve(f({
|
|
2317
2135
|
id: e,
|
|
2318
2136
|
left: t,
|
|
2319
|
-
top:
|
|
2320
|
-
width:
|
|
2321
|
-
height:
|
|
2322
|
-
fill:
|
|
2137
|
+
top: s,
|
|
2138
|
+
width: i,
|
|
2139
|
+
height: n,
|
|
2140
|
+
fill: a
|
|
2323
2141
|
}, o));
|
|
2324
|
-
return !t && !
|
|
2142
|
+
return !t && !s && g.centerObject(u), r || (g.add(u), d || g.setActiveObject(u), g.renderAll()), u;
|
|
2325
2143
|
}
|
|
2326
2144
|
/**
|
|
2327
2145
|
* Добавление круга
|
|
2328
|
-
* @param
|
|
2329
|
-
* @param
|
|
2330
|
-
* @param
|
|
2331
|
-
* @param
|
|
2332
|
-
* @param
|
|
2333
|
-
* @param
|
|
2334
|
-
* @param
|
|
2335
|
-
* @param
|
|
2336
|
-
* @param
|
|
2146
|
+
* @param shapeOptions
|
|
2147
|
+
* @param shapeOptions.id - Уникальный идентификатор фигуры
|
|
2148
|
+
* @param shapeOptions.left - Координата X
|
|
2149
|
+
* @param shapeOptions.top - Координата Y
|
|
2150
|
+
* @param shapeOptions.radius - Радиус
|
|
2151
|
+
* @param shapeOptions.fill - Цвет заливки
|
|
2152
|
+
* @param shapeOptions.originX - Ориентация по X
|
|
2153
|
+
* @param shapeOptions.originY - Ориентация по Y
|
|
2154
|
+
* @param shapeOptions.rest - Остальные параметры
|
|
2337
2155
|
*
|
|
2338
|
-
* @param
|
|
2339
|
-
* @param
|
|
2340
|
-
* @param
|
|
2156
|
+
* @param flags - Флаги для управления поведением
|
|
2157
|
+
* @param flags.withoutSelection - Не выделять объект
|
|
2158
|
+
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2341
2159
|
*/
|
|
2342
|
-
addCircle(
|
|
2343
|
-
var l =
|
|
2160
|
+
addCircle(r = {}, { withoutSelection: o, withoutAdding: d } = {}) {
|
|
2161
|
+
var l = r, {
|
|
2344
2162
|
id: e = `circle-${D()}`,
|
|
2345
2163
|
left: t,
|
|
2346
|
-
top:
|
|
2347
|
-
radius:
|
|
2348
|
-
fill:
|
|
2349
|
-
} = l,
|
|
2164
|
+
top: s,
|
|
2165
|
+
radius: i = 50,
|
|
2166
|
+
fill: n = "green"
|
|
2167
|
+
} = l, a = Y(l, [
|
|
2350
2168
|
"id",
|
|
2351
2169
|
"left",
|
|
2352
2170
|
"top",
|
|
2353
2171
|
"radius",
|
|
2354
2172
|
"fill"
|
|
2355
2173
|
]);
|
|
2356
|
-
const { canvas: h } = this.editor, g = new
|
|
2174
|
+
const { canvas: h } = this.editor, g = new Ae(f({
|
|
2357
2175
|
id: e,
|
|
2358
2176
|
left: t,
|
|
2359
|
-
top:
|
|
2360
|
-
fill:
|
|
2361
|
-
radius:
|
|
2362
|
-
},
|
|
2363
|
-
return !t && !
|
|
2177
|
+
top: s,
|
|
2178
|
+
fill: n,
|
|
2179
|
+
radius: i
|
|
2180
|
+
}, a));
|
|
2181
|
+
return !t && !s && h.centerObject(g), d || (h.add(g), o || h.setActiveObject(g), h.renderAll()), g;
|
|
2364
2182
|
}
|
|
2365
2183
|
/**
|
|
2366
2184
|
* Добавление треугольника
|
|
2367
|
-
* @param
|
|
2368
|
-
* @param
|
|
2369
|
-
* @param
|
|
2370
|
-
* @param
|
|
2371
|
-
* @param
|
|
2372
|
-
* @param
|
|
2373
|
-
* @param
|
|
2374
|
-
* @param
|
|
2375
|
-
* @param
|
|
2376
|
-
* @param
|
|
2185
|
+
* @param shapeOptions
|
|
2186
|
+
* @param shapeOptions.id - Уникальный идентификатор фигуры
|
|
2187
|
+
* @param shapeOptions.left - Координата X
|
|
2188
|
+
* @param shapeOptions.top - Координата Y
|
|
2189
|
+
* @param shapeOptions.width - Ширина
|
|
2190
|
+
* @param shapeOptions.height - Высота
|
|
2191
|
+
* @param shapeOptions.originX - Ориентация по X
|
|
2192
|
+
* @param shapeOptions.originY - Ориентация по Y
|
|
2193
|
+
* @param shapeOptions.fill - Цвет заливки
|
|
2194
|
+
* @param shapeOptions.rest - Остальные параметры
|
|
2377
2195
|
*
|
|
2378
|
-
* @param
|
|
2379
|
-
* @param
|
|
2380
|
-
* @param
|
|
2196
|
+
* @param flags - Флаги для управления поведением
|
|
2197
|
+
* @param flags.withoutSelection - Не выделять объект
|
|
2198
|
+
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2381
2199
|
*/
|
|
2382
|
-
addTriangle(l = {}, { withoutSelection:
|
|
2200
|
+
addTriangle(l = {}, { withoutSelection: d, withoutAdding: r } = {}) {
|
|
2383
2201
|
var h = l, {
|
|
2384
2202
|
id: e = `triangle-${D()}`,
|
|
2385
2203
|
left: t,
|
|
2386
|
-
top:
|
|
2387
|
-
width:
|
|
2388
|
-
height:
|
|
2389
|
-
fill:
|
|
2204
|
+
top: s,
|
|
2205
|
+
width: i = 100,
|
|
2206
|
+
height: n = 100,
|
|
2207
|
+
fill: a = "yellow"
|
|
2390
2208
|
} = h, o = Y(h, [
|
|
2391
2209
|
"id",
|
|
2392
2210
|
"left",
|
|
@@ -2395,21 +2213,21 @@ class ot {
|
|
|
2395
2213
|
"height",
|
|
2396
2214
|
"fill"
|
|
2397
2215
|
]);
|
|
2398
|
-
const { canvas: g } = this.editor, u = new
|
|
2216
|
+
const { canvas: g } = this.editor, u = new Se(f({
|
|
2399
2217
|
id: e,
|
|
2400
2218
|
left: t,
|
|
2401
|
-
top:
|
|
2402
|
-
fill:
|
|
2403
|
-
width:
|
|
2404
|
-
height:
|
|
2219
|
+
top: s,
|
|
2220
|
+
fill: a,
|
|
2221
|
+
width: i,
|
|
2222
|
+
height: n
|
|
2405
2223
|
}, o));
|
|
2406
|
-
return !t && !
|
|
2224
|
+
return !t && !s && g.centerObject(u), r || (g.add(u), d || g.setActiveObject(u), g.renderAll()), u;
|
|
2407
2225
|
}
|
|
2408
2226
|
}
|
|
2409
|
-
class
|
|
2227
|
+
class nt {
|
|
2410
2228
|
/**
|
|
2411
|
-
* @param
|
|
2412
|
-
* @param
|
|
2229
|
+
* @param options
|
|
2230
|
+
* @param options.editor - экземпляр редактора с доступом к canvas
|
|
2413
2231
|
*/
|
|
2414
2232
|
constructor({ editor: e }) {
|
|
2415
2233
|
this.editor = e, this.clipboard = null;
|
|
@@ -2419,8 +2237,8 @@ class rt {
|
|
|
2419
2237
|
* @fires editor:object-copied
|
|
2420
2238
|
*/
|
|
2421
2239
|
copy() {
|
|
2422
|
-
const { canvas: e, errorManager: t } = this.editor,
|
|
2423
|
-
if (!
|
|
2240
|
+
const { canvas: e, errorManager: t } = this.editor, s = e.getActiveObject();
|
|
2241
|
+
if (!s) return;
|
|
2424
2242
|
if (typeof ClipboardItem == "undefined" || !navigator.clipboard) {
|
|
2425
2243
|
t.emitWarning({
|
|
2426
2244
|
origin: "ClipboardManager",
|
|
@@ -2428,11 +2246,11 @@ class rt {
|
|
|
2428
2246
|
code: "CLIPBOARD_NOT_SUPPORTED",
|
|
2429
2247
|
// eslint-disable-next-line max-len
|
|
2430
2248
|
message: "ClipboardManager. navigator.clipboard не поддерживается в этом браузере или отсутствует соединение по HTTPS-протоколу."
|
|
2431
|
-
}), this._cloneAndFire(e,
|
|
2249
|
+
}), this._cloneAndFire(e, s);
|
|
2432
2250
|
return;
|
|
2433
2251
|
}
|
|
2434
|
-
if (
|
|
2435
|
-
const g = `application/image-editor:${JSON.stringify(
|
|
2252
|
+
if (s.type !== "image") {
|
|
2253
|
+
const g = `application/image-editor:${JSON.stringify(s.toObject(["format"]))}`;
|
|
2436
2254
|
navigator.clipboard.writeText(g).catch((u) => {
|
|
2437
2255
|
t.emitWarning({
|
|
2438
2256
|
origin: "ClipboardManager",
|
|
@@ -2441,13 +2259,13 @@ class rt {
|
|
|
2441
2259
|
message: `Ошибка записи текстового объекта в буфер обмена: ${u.message}`,
|
|
2442
2260
|
data: u
|
|
2443
2261
|
});
|
|
2444
|
-
}), this._cloneAndFire(e,
|
|
2262
|
+
}), this._cloneAndFire(e, s);
|
|
2445
2263
|
return;
|
|
2446
2264
|
}
|
|
2447
|
-
const
|
|
2448
|
-
for (let g = 0; g <
|
|
2449
|
-
|
|
2450
|
-
const l = new Blob([
|
|
2265
|
+
const n = s.toCanvasElement().toDataURL(), a = n.slice(5).split(";")[0], o = n.split(",")[1], d = atob(o), r = new Uint8Array(d.length);
|
|
2266
|
+
for (let g = 0; g < d.length; g += 1)
|
|
2267
|
+
r[g] = d.charCodeAt(g);
|
|
2268
|
+
const l = new Blob([r.buffer], { type: a }), h = new ClipboardItem({ [a]: l });
|
|
2451
2269
|
navigator.clipboard.write([h]).catch((g) => {
|
|
2452
2270
|
t.emitWarning({
|
|
2453
2271
|
origin: "ClipboardManager",
|
|
@@ -2455,7 +2273,7 @@ class rt {
|
|
|
2455
2273
|
code: "CLIPBOARD_WRITE_IMAGE_FAILED",
|
|
2456
2274
|
message: `Ошибка записи изображения в буфер обмена: ${g.message}`
|
|
2457
2275
|
});
|
|
2458
|
-
}), this._cloneAndFire(e,
|
|
2276
|
+
}), this._cloneAndFire(e, s);
|
|
2459
2277
|
}
|
|
2460
2278
|
/**
|
|
2461
2279
|
* Клонирует объект и вызывает событие 'editor:object-copied'.
|
|
@@ -2463,42 +2281,42 @@ class rt {
|
|
|
2463
2281
|
* @param object - активный объект
|
|
2464
2282
|
*/
|
|
2465
2283
|
_cloneAndFire(e, t) {
|
|
2466
|
-
t.clone(["format"]).then((
|
|
2467
|
-
this.clipboard =
|
|
2468
|
-
}).catch((
|
|
2284
|
+
t.clone(["format"]).then((s) => {
|
|
2285
|
+
this.clipboard = s, e.fire("editor:object-copied", { object: s });
|
|
2286
|
+
}).catch((s) => {
|
|
2469
2287
|
this.editor.errorManager.emitError({
|
|
2470
2288
|
origin: "ClipboardManager",
|
|
2471
2289
|
method: "_cloneAndFire",
|
|
2472
2290
|
code: "CLONE_FAILED",
|
|
2473
2291
|
message: "Ошибка клонирования объекта",
|
|
2474
|
-
data:
|
|
2292
|
+
data: s
|
|
2475
2293
|
});
|
|
2476
2294
|
});
|
|
2477
2295
|
}
|
|
2478
2296
|
/**
|
|
2479
2297
|
* Обработчик вставки объекта или изображения из буфера обмена.
|
|
2480
|
-
* @param
|
|
2481
|
-
* @param
|
|
2482
|
-
* @param
|
|
2298
|
+
* @param event — объект события
|
|
2299
|
+
* @param event.clipboardData — данные из буфера обмена
|
|
2300
|
+
* @param event.clipboardData.items — элементы буфера обмена
|
|
2483
2301
|
*/
|
|
2484
2302
|
handlePasteEvent({ clipboardData: e }) {
|
|
2485
|
-
var
|
|
2486
|
-
if (!((
|
|
2487
|
-
const { imageManager: t } = this.editor, { items:
|
|
2488
|
-
if (
|
|
2489
|
-
const o =
|
|
2303
|
+
var a;
|
|
2304
|
+
if (!((a = e == null ? void 0 : e.items) != null && a.length)) return;
|
|
2305
|
+
const { imageManager: t } = this.editor, { items: s } = e, i = s[s.length - 1];
|
|
2306
|
+
if (i.type !== "text/html") {
|
|
2307
|
+
const o = i.getAsFile();
|
|
2490
2308
|
if (!o) return;
|
|
2491
|
-
const
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
},
|
|
2309
|
+
const d = new FileReader();
|
|
2310
|
+
d.onload = (r) => {
|
|
2311
|
+
r.target && this.editor.imageManager.importImage({ source: r.target.result });
|
|
2312
|
+
}, d.readAsDataURL(o);
|
|
2495
2313
|
return;
|
|
2496
2314
|
}
|
|
2497
|
-
const
|
|
2498
|
-
if (
|
|
2499
|
-
const
|
|
2500
|
-
if (
|
|
2501
|
-
t.importImage({ source:
|
|
2315
|
+
const n = e.getData("text/html");
|
|
2316
|
+
if (n) {
|
|
2317
|
+
const r = new DOMParser().parseFromString(n, "text/html").querySelector("img");
|
|
2318
|
+
if (r != null && r.src) {
|
|
2319
|
+
t.importImage({ source: r.src });
|
|
2502
2320
|
return;
|
|
2503
2321
|
}
|
|
2504
2322
|
}
|
|
@@ -2509,7 +2327,7 @@ class rt {
|
|
|
2509
2327
|
* @fires editor:object-pasted
|
|
2510
2328
|
*/
|
|
2511
2329
|
paste() {
|
|
2512
|
-
return
|
|
2330
|
+
return I(this, null, function* () {
|
|
2513
2331
|
const { canvas: e } = this.editor;
|
|
2514
2332
|
if (!this.clipboard) return;
|
|
2515
2333
|
const t = yield this.clipboard.clone(["format"]);
|
|
@@ -2518,214 +2336,173 @@ class rt {
|
|
|
2518
2336
|
left: t.left + 10,
|
|
2519
2337
|
top: t.top + 10,
|
|
2520
2338
|
evented: !0
|
|
2521
|
-
}), t instanceof
|
|
2522
|
-
e.add(
|
|
2339
|
+
}), t instanceof v ? (t.canvas = e, t.forEachObject((s) => {
|
|
2340
|
+
e.add(s);
|
|
2523
2341
|
})) : e.add(t), e.setActiveObject(t), e.requestRenderAll(), e.fire("editor:object-pasted", { object: t });
|
|
2524
2342
|
});
|
|
2525
2343
|
}
|
|
2526
2344
|
}
|
|
2527
|
-
class
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
* @param {ImageEditor} options.editor - экземпляр редактора с доступом к canvas
|
|
2531
|
-
*/
|
|
2532
|
-
constructor(e) {
|
|
2533
|
-
var {
|
|
2534
|
-
editor: t
|
|
2535
|
-
} = e;
|
|
2536
|
-
this.editor = t;
|
|
2345
|
+
class F {
|
|
2346
|
+
constructor({ editor: e }) {
|
|
2347
|
+
this.editor = e;
|
|
2537
2348
|
}
|
|
2538
2349
|
/**
|
|
2539
2350
|
* Блокирует объект (или группу объектов) на канвасе
|
|
2540
|
-
* @param
|
|
2541
|
-
* @param
|
|
2542
|
-
* @param
|
|
2543
|
-
* @
|
|
2351
|
+
* @param options
|
|
2352
|
+
* @param options.object - объект, который нужно заблокировать
|
|
2353
|
+
* @param options.skipInnerObjects - не блокировать внутренние объекты
|
|
2354
|
+
* @param options.withoutSave - не сохранять состояние
|
|
2544
2355
|
* @fires editor:object-locked
|
|
2545
2356
|
*/
|
|
2546
|
-
lockObject() {
|
|
2547
|
-
|
|
2548
|
-
|
|
2357
|
+
lockObject({ object: e, skipInnerObjects: t, withoutSave: s } = {}) {
|
|
2358
|
+
const { canvas: i, historyManager: n } = this.editor, a = e || i.getActiveObject();
|
|
2359
|
+
if (!a || a.locked) return;
|
|
2360
|
+
const o = {
|
|
2361
|
+
lockMovementX: !0,
|
|
2362
|
+
lockMovementY: !0,
|
|
2363
|
+
lockRotation: !0,
|
|
2364
|
+
lockScalingX: !0,
|
|
2365
|
+
lockScalingY: !0,
|
|
2366
|
+
lockSkewingX: !0,
|
|
2367
|
+
lockSkewingY: !0,
|
|
2368
|
+
locked: !0
|
|
2369
|
+
};
|
|
2370
|
+
a.set(o), !t && F._isGroupOrSelection(a) && a.getObjects().forEach((r) => {
|
|
2371
|
+
r.set(o);
|
|
2372
|
+
}), i.renderAll(), s || n.saveState(), i.fire("editor:object-locked", {
|
|
2373
|
+
object: a,
|
|
2549
2374
|
skipInnerObjects: t,
|
|
2550
|
-
withoutSave:
|
|
2551
|
-
}
|
|
2552
|
-
canvas: s,
|
|
2553
|
-
historyManager: i
|
|
2554
|
-
} = this.editor, n = e || s.getActiveObject();
|
|
2555
|
-
if (!(!n || n.locked)) {
|
|
2556
|
-
var o = {
|
|
2557
|
-
lockMovementX: !0,
|
|
2558
|
-
lockMovementY: !0,
|
|
2559
|
-
lockRotation: !0,
|
|
2560
|
-
lockScalingX: !0,
|
|
2561
|
-
lockScalingY: !0,
|
|
2562
|
-
lockSkewingX: !0,
|
|
2563
|
-
lockSkewingY: !0,
|
|
2564
|
-
locked: !0
|
|
2565
|
-
};
|
|
2566
|
-
n.set(o);
|
|
2567
|
-
var c = !t && ["activeselection", "group"].includes(n.type);
|
|
2568
|
-
c && n.getObjects().forEach((d) => {
|
|
2569
|
-
d.set(o);
|
|
2570
|
-
}), s.renderAll(), a || i.saveState(), s.fire("editor:object-locked", {
|
|
2571
|
-
object: n,
|
|
2572
|
-
skipInnerObjects: t,
|
|
2573
|
-
withoutSave: a
|
|
2574
|
-
});
|
|
2575
|
-
}
|
|
2375
|
+
withoutSave: s
|
|
2376
|
+
});
|
|
2576
2377
|
}
|
|
2577
2378
|
/**
|
|
2578
2379
|
* Разблокирует объект (или группу объектов) на канвасе
|
|
2579
|
-
* @param
|
|
2580
|
-
* @param
|
|
2581
|
-
* @param
|
|
2582
|
-
* @returns
|
|
2380
|
+
* @param options
|
|
2381
|
+
* @param options.object - объект, который нужно разблокировать
|
|
2382
|
+
* @param options.withoutSave - не сохранять состояние в истории изменений
|
|
2583
2383
|
* @fires editor:object-unlocked
|
|
2584
2384
|
*/
|
|
2585
|
-
unlockObject() {
|
|
2586
|
-
|
|
2587
|
-
|
|
2385
|
+
unlockObject({ object: e, withoutSave: t } = {}) {
|
|
2386
|
+
const { canvas: s, historyManager: i } = this.editor, n = e || s.getActiveObject();
|
|
2387
|
+
if (!n) return;
|
|
2388
|
+
const a = {
|
|
2389
|
+
lockMovementX: !1,
|
|
2390
|
+
lockMovementY: !1,
|
|
2391
|
+
lockRotation: !1,
|
|
2392
|
+
lockScalingX: !1,
|
|
2393
|
+
lockScalingY: !1,
|
|
2394
|
+
lockSkewingX: !1,
|
|
2395
|
+
lockSkewingY: !1,
|
|
2396
|
+
locked: !1
|
|
2397
|
+
};
|
|
2398
|
+
n.set(a), F._isGroupOrSelection(n) && n.getObjects().forEach((o) => {
|
|
2399
|
+
o.set(a);
|
|
2400
|
+
}), s.renderAll(), t || i.saveState(), s.fire("editor:object-unlocked", {
|
|
2401
|
+
object: n,
|
|
2588
2402
|
withoutSave: t
|
|
2589
|
-
}
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
if (i) {
|
|
2594
|
-
var n = {
|
|
2595
|
-
lockMovementX: !1,
|
|
2596
|
-
lockMovementY: !1,
|
|
2597
|
-
lockRotation: !1,
|
|
2598
|
-
lockScalingX: !1,
|
|
2599
|
-
lockScalingY: !1,
|
|
2600
|
-
lockSkewingX: !1,
|
|
2601
|
-
lockSkewingY: !1,
|
|
2602
|
-
locked: !1
|
|
2603
|
-
};
|
|
2604
|
-
i.set(n), ["activeselection", "group"].includes(i.type) && i.getObjects().forEach((o) => {
|
|
2605
|
-
o.set(n);
|
|
2606
|
-
}), a.renderAll(), t || s.saveState(), a.fire("editor:object-unlocked", {
|
|
2607
|
-
object: i,
|
|
2608
|
-
withoutSave: t
|
|
2609
|
-
});
|
|
2610
|
-
}
|
|
2403
|
+
});
|
|
2404
|
+
}
|
|
2405
|
+
static _isGroupOrSelection(e) {
|
|
2406
|
+
return e instanceof v || e instanceof X;
|
|
2611
2407
|
}
|
|
2612
2408
|
}
|
|
2613
|
-
class
|
|
2409
|
+
class at {
|
|
2614
2410
|
constructor({ editor: e }) {
|
|
2615
2411
|
this.editor = e;
|
|
2616
2412
|
}
|
|
2617
2413
|
/**
|
|
2618
2414
|
* Группировка объектов
|
|
2619
|
-
* @param
|
|
2620
|
-
* @param
|
|
2621
|
-
* @param
|
|
2415
|
+
* @param options
|
|
2416
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
2417
|
+
* @param options.object - массив объектов для группировки
|
|
2622
2418
|
* @fires editor:objects-grouped
|
|
2623
2419
|
*/
|
|
2624
2420
|
group({
|
|
2625
2421
|
object: e,
|
|
2626
2422
|
withoutSave: t
|
|
2627
2423
|
} = {}) {
|
|
2628
|
-
const { canvas:
|
|
2629
|
-
|
|
2630
|
-
const
|
|
2631
|
-
if (!
|
|
2632
|
-
const
|
|
2633
|
-
|
|
2634
|
-
object:
|
|
2424
|
+
const { canvas: s, historyManager: i } = this.editor;
|
|
2425
|
+
i.suspendHistory();
|
|
2426
|
+
const n = e || s.getActiveObject();
|
|
2427
|
+
if (!n || !(n instanceof v)) return;
|
|
2428
|
+
const a = n.getObjects(), o = new X(a);
|
|
2429
|
+
a.forEach((d) => s.remove(d)), o.set("id", `${o.type}-${D()}`), s.add(o), s.setActiveObject(o), s.renderAll(), i.resumeHistory(), t || i.saveState(), s.fire("editor:objects-grouped", {
|
|
2430
|
+
object: n,
|
|
2635
2431
|
group: o,
|
|
2636
2432
|
withoutSave: t
|
|
2637
2433
|
});
|
|
2638
2434
|
}
|
|
2639
2435
|
/**
|
|
2640
2436
|
* Разгруппировка объектов
|
|
2641
|
-
* @param
|
|
2642
|
-
* @param
|
|
2643
|
-
* @param
|
|
2437
|
+
* @param options
|
|
2438
|
+
* @param options.object - объект для разгруппировки
|
|
2439
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
2644
2440
|
* @fires editor:objects-ungrouped
|
|
2645
2441
|
*/
|
|
2646
2442
|
ungroup({
|
|
2647
2443
|
object: e,
|
|
2648
2444
|
withoutSave: t
|
|
2649
2445
|
} = {}) {
|
|
2650
|
-
const { canvas:
|
|
2651
|
-
|
|
2652
|
-
const
|
|
2653
|
-
if (!(
|
|
2654
|
-
const
|
|
2655
|
-
|
|
2656
|
-
const o = new
|
|
2657
|
-
canvas:
|
|
2446
|
+
const { canvas: s, historyManager: i } = this.editor;
|
|
2447
|
+
i.suspendHistory();
|
|
2448
|
+
const n = e || s.getActiveObject();
|
|
2449
|
+
if (!(n instanceof X)) return;
|
|
2450
|
+
const a = n.removeAll();
|
|
2451
|
+
s.remove(n), a.forEach((d) => s.add(d));
|
|
2452
|
+
const o = new v(a, {
|
|
2453
|
+
canvas: s
|
|
2658
2454
|
});
|
|
2659
|
-
|
|
2660
|
-
object:
|
|
2455
|
+
s.setActiveObject(o), s.renderAll(), i.resumeHistory(), t || i.saveState(), s.fire("editor:objects-ungrouped", {
|
|
2456
|
+
object: n,
|
|
2661
2457
|
selection: o,
|
|
2662
2458
|
withoutSave: t
|
|
2663
2459
|
});
|
|
2664
2460
|
}
|
|
2665
2461
|
}
|
|
2666
|
-
class
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
* @param {ImageEditor} options.editor - экземпляр редактора с доступом к canvas
|
|
2670
|
-
*/
|
|
2671
|
-
constructor(e) {
|
|
2672
|
-
var {
|
|
2673
|
-
editor: t
|
|
2674
|
-
} = e;
|
|
2675
|
-
this.editor = t;
|
|
2462
|
+
class ot {
|
|
2463
|
+
constructor({ editor: e }) {
|
|
2464
|
+
this.editor = e;
|
|
2676
2465
|
}
|
|
2677
2466
|
/**
|
|
2678
2467
|
* Выделить все объекты
|
|
2679
2468
|
* @fires editor:all-objects-selected
|
|
2680
2469
|
*/
|
|
2681
2470
|
selectAll() {
|
|
2682
|
-
|
|
2683
|
-
canvas: e,
|
|
2684
|
-
canvasManager: t,
|
|
2685
|
-
objectLockManager: a
|
|
2686
|
-
} = this.editor;
|
|
2471
|
+
const { canvas: e, canvasManager: t, objectLockManager: s } = this.editor;
|
|
2687
2472
|
e.discardActiveObject();
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
}) : s[0];
|
|
2691
|
-
i && a.lockObject({
|
|
2692
|
-
object: n,
|
|
2693
|
-
skipInnerObjects: !0,
|
|
2694
|
-
withoutSave: !0
|
|
2695
|
-
}), e.setActiveObject(n), e.requestRenderAll(), e.fire("editor:all-objects-selected", {
|
|
2696
|
-
selected: n
|
|
2697
|
-
});
|
|
2473
|
+
const i = t.getObjects(), n = i.some((o) => o.locked), a = i.length > 1 ? new v(t.getObjects(), { canvas: e }) : i[0];
|
|
2474
|
+
n && s.lockObject({ object: a, skipInnerObjects: !0, withoutSave: !0 }), e.setActiveObject(a), e.requestRenderAll(), e.fire("editor:all-objects-selected", { selected: a });
|
|
2698
2475
|
}
|
|
2699
2476
|
}
|
|
2700
|
-
class
|
|
2477
|
+
class rt {
|
|
2701
2478
|
constructor({ editor: e }) {
|
|
2702
2479
|
this.editor = e;
|
|
2703
2480
|
}
|
|
2704
2481
|
/**
|
|
2705
2482
|
* Удалить выбранные объекты
|
|
2706
|
-
* @param
|
|
2707
|
-
* @param
|
|
2708
|
-
* @param
|
|
2483
|
+
* @param options
|
|
2484
|
+
* @param options.objects - массив объектов для удаления
|
|
2485
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
2709
2486
|
* @fires editor:objects-deleted
|
|
2710
2487
|
*/
|
|
2711
2488
|
deleteSelectedObjects({
|
|
2712
2489
|
objects: e,
|
|
2713
2490
|
withoutSave: t
|
|
2714
2491
|
} = {}) {
|
|
2715
|
-
const { canvas:
|
|
2716
|
-
|
|
2492
|
+
const { canvas: s, historyManager: i, groupingManager: n } = this.editor, a = (e || s.getActiveObjects()).filter((o) => !o.locked);
|
|
2493
|
+
a != null && a.length && (i.suspendHistory(), a.forEach((o) => {
|
|
2717
2494
|
if (o.type === "group" && o.format !== "svg") {
|
|
2718
|
-
|
|
2495
|
+
n.ungroup({ object: o, withoutSave: t }), this.deleteSelectedObjects();
|
|
2719
2496
|
return;
|
|
2720
2497
|
}
|
|
2721
|
-
|
|
2722
|
-
}),
|
|
2723
|
-
objects:
|
|
2498
|
+
s.remove(o);
|
|
2499
|
+
}), s.discardActiveObject(), s.renderAll(), i.resumeHistory(), t || i.saveState(), s.fire("editor:objects-deleted", {
|
|
2500
|
+
objects: a,
|
|
2724
2501
|
withoutSave: t
|
|
2725
2502
|
}));
|
|
2726
2503
|
}
|
|
2727
2504
|
}
|
|
2728
|
-
const
|
|
2505
|
+
const ct = {
|
|
2729
2506
|
IMAGE_MANAGER: {
|
|
2730
2507
|
/**
|
|
2731
2508
|
* Некорректный Content-Type изображения
|
|
@@ -2791,108 +2568,127 @@ class V {
|
|
|
2791
2568
|
constructor({ editor: e }) {
|
|
2792
2569
|
this._buffer = [], this.editor = e;
|
|
2793
2570
|
}
|
|
2571
|
+
/**
|
|
2572
|
+
* Возвращает буфер с ошибками и предупреждениями
|
|
2573
|
+
*/
|
|
2794
2574
|
get buffer() {
|
|
2795
2575
|
return this._buffer;
|
|
2796
2576
|
}
|
|
2577
|
+
/**
|
|
2578
|
+
* Очищает буфер ошибок и предупреждений
|
|
2579
|
+
*/
|
|
2797
2580
|
cleanBuffer() {
|
|
2798
2581
|
this._buffer.length = 0;
|
|
2799
2582
|
}
|
|
2800
2583
|
/**
|
|
2801
2584
|
* Эмитит событие ошибки через fabricjs
|
|
2802
|
-
* @param
|
|
2803
|
-
* @param
|
|
2804
|
-
* @param
|
|
2805
|
-
* @param
|
|
2806
|
-
* @param
|
|
2807
|
-
* @param
|
|
2585
|
+
* @param options
|
|
2586
|
+
* @param options.origin — источник ошибки (по умолчанию 'ImageEditor')
|
|
2587
|
+
* @param options.method — метод, вызвавший ошибку (по умолчанию 'Unknown Method')
|
|
2588
|
+
* @param options.code — код ошибки (из errorCodes)
|
|
2589
|
+
* @param options.data — доп. данные (опционально)
|
|
2590
|
+
* @param options.message — текст ошибки (опционально, если не передан, то используется код ошибки)
|
|
2808
2591
|
* @fires editor:error
|
|
2809
2592
|
*/
|
|
2810
|
-
emitError({ origin: e = "ImageEditor", method: t = "Unknown Method", code:
|
|
2811
|
-
if (!V.isValidErrorCode(
|
|
2812
|
-
console.warn("Неизвестный код ошибки: ", { code:
|
|
2593
|
+
emitError({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, data: i, message: n }) {
|
|
2594
|
+
if (!V.isValidErrorCode(s)) {
|
|
2595
|
+
console.warn("Неизвестный код ошибки: ", { code: s, origin: e, method: t });
|
|
2813
2596
|
return;
|
|
2814
2597
|
}
|
|
2815
|
-
if (!
|
|
2816
|
-
const
|
|
2817
|
-
console.error(`${e}. ${t}. ${
|
|
2598
|
+
if (!s) return;
|
|
2599
|
+
const a = n || s;
|
|
2600
|
+
console.error(`${e}. ${t}. ${s}. ${a}`, i);
|
|
2818
2601
|
const o = {
|
|
2819
|
-
code:
|
|
2602
|
+
code: s,
|
|
2820
2603
|
origin: e,
|
|
2821
2604
|
method: t,
|
|
2822
|
-
message:
|
|
2823
|
-
data:
|
|
2605
|
+
message: a,
|
|
2606
|
+
data: i
|
|
2824
2607
|
};
|
|
2825
|
-
this._buffer.push(
|
|
2608
|
+
this._buffer.push(f({
|
|
2826
2609
|
type: "editor:error"
|
|
2827
2610
|
}, o)), this.editor.canvas.fire("editor:error", o);
|
|
2828
2611
|
}
|
|
2829
2612
|
/**
|
|
2830
2613
|
* Эмитит предупреждение через fabricjs
|
|
2831
|
-
* @param
|
|
2832
|
-
* @param
|
|
2833
|
-
* @param
|
|
2834
|
-
* @param
|
|
2835
|
-
* @param
|
|
2836
|
-
* @param
|
|
2614
|
+
* @param options
|
|
2615
|
+
* @param options.origin — источник предупреждения (по умолчанию 'ImageEditor')
|
|
2616
|
+
* @param options.method — метод, вызвавший предупреждение (по умолчанию 'Unknown Method')
|
|
2617
|
+
* @param ptions.code — код предупреждения (из errorCodes)
|
|
2618
|
+
* @param options.data — доп. данные (опционально)
|
|
2619
|
+
* @param options.message — текст предупреждения (опционально, если не передан, то используется код предупреждения)
|
|
2837
2620
|
* @fires editor:warning
|
|
2838
2621
|
*/
|
|
2839
|
-
emitWarning({ origin: e = "ImageEditor", method: t = "Unknown Method", code:
|
|
2840
|
-
if (!V.isValidErrorCode(
|
|
2841
|
-
console.warn("Неизвестный код предупреждения: ", { code:
|
|
2622
|
+
emitWarning({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, message: i, data: n }) {
|
|
2623
|
+
if (!V.isValidErrorCode(s)) {
|
|
2624
|
+
console.warn("Неизвестный код предупреждения: ", { code: s, origin: e, method: t });
|
|
2842
2625
|
return;
|
|
2843
2626
|
}
|
|
2844
|
-
const
|
|
2845
|
-
console.warn(`${e}. ${t}. ${
|
|
2627
|
+
const a = i || s;
|
|
2628
|
+
console.warn(`${e}. ${t}. ${s}. ${a}`, n);
|
|
2846
2629
|
const o = {
|
|
2847
|
-
code:
|
|
2630
|
+
code: s,
|
|
2848
2631
|
origin: e,
|
|
2849
2632
|
method: t,
|
|
2850
|
-
message:
|
|
2851
|
-
data:
|
|
2633
|
+
message: a,
|
|
2634
|
+
data: n
|
|
2852
2635
|
};
|
|
2853
|
-
this._buffer.push(
|
|
2636
|
+
this._buffer.push(f({
|
|
2854
2637
|
type: "editor:warning"
|
|
2855
2638
|
}, o)), this.editor.canvas.fire("editor:warning", o);
|
|
2856
2639
|
}
|
|
2640
|
+
/**
|
|
2641
|
+
* Проверяет, является ли код ошибки или предупреждения допустимым
|
|
2642
|
+
* @param code - код ошибки или предупреждения
|
|
2643
|
+
* @returns true, если код допустим, иначе false
|
|
2644
|
+
*/
|
|
2857
2645
|
static isValidErrorCode(e) {
|
|
2858
|
-
return e ? Object.values(
|
|
2646
|
+
return e ? Object.values(ct).some((t) => Object.values(t).includes(e)) : !1;
|
|
2859
2647
|
}
|
|
2860
2648
|
}
|
|
2861
|
-
class
|
|
2649
|
+
class ie {
|
|
2862
2650
|
/**
|
|
2863
2651
|
* Конструктор класса ImageEditor.
|
|
2864
|
-
* @param
|
|
2865
|
-
* @param
|
|
2652
|
+
* @param canvasId - идентификатор канваса, в котором будет создан редактор
|
|
2653
|
+
* @param options - опции и настройки редактора
|
|
2866
2654
|
*/
|
|
2867
2655
|
constructor(e, t) {
|
|
2868
2656
|
this.options = t, this.containerId = e, this.editorId = `${e}-${D()}`, this.clipboard = null, this.init();
|
|
2869
2657
|
}
|
|
2658
|
+
/**
|
|
2659
|
+
* Инициализация редактора.
|
|
2660
|
+
* Создаёт все необходимые менеджеры и загружает начальное состояние.
|
|
2661
|
+
* @fires editor:ready
|
|
2662
|
+
*/
|
|
2870
2663
|
init() {
|
|
2871
|
-
return
|
|
2664
|
+
return I(this, null, function* () {
|
|
2872
2665
|
const {
|
|
2873
2666
|
editorContainerWidth: e,
|
|
2874
2667
|
editorContainerHeight: t,
|
|
2875
|
-
canvasWrapperWidth:
|
|
2876
|
-
canvasWrapperHeight:
|
|
2877
|
-
canvasCSSWidth:
|
|
2878
|
-
canvasCSSHeight:
|
|
2668
|
+
canvasWrapperWidth: s,
|
|
2669
|
+
canvasWrapperHeight: i,
|
|
2670
|
+
canvasCSSWidth: n,
|
|
2671
|
+
canvasCSSHeight: a,
|
|
2879
2672
|
initialImage: o,
|
|
2880
|
-
initialStateJSON:
|
|
2881
|
-
scaleType:
|
|
2673
|
+
initialStateJSON: d,
|
|
2674
|
+
scaleType: r,
|
|
2882
2675
|
_onReadyCallback: l
|
|
2883
2676
|
} = this.options;
|
|
2884
|
-
if (
|
|
2677
|
+
if (Re.apply(), this.canvas = new Ce(this.containerId, this.options), this.moduleLoader = new Ee(), this.workerManager = new Oe(), this.errorManager = new V({ editor: this }), this.historyManager = new Qe({ editor: this }), this.toolbar = new Xe({ editor: this }), this.transformManager = new tt({ editor: this }), this.canvasManager = new et({ editor: this }), this.imageManager = new N({ editor: this }), this.layerManager = new P({ editor: this }), this.shapeManager = new it({ editor: this }), this.interactionBlocker = new st({ editor: this }), this.clipboardManager = new nt({ editor: this }), this.objectLockManager = new F({ editor: this }), this.groupingManager = new at({ editor: this }), this.selectionManager = new ot({ editor: this }), this.deletionManager = new rt({ editor: this }), this._createMontageArea(), this._createClippingArea(), this.listeners = new z({ editor: this, options: this.options }), this.canvasManager.setEditorContainerWidth(e), this.canvasManager.setEditorContainerHeight(t), this.canvasManager.setCanvasWrapperWidth(s), this.canvasManager.setCanvasWrapperHeight(i), this.canvasManager.setCanvasCSSWidth(n), this.canvasManager.setCanvasCSSHeight(a), o != null && o.source) {
|
|
2885
2678
|
const {
|
|
2886
2679
|
source: h,
|
|
2887
|
-
scale: g = `image-${
|
|
2680
|
+
scale: g = `image-${r}`,
|
|
2888
2681
|
withoutSave: u = !0
|
|
2889
2682
|
} = o;
|
|
2890
2683
|
yield this.imageManager.importImage({ source: h, scale: g, withoutSave: u });
|
|
2891
2684
|
} else
|
|
2892
2685
|
this.canvasManager.setDefaultScale({ withoutSave: !0 });
|
|
2893
|
-
|
|
2686
|
+
d && this.historyManager.loadStateFromFullState(d), this.historyManager.saveState(), console.log("editor:ready"), this.canvas.fire("editor:ready", this), typeof l == "function" && l(this);
|
|
2894
2687
|
});
|
|
2895
2688
|
}
|
|
2689
|
+
/**
|
|
2690
|
+
* Создаёт монтажную область
|
|
2691
|
+
*/
|
|
2896
2692
|
_createMontageArea() {
|
|
2897
2693
|
const {
|
|
2898
2694
|
montageAreaWidth: e,
|
|
@@ -2901,7 +2697,7 @@ class ae {
|
|
|
2901
2697
|
this.montageArea = this.shapeManager.addRectangle({
|
|
2902
2698
|
width: e,
|
|
2903
2699
|
height: t,
|
|
2904
|
-
fill:
|
|
2700
|
+
fill: ie._createMosaicPattern(),
|
|
2905
2701
|
stroke: null,
|
|
2906
2702
|
strokeWidth: 0,
|
|
2907
2703
|
selectable: !1,
|
|
@@ -2915,6 +2711,9 @@ class ae {
|
|
|
2915
2711
|
noScaleCache: !0
|
|
2916
2712
|
}, { withoutSelection: !0 });
|
|
2917
2713
|
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Создаёт область клиппинга
|
|
2716
|
+
*/
|
|
2918
2717
|
_createClippingArea() {
|
|
2919
2718
|
const {
|
|
2920
2719
|
montageAreaWidth: e,
|
|
@@ -2934,24 +2733,27 @@ class ae {
|
|
|
2934
2733
|
originY: "center"
|
|
2935
2734
|
}, { withoutSelection: !0, withoutAdding: !0 });
|
|
2936
2735
|
}
|
|
2736
|
+
/**
|
|
2737
|
+
* Метод для удаления редактора и всех слушателей.
|
|
2738
|
+
*/
|
|
2937
2739
|
destroy() {
|
|
2938
2740
|
this.listeners.destroy(), this.toolbar.destroy(), this.canvas.dispose(), this.workerManager.worker.terminate(), this.imageManager.revokeBlobUrls(), this.errorManager.cleanBuffer();
|
|
2939
2741
|
}
|
|
2940
2742
|
/**
|
|
2941
2743
|
* Создает паттерн мозаики.
|
|
2942
|
-
* @returns
|
|
2744
|
+
* @returns паттерн мозаики
|
|
2943
2745
|
*/
|
|
2944
2746
|
static _createMosaicPattern() {
|
|
2945
2747
|
const e = document.createElement("canvas");
|
|
2946
2748
|
e.width = 20, e.height = 20;
|
|
2947
2749
|
const t = e.getContext("2d");
|
|
2948
|
-
return t.fillStyle = "#ddd", t.fillRect(0, 0, 40, 40), t.fillStyle = "#ccc", t.fillRect(0, 0, 10, 10), t.fillRect(10, 10, 10, 10), new
|
|
2750
|
+
return t.fillStyle = "#ddd", t.fillRect(0, 0, 40, 40), t.fillStyle = "#ccc", t.fillRect(0, 0, 10, 10), t.fillRect(10, 10, 10, 10), new Ne({
|
|
2949
2751
|
source: e,
|
|
2950
2752
|
repeat: "repeat"
|
|
2951
2753
|
});
|
|
2952
2754
|
}
|
|
2953
2755
|
}
|
|
2954
|
-
const
|
|
2756
|
+
const dt = {
|
|
2955
2757
|
/**
|
|
2956
2758
|
* Опции редактора
|
|
2957
2759
|
*/
|
|
@@ -3039,18 +2841,18 @@ const ut = {
|
|
|
3039
2841
|
deleteObjectsByHotkey: !0,
|
|
3040
2842
|
resetObjectFitByDoubleClick: !0
|
|
3041
2843
|
};
|
|
3042
|
-
function
|
|
3043
|
-
const t =
|
|
3044
|
-
if (!
|
|
3045
|
-
return Promise.reject(new Error(`Контейнер с ID "${
|
|
3046
|
-
const
|
|
3047
|
-
return
|
|
3048
|
-
t._onReadyCallback =
|
|
3049
|
-
const
|
|
3050
|
-
window[
|
|
2844
|
+
function ft(c, e = {}) {
|
|
2845
|
+
const t = f(f({}, dt), e), s = document.getElementById(c);
|
|
2846
|
+
if (!s)
|
|
2847
|
+
return Promise.reject(new Error(`Контейнер с ID "${c}" не найден.`));
|
|
2848
|
+
const i = document.createElement("canvas");
|
|
2849
|
+
return i.id = `${c}-canvas`, s.appendChild(i), t.editorContainer = s, new Promise((n) => {
|
|
2850
|
+
t._onReadyCallback = n;
|
|
2851
|
+
const a = new ie(i.id, t);
|
|
2852
|
+
window[c] = a;
|
|
3051
2853
|
});
|
|
3052
2854
|
}
|
|
3053
2855
|
export {
|
|
3054
|
-
|
|
2856
|
+
ft as default
|
|
3055
2857
|
};
|
|
3056
2858
|
//# sourceMappingURL=main.js.map
|