@anu3ev/fabric-image-editor 0.1.82 → 0.2.1
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 +1159 -857
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
var Ne = Object.defineProperty, Le = Object.defineProperties;
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var Me = Object.prototype.hasOwnProperty,
|
|
5
|
-
var
|
|
2
|
+
var Te = Object.getOwnPropertyDescriptors;
|
|
3
|
+
var V = Object.getOwnPropertySymbols;
|
|
4
|
+
var Me = Object.prototype.hasOwnProperty, pe = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var me = (d, e, t) => e in d ? Ne(d, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : d[e] = t, I = (d, e) => {
|
|
6
6
|
for (var t in e || (e = {}))
|
|
7
|
-
Me.call(e, t) &&
|
|
8
|
-
if (
|
|
9
|
-
for (var t of
|
|
10
|
-
|
|
11
|
-
return
|
|
12
|
-
}, be = (
|
|
13
|
-
var
|
|
7
|
+
Me.call(e, t) && me(d, t, e[t]);
|
|
8
|
+
if (V)
|
|
9
|
+
for (var t of V(e))
|
|
10
|
+
pe.call(e, t) && me(d, t, e[t]);
|
|
11
|
+
return d;
|
|
12
|
+
}, be = (d, e) => Le(d, Te(e));
|
|
13
|
+
var G = (d, e) => {
|
|
14
14
|
var t = {};
|
|
15
|
-
for (var s in
|
|
16
|
-
Me.call(
|
|
17
|
-
if (
|
|
18
|
-
for (var s of
|
|
19
|
-
e.indexOf(s) < 0 &&
|
|
15
|
+
for (var s in d)
|
|
16
|
+
Me.call(d, s) && e.indexOf(s) < 0 && (t[s] = d[s]);
|
|
17
|
+
if (d != null && V)
|
|
18
|
+
for (var s of V(d))
|
|
19
|
+
e.indexOf(s) < 0 && pe.call(d, s) && (t[s] = d[s]);
|
|
20
20
|
return t;
|
|
21
21
|
};
|
|
22
|
-
var
|
|
23
|
-
var
|
|
22
|
+
var y = (d, e, t) => new Promise((s, n) => {
|
|
23
|
+
var o = (r) => {
|
|
24
24
|
try {
|
|
25
25
|
i(t.next(r));
|
|
26
|
-
} catch (
|
|
27
|
-
|
|
26
|
+
} catch (c) {
|
|
27
|
+
n(c);
|
|
28
28
|
}
|
|
29
|
-
},
|
|
29
|
+
}, a = (r) => {
|
|
30
30
|
try {
|
|
31
31
|
i(t.throw(r));
|
|
32
|
-
} catch (
|
|
33
|
-
|
|
32
|
+
} catch (c) {
|
|
33
|
+
n(c);
|
|
34
34
|
}
|
|
35
|
-
}, i = (r) => r.done ? s(r.value) : Promise.resolve(r.value).then(
|
|
36
|
-
i((t = t.apply(
|
|
35
|
+
}, i = (r) => r.done ? s(r.value) : Promise.resolve(r.value).then(o, a);
|
|
36
|
+
i((t = t.apply(d, e)).next());
|
|
37
37
|
});
|
|
38
|
-
import { ActiveSelection as v, util as
|
|
39
|
-
import { create as
|
|
38
|
+
import { ActiveSelection as v, util as F, controlsUtils as ke, InteractiveFabricObject as je, loadSVGFromURL as _e, FabricImage as z, Point as $, Gradient as ye, Rect as Be, Circle as xe, Triangle as Re, Group as U, Canvas as Ue, Pattern as Ye } from "fabric";
|
|
39
|
+
import { create as Ze } from "jsondiffpatch";
|
|
40
40
|
import He from "diff-match-patch";
|
|
41
|
-
var
|
|
41
|
+
var ze = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", C = function() {
|
|
42
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 +=
|
|
43
|
+
t += ze[s[e] & 63];
|
|
44
44
|
return t;
|
|
45
45
|
};
|
|
46
|
-
class
|
|
46
|
+
class W {
|
|
47
47
|
/**
|
|
48
48
|
* Конструктор принимает редактор и опции.
|
|
49
49
|
* @param params
|
|
@@ -61,7 +61,7 @@ class P {
|
|
|
61
61
|
* @param params.options.adaptCanvasToContainerOnResize — адаптировать канвас к размерам контейнера при изменении размеров окна
|
|
62
62
|
*/
|
|
63
63
|
constructor({ editor: e, options: t = {} }) {
|
|
64
|
-
this.isDragging = !1, this.lastMouseX = 0, this.lastMouseY = 0, this.isUndoRedoKeyPressed = !1, this.isSpacePressed = !1, this.savedSelection = [], 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.savedSelection = [], 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 = W.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 = W.debounce(this.handleObjectModifiedHistory.bind(this), 300), this.handleObjectRotatingHistoryBound = W.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.handleBackgroundUpdateBound = this.handleBackgroundUpdate.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();
|
|
65
65
|
}
|
|
66
66
|
/**
|
|
67
67
|
* Инициализация всех обработчиков согласно опциям.
|
|
@@ -71,15 +71,15 @@ class P {
|
|
|
71
71
|
adaptCanvasToContainerOnResize: e,
|
|
72
72
|
canvasDragging: t,
|
|
73
73
|
mouseWheelZooming: s,
|
|
74
|
-
bringToFrontOnSelection:
|
|
75
|
-
copyObjectsByHotkey:
|
|
76
|
-
pasteImageFromClipboard:
|
|
74
|
+
bringToFrontOnSelection: n,
|
|
75
|
+
copyObjectsByHotkey: o,
|
|
76
|
+
pasteImageFromClipboard: a,
|
|
77
77
|
undoRedoByHotKeys: i,
|
|
78
78
|
selectAllByHotkey: r,
|
|
79
|
-
deleteObjectsByHotkey:
|
|
79
|
+
deleteObjectsByHotkey: c,
|
|
80
80
|
resetObjectFitByDoubleClick: h
|
|
81
81
|
} = this.options;
|
|
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),
|
|
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), n && (this.canvas.on("selection:created", this.handleBringToFrontBound), this.canvas.on("selection:updated", this.handleBringToFrontBound)), h && this.canvas.on("mouse:dblclick", this.handleResetObjectFitBound), e && window.addEventListener("resize", this.handleContainerResizeBound, { capture: !0 }), o && document.addEventListener("keydown", this.handleCopyEventBound, { capture: !0 }), a && document.addEventListener("paste", this.handlePasteEventBound, { capture: !0 }), i && (document.addEventListener("keydown", this.handleUndoRedoEventBound, { capture: !0 }), document.addEventListener("keyup", this.handleUndoRedoKeyUpBound, { capture: !0 })), r && document.addEventListener("keydown", this.handleSelectAllEventBound, { capture: !0 }), c && 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), this.canvas.on("object:added", this.handleBackgroundUpdateBound), this.canvas.on("selection:created", this.handleBackgroundUpdateBound);
|
|
83
83
|
}
|
|
84
84
|
/**
|
|
85
85
|
* При массовом выделении объектов удаляем из него залоченные.
|
|
@@ -89,31 +89,31 @@ class P {
|
|
|
89
89
|
*/
|
|
90
90
|
_filterLockedSelection({ selected: e, e: t }) {
|
|
91
91
|
if (!(e != null && e.length) || !(t instanceof MouseEvent) || e.length === 1) return;
|
|
92
|
-
const { lockedObjects: s, unlockedObjects:
|
|
93
|
-
(
|
|
92
|
+
const { lockedObjects: s, unlockedObjects: n } = e.reduce(
|
|
93
|
+
(a, i) => i.locked ? (a.lockedObjects.push(i), a) : (a.unlockedObjects.push(i), a),
|
|
94
94
|
{ lockedObjects: [], unlockedObjects: [] }
|
|
95
95
|
);
|
|
96
96
|
if (s.length === 0) return;
|
|
97
|
-
if (
|
|
98
|
-
if (
|
|
99
|
-
this.canvas.setActiveObject(
|
|
97
|
+
if (n.length > 0) {
|
|
98
|
+
if (n.length === 1)
|
|
99
|
+
this.canvas.setActiveObject(n[0]);
|
|
100
100
|
else {
|
|
101
|
-
const
|
|
101
|
+
const a = new v(n, {
|
|
102
102
|
canvas: this.canvas
|
|
103
103
|
});
|
|
104
|
-
this.canvas.setActiveObject(
|
|
104
|
+
this.canvas.setActiveObject(a);
|
|
105
105
|
}
|
|
106
106
|
this.canvas.requestRenderAll();
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
-
const
|
|
109
|
+
const o = new v(e, {
|
|
110
110
|
canvas: this.canvas
|
|
111
111
|
});
|
|
112
112
|
this.editor.objectLockManager.lockObject({
|
|
113
|
-
object:
|
|
113
|
+
object: o,
|
|
114
114
|
skipInnerObjects: !0,
|
|
115
115
|
withoutSave: !0
|
|
116
|
-
}), this.canvas.setActiveObject(
|
|
116
|
+
}), this.canvas.setActiveObject(o), this.canvas.requestRenderAll();
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Обработчики для сохранения состояния редактора в истории.
|
|
@@ -157,8 +157,8 @@ class P {
|
|
|
157
157
|
* @param event.code — код клавиши
|
|
158
158
|
*/
|
|
159
159
|
handleCopyEvent(e) {
|
|
160
|
-
const { ctrlKey: t, metaKey: s, code:
|
|
161
|
-
this._shouldIgnoreKeyboardEvent(e) || !t && !s ||
|
|
160
|
+
const { ctrlKey: t, metaKey: s, code: n } = e;
|
|
161
|
+
this._shouldIgnoreKeyboardEvent(e) || !t && !s || n !== "KeyC" || (e.preventDefault(), this.editor.clipboardManager.copy());
|
|
162
162
|
}
|
|
163
163
|
/**
|
|
164
164
|
* Обработчик вставки объекта или изображения из буфера обмена.
|
|
@@ -175,9 +175,9 @@ class P {
|
|
|
175
175
|
* @param event.code — код клавиши
|
|
176
176
|
*/
|
|
177
177
|
handleUndoRedoEvent(e) {
|
|
178
|
-
return
|
|
179
|
-
const { ctrlKey: t, metaKey: s, code:
|
|
180
|
-
this._shouldIgnoreKeyboardEvent(e) || !t && !s ||
|
|
178
|
+
return y(this, null, function* () {
|
|
179
|
+
const { ctrlKey: t, metaKey: s, code: n, repeat: o } = e;
|
|
180
|
+
this._shouldIgnoreKeyboardEvent(e) || !t && !s || o || !/Mac/i.test(navigator.userAgent) && this.isUndoRedoKeyPressed || (n === "KeyZ" ? (e.preventDefault(), this.isUndoRedoKeyPressed = !0, yield this.editor.historyManager.undo()) : n === "KeyY" && (e.preventDefault(), this.isUndoRedoKeyPressed = !0, yield this.editor.historyManager.redo()));
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
183
|
/**
|
|
@@ -197,8 +197,8 @@ class P {
|
|
|
197
197
|
*/
|
|
198
198
|
handleSelectAllEvent(e) {
|
|
199
199
|
if (this._shouldIgnoreKeyboardEvent(e)) return;
|
|
200
|
-
const { ctrlKey: t, metaKey: s, code:
|
|
201
|
-
!t && !s ||
|
|
200
|
+
const { ctrlKey: t, metaKey: s, code: n } = e;
|
|
201
|
+
!t && !s || n !== "KeyA" || (e.preventDefault(), this.editor.selectionManager.selectAll());
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
* Обработчик для удаления объектов (Delete или Backspace).
|
|
@@ -216,11 +216,11 @@ class P {
|
|
|
216
216
|
*/
|
|
217
217
|
handleSpaceKeyDown(e) {
|
|
218
218
|
if (e.code !== "Space" || this._shouldIgnoreKeyboardEvent(e)) return;
|
|
219
|
-
const { canvas: t, editor: s, isSpacePressed:
|
|
220
|
-
if (
|
|
219
|
+
const { canvas: t, editor: s, isSpacePressed: n, isDragging: o } = this;
|
|
220
|
+
if (n || o) return;
|
|
221
221
|
this.isSpacePressed = !0, e.preventDefault();
|
|
222
|
-
const
|
|
223
|
-
|
|
222
|
+
const a = t.getActiveObject() || null;
|
|
223
|
+
a instanceof v ? this.savedSelection = a.getObjects().slice() : a && (this.savedSelection = [a]), t.discardActiveObject(), t.set({
|
|
224
224
|
selection: !1,
|
|
225
225
|
defaultCursor: "grab"
|
|
226
226
|
}), t.setCursor("grab"), s.canvasManager.getObjects().forEach((i) => {
|
|
@@ -259,8 +259,8 @@ class P {
|
|
|
259
259
|
t.setActiveObject(e[0]);
|
|
260
260
|
return;
|
|
261
261
|
}
|
|
262
|
-
const
|
|
263
|
-
t.setActiveObject(
|
|
262
|
+
const n = e.filter((a) => s.canvasManager.getObjects().includes(a)), o = new v(n, { canvas: t });
|
|
263
|
+
t.setActiveObject(o);
|
|
264
264
|
}
|
|
265
265
|
// --- Обработчики для событий canvas (Fabric) ---
|
|
266
266
|
/**
|
|
@@ -273,15 +273,17 @@ class P {
|
|
|
273
273
|
}
|
|
274
274
|
/**
|
|
275
275
|
* Перетаскивание канваса (mouse:move).
|
|
276
|
+
* Проверяет, разрешено ли перетаскивание при текущем зуме и применяет ограничения на панорамирование с помощью panConstraintManager.
|
|
276
277
|
* @param options
|
|
277
278
|
* @param options.e — объект события
|
|
278
|
-
*
|
|
279
|
-
* TODO: Надо как-то ограничить область перетаскивания, чтобы канвас не уходил сильно далеко за пределы экрана
|
|
280
279
|
*/
|
|
281
280
|
handleCanvasDragging({ e }) {
|
|
282
281
|
if (!this.isDragging || !this.isSpacePressed || !(e instanceof MouseEvent)) return;
|
|
283
|
-
const t = this.
|
|
284
|
-
|
|
282
|
+
const { panConstraintManager: t, montageArea: s } = this.editor;
|
|
283
|
+
if (!t.isPanAllowed())
|
|
284
|
+
return;
|
|
285
|
+
const n = this.canvas.viewportTransform, o = n[4] + (e.clientX - this.lastMouseX), a = n[5] + (e.clientY - this.lastMouseY), i = t.constrainPan(o, a);
|
|
286
|
+
n[4] = i.x, n[5] = i.y, s.setCoords(), this.canvas.requestRenderAll(), this.lastMouseX = e.clientX, this.lastMouseY = e.clientY;
|
|
285
287
|
}
|
|
286
288
|
/**
|
|
287
289
|
* Завершение перетаскивания канваса (mouse:up).
|
|
@@ -290,6 +292,18 @@ class P {
|
|
|
290
292
|
handleCanvasDragEnd() {
|
|
291
293
|
this.isDragging && (this.canvas.setViewportTransform(this.canvas.viewportTransform), this.isDragging = !1, this.isSpacePressed && (this.canvas.set("defaultCursor", "grab"), this.canvas.setCursor("grab")));
|
|
292
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Рассчитывает шаг зума на основе текущего масштаба канваса.
|
|
297
|
+
* Логика: один скролл изменяет зум на фиксированный процент от текущего значения.
|
|
298
|
+
*
|
|
299
|
+
* @param currentZoom - Текущий уровень зума канваса
|
|
300
|
+
* @param deltaY - Значение deltaY из WheelEvent
|
|
301
|
+
* @returns Шаг изменения зума
|
|
302
|
+
*/
|
|
303
|
+
_calculateAdaptiveZoomStep(e) {
|
|
304
|
+
const t = this.canvas.getZoom(), s = 0.05, o = e / 100;
|
|
305
|
+
return -(t * s * o);
|
|
306
|
+
}
|
|
293
307
|
/**
|
|
294
308
|
* Обработчик зума колесиком мыши. Работает при зажатом Ctrl или Cmd.
|
|
295
309
|
* @param options
|
|
@@ -297,8 +311,8 @@ class P {
|
|
|
297
311
|
*/
|
|
298
312
|
handleMouseWheelZoom({ e }) {
|
|
299
313
|
if (!e.ctrlKey && !e.metaKey) return;
|
|
300
|
-
const
|
|
301
|
-
this.editor.
|
|
314
|
+
const t = this._calculateAdaptiveZoomStep(e.deltaY);
|
|
315
|
+
this.editor.zoomManager.handleMouseWheelZoom(t, e), e.preventDefault(), e.stopPropagation();
|
|
302
316
|
}
|
|
303
317
|
/**
|
|
304
318
|
* Обработчик, поднимающий выделенные объекты на передний план.
|
|
@@ -325,22 +339,22 @@ class P {
|
|
|
325
339
|
* @returns true если событие должно быть проигнорировано
|
|
326
340
|
*/
|
|
327
341
|
_shouldIgnoreKeyboardEvent(e) {
|
|
328
|
-
const t = document.activeElement, s = e.target,
|
|
342
|
+
const t = document.activeElement, s = e.target, n = ["input", "textarea", "select"];
|
|
329
343
|
if (s) {
|
|
330
|
-
const
|
|
331
|
-
if (
|
|
344
|
+
const a = s.tagName.toLowerCase();
|
|
345
|
+
if (n.includes(a) || s.contentEditable === "true") return !0;
|
|
332
346
|
}
|
|
333
347
|
if (t && t !== s) {
|
|
334
|
-
const
|
|
335
|
-
if (
|
|
348
|
+
const a = t.tagName.toLowerCase();
|
|
349
|
+
if (n.includes(a) || t.contentEditable === "true") return !0;
|
|
336
350
|
}
|
|
337
|
-
const
|
|
338
|
-
if (
|
|
339
|
-
let r =
|
|
351
|
+
const o = window.getSelection();
|
|
352
|
+
if (o && !o.isCollapsed && o.rangeCount > 0) {
|
|
353
|
+
let r = o.getRangeAt(0).commonAncestorContainer;
|
|
340
354
|
r.nodeType === Node.TEXT_NODE && (r = r.parentElement);
|
|
341
|
-
const { keyboardIgnoreSelectors:
|
|
342
|
-
if (
|
|
343
|
-
for (const h of
|
|
355
|
+
const { keyboardIgnoreSelectors: c } = this.options;
|
|
356
|
+
if (c != null && c.length && r)
|
|
357
|
+
for (const h of c)
|
|
344
358
|
try {
|
|
345
359
|
const l = r;
|
|
346
360
|
if (l.matches && l.matches(h) || l.closest && l.closest(h))
|
|
@@ -365,14 +379,14 @@ class P {
|
|
|
365
379
|
*/
|
|
366
380
|
static debounce(e, t) {
|
|
367
381
|
let s = null;
|
|
368
|
-
return function(...
|
|
382
|
+
return function(...n) {
|
|
369
383
|
s !== null && clearTimeout(s), s = setTimeout(() => {
|
|
370
|
-
e.apply(this,
|
|
384
|
+
e.apply(this, n);
|
|
371
385
|
}, t);
|
|
372
386
|
};
|
|
373
387
|
}
|
|
374
388
|
}
|
|
375
|
-
class
|
|
389
|
+
class Pe {
|
|
376
390
|
/**
|
|
377
391
|
* Класс для динамической загрузки внешних модулей.
|
|
378
392
|
*/
|
|
@@ -390,21 +404,21 @@ class Ye {
|
|
|
390
404
|
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}"`));
|
|
391
405
|
}
|
|
392
406
|
}
|
|
393
|
-
function
|
|
407
|
+
function We(d) {
|
|
394
408
|
return new Worker(
|
|
395
409
|
"" + new URL("assets/worker-CN39s7P7.js", import.meta.url).href,
|
|
396
410
|
{
|
|
397
|
-
name:
|
|
411
|
+
name: d == null ? void 0 : d.name
|
|
398
412
|
}
|
|
399
413
|
);
|
|
400
414
|
}
|
|
401
|
-
class
|
|
415
|
+
class Fe {
|
|
402
416
|
/**
|
|
403
417
|
* @param scriptUrl — URL скрипта воркера.
|
|
404
418
|
* По-умолчанию использует DefaultWorker из соседнего файла
|
|
405
419
|
*/
|
|
406
420
|
constructor(e) {
|
|
407
|
-
e ? this.worker = new Worker(e, { type: "module" }) : this.worker = new
|
|
421
|
+
e ? this.worker = new Worker(e, { type: "module" }) : this.worker = new We(), this._callbacks = /* @__PURE__ */ new Map(), this.worker.onmessage = this._handleMessage.bind(this);
|
|
408
422
|
}
|
|
409
423
|
/**
|
|
410
424
|
* Обработчик сообщений от воркера
|
|
@@ -417,12 +431,12 @@ class We {
|
|
|
417
431
|
* @returns
|
|
418
432
|
*/
|
|
419
433
|
_handleMessage({ data: e }) {
|
|
420
|
-
const { requestId: t, success: s, data:
|
|
421
|
-
if (!
|
|
434
|
+
const { requestId: t, success: s, data: n, error: o } = e, a = this._callbacks.get(t);
|
|
435
|
+
if (!a) {
|
|
422
436
|
console.warn(`No callback found for requestId: ${t}`);
|
|
423
437
|
return;
|
|
424
438
|
}
|
|
425
|
-
s ?
|
|
439
|
+
s ? a.resolve(n) : a.reject(new Error(o)), this._callbacks.delete(t);
|
|
426
440
|
}
|
|
427
441
|
/**
|
|
428
442
|
* Универсальный метод отправки команды в воркер
|
|
@@ -432,9 +446,9 @@ class We {
|
|
|
432
446
|
* @returns Promise, который будет выполнен, когда воркер вернет ответ
|
|
433
447
|
*/
|
|
434
448
|
post(e, t, s = []) {
|
|
435
|
-
const
|
|
436
|
-
return new Promise((
|
|
437
|
-
this._callbacks.set(
|
|
449
|
+
const n = `${e}:${C(8)}`;
|
|
450
|
+
return new Promise((o, a) => {
|
|
451
|
+
this._callbacks.set(n, { resolve: o, reject: a }), this.worker.postMessage({ action: e, payload: t, requestId: n }, s);
|
|
438
452
|
});
|
|
439
453
|
}
|
|
440
454
|
/**
|
|
@@ -444,112 +458,112 @@ class We {
|
|
|
444
458
|
this.worker.terminate();
|
|
445
459
|
}
|
|
446
460
|
}
|
|
447
|
-
const
|
|
448
|
-
function
|
|
449
|
-
const
|
|
450
|
-
|
|
461
|
+
const k = 12, Ve = 2, ne = 8, oe = 20, Ge = 100, ae = 20, ie = 8, Xe = 100, Q = 32, re = 1, $e = "#2B2D33", ce = "#3D8BF4", de = "#FFFFFF";
|
|
462
|
+
function X(d, e, t, s, n) {
|
|
463
|
+
const o = k, a = Ve;
|
|
464
|
+
d.save(), d.translate(e, t), d.rotate(F.degreesToRadians(n.angle)), d.fillStyle = de, d.strokeStyle = ce, d.lineWidth = re, d.beginPath(), d.roundRect(-o / 2, -o / 2, o, o, a), d.fill(), d.stroke(), d.restore();
|
|
451
465
|
}
|
|
452
|
-
function
|
|
453
|
-
const
|
|
454
|
-
|
|
466
|
+
function ve(d, e, t, s, n) {
|
|
467
|
+
const o = ne, a = oe, i = Ge;
|
|
468
|
+
d.save(), d.translate(e, t), d.rotate(F.degreesToRadians(n.angle)), d.fillStyle = de, d.strokeStyle = ce, d.lineWidth = re, d.beginPath(), d.roundRect(-o / 2, -a / 2, o, a, i), d.fill(), d.stroke(), d.restore();
|
|
455
469
|
}
|
|
456
|
-
function Ie(
|
|
457
|
-
const
|
|
458
|
-
|
|
470
|
+
function Ie(d, e, t, s, n) {
|
|
471
|
+
const o = ae, a = ie, i = Xe;
|
|
472
|
+
d.save(), d.translate(e, t), d.rotate(F.degreesToRadians(n.angle)), d.fillStyle = de, d.strokeStyle = ce, d.lineWidth = re, d.beginPath(), d.roundRect(-o / 2, -a / 2, o, a, i), d.fill(), d.stroke(), d.restore();
|
|
459
473
|
}
|
|
460
|
-
const Qe = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE4Ljc1IDQuMzc1djMuNzVhLjYyNS42MjUgMCAwIDEtLjYyNS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDEgMC0xLjI1aDIuMTRsLTIuMDc3LTEuOTAzLS4wMi0uMDE5YTYuMjUgNi4yNSAwIDEgMC0uMTMgOC45NjcuNjI2LjYyNiAwIDAgMSAuODYuOTA5QTcuNDU2IDcuNDU2IDAgMCAxIDEwIDE3LjVoLS4xMDNhNy41IDcuNSAwIDEgMSA1LjM5Ni0xMi44MTJMMTcuNSA2LjcwM1Y0LjM3NWEuNjI1LjYyNSAwIDAgMSAxLjI1IDBaIi8+PC9zdmc+",
|
|
461
|
-
|
|
462
|
-
function
|
|
463
|
-
const
|
|
464
|
-
|
|
474
|
+
const Qe = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE4Ljc1IDQuMzc1djMuNzVhLjYyNS42MjUgMCAwIDEtLjYyNS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDEgMC0xLjI1aDIuMTRsLTIuMDc3LTEuOTAzLS4wMi0uMDE5YTYuMjUgNi4yNSAwIDEgMC0uMTMgOC45NjcuNjI2LjYyNiAwIDAgMSAuODYuOTA5QTcuNDU2IDcuNDU2IDAgMCAxIDEwIDE3LjVoLS4xMDNhNy41IDcuNSAwIDEgMSA1LjM5Ni0xMi44MTJMMTcuNSA2LjcwM1Y0LjM3NWEuNjI1LjYyNSAwIDAgMSAxLjI1IDBaIi8+PC9zdmc+", Oe = new Image();
|
|
475
|
+
Oe.src = Qe;
|
|
476
|
+
function Ke(d, e, t, s, n) {
|
|
477
|
+
const a = Q / 2;
|
|
478
|
+
d.save(), d.translate(e, t), d.rotate(F.degreesToRadians(n.angle)), d.fillStyle = $e, d.beginPath(), d.arc(0, 0, a, 0, 2 * Math.PI), d.fill(), d.drawImage(Oe, -a / 2, -a / 2, a, a), d.restore();
|
|
465
479
|
}
|
|
466
|
-
const
|
|
480
|
+
const Je = {
|
|
467
481
|
// Угловые точки
|
|
468
482
|
tl: {
|
|
469
|
-
render:
|
|
470
|
-
sizeX:
|
|
471
|
-
sizeY:
|
|
483
|
+
render: X,
|
|
484
|
+
sizeX: k,
|
|
485
|
+
sizeY: k,
|
|
472
486
|
offsetX: 0,
|
|
473
487
|
offsetY: 0
|
|
474
488
|
},
|
|
475
489
|
tr: {
|
|
476
|
-
render:
|
|
477
|
-
sizeX:
|
|
478
|
-
sizeY:
|
|
490
|
+
render: X,
|
|
491
|
+
sizeX: k,
|
|
492
|
+
sizeY: k,
|
|
479
493
|
offsetX: 0,
|
|
480
494
|
offsetY: 0
|
|
481
495
|
},
|
|
482
496
|
bl: {
|
|
483
|
-
render:
|
|
484
|
-
sizeX:
|
|
485
|
-
sizeY:
|
|
497
|
+
render: X,
|
|
498
|
+
sizeX: k,
|
|
499
|
+
sizeY: k,
|
|
486
500
|
offsetX: 0,
|
|
487
501
|
offsetY: 0
|
|
488
502
|
},
|
|
489
503
|
br: {
|
|
490
|
-
render:
|
|
491
|
-
sizeX:
|
|
492
|
-
sizeY:
|
|
504
|
+
render: X,
|
|
505
|
+
sizeX: k,
|
|
506
|
+
sizeY: k,
|
|
493
507
|
offsetX: 0,
|
|
494
508
|
offsetY: 0
|
|
495
509
|
},
|
|
496
510
|
// Середина вертикалей
|
|
497
511
|
ml: {
|
|
498
|
-
render:
|
|
499
|
-
sizeX:
|
|
500
|
-
sizeY:
|
|
512
|
+
render: ve,
|
|
513
|
+
sizeX: ne,
|
|
514
|
+
sizeY: oe,
|
|
501
515
|
offsetX: 0,
|
|
502
516
|
offsetY: 0
|
|
503
517
|
},
|
|
504
518
|
mr: {
|
|
505
|
-
render:
|
|
506
|
-
sizeX:
|
|
507
|
-
sizeY:
|
|
519
|
+
render: ve,
|
|
520
|
+
sizeX: ne,
|
|
521
|
+
sizeY: oe,
|
|
508
522
|
offsetX: 0,
|
|
509
523
|
offsetY: 0
|
|
510
524
|
},
|
|
511
525
|
// Середина горизонталей
|
|
512
526
|
mt: {
|
|
513
527
|
render: Ie,
|
|
514
|
-
sizeX:
|
|
515
|
-
sizeY:
|
|
528
|
+
sizeX: ae,
|
|
529
|
+
sizeY: ie,
|
|
516
530
|
offsetX: 0,
|
|
517
531
|
offsetY: 0
|
|
518
532
|
},
|
|
519
533
|
mb: {
|
|
520
534
|
render: Ie,
|
|
521
|
-
sizeX:
|
|
522
|
-
sizeY:
|
|
535
|
+
sizeX: ae,
|
|
536
|
+
sizeY: ie,
|
|
523
537
|
offsetX: 0,
|
|
524
538
|
offsetY: 0
|
|
525
539
|
},
|
|
526
540
|
// Специальный «rotate» контрол
|
|
527
541
|
mtr: {
|
|
528
|
-
render:
|
|
542
|
+
render: Ke,
|
|
529
543
|
sizeX: Q,
|
|
530
544
|
sizeY: Q,
|
|
531
545
|
offsetX: 0,
|
|
532
546
|
offsetY: -Q
|
|
533
547
|
}
|
|
534
548
|
};
|
|
535
|
-
class
|
|
549
|
+
class qe {
|
|
536
550
|
static apply() {
|
|
537
|
-
const e =
|
|
538
|
-
Object.entries(
|
|
551
|
+
const e = ke.createObjectDefaultControls();
|
|
552
|
+
Object.entries(Je).forEach(([t, s]) => {
|
|
539
553
|
Object.assign(e[t], {
|
|
540
554
|
render: s.render,
|
|
541
555
|
sizeX: s.sizeX,
|
|
542
556
|
sizeY: s.sizeY,
|
|
543
557
|
offsetX: s.offsetX,
|
|
544
558
|
offsetY: s.offsetY
|
|
545
|
-
}), t === "mtr" && (e[t].cursorStyle = "grab", e[t].mouseDownHandler = (
|
|
559
|
+
}), t === "mtr" && (e[t].cursorStyle = "grab", e[t].mouseDownHandler = (o, a, i, r) => {
|
|
546
560
|
var h;
|
|
547
|
-
(h =
|
|
561
|
+
(h = a.target.canvas) == null || h.setCursor("grabbing");
|
|
548
562
|
});
|
|
549
563
|
}), je.ownDefaults.controls = e, je.ownDefaults.snapAngle = 1;
|
|
550
564
|
}
|
|
551
565
|
}
|
|
552
|
-
const
|
|
566
|
+
const et = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNi44NzUgMi41YS42MjUuNjI1IDAgMCAwLS42MjUuNjI0VjYuMjVIMy4xMjVhLjYyNS42MjUgMCAwIDAtLjYyNS42MjV2MTBjMCAuMzQ1LjI4LjYyNS42MjUuNjI1aDEwYy4zNDUgMCAuNjI1LS4yOC42MjUtLjYyNXYtMy4xMjZoMy4xMjVjLjM0NSAwIC42MjUtLjI4LjYyNS0uNjI1di0xMGEuNjI1LjYyNSAwIDAgMC0uNjI1LS42MjVoLTEwWm02Ljg3NSAxMGgyLjVWMy43NUg3LjV2Mi41aDUuNjI1Yy4zNDUgMCAuNjI1LjI4LjYyNS42MjV2NS42MjRabS0xMCAzLjc1VjcuNWg4Ljc1djguNzVIMy43NVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", tt = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDcuNWMwLS42OS41Ni0xLjI1IDEuMjUtMS4yNWgxMi41Yy42OSAwIDEuMjUuNTYgMS4yNSAxLjI1djguNzVjMCAuNjktLjU2IDEuMjUtMS4yNSAxLjI1SDMuNzVjLS42OSAwLTEuMjUtLjU2LTEuMjUtMS4yNVY3LjVabTEzLjc1IDBIMy43NXY4Ljc1aDEyLjVWNy41WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMTAgMS44NzVhMi4xODggMi4xODggMCAwIDAtMi4xODggMi4xODh2Mi44MTJhLjYyNS42MjUgMCAxIDEtMS4yNSAwVjQuMDYyYTMuNDM3IDMuNDM3IDAgMSAxIDYuODc1IDB2Mi44MTNhLjYyNS42MjUgMCAxIDEtMS4yNSAwVjQuMDYyQTIuMTg4IDIuMTg4IDAgMCAwIDEwIDEuODc2WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTEwIDEyLjgxM2EuOTM3LjkzNyAwIDEgMCAwLTEuODc1LjkzNy45MzcgMCAwIDAgMCAxLjg3NFoiLz48L3N2Zz4=", st = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE2LjI1IDYuMjVINy41VjQuMzc1YTIuNSAyLjUgMCAwIDEgMi41LTIuNWMxLjIgMCAyLjI4MS44NiAyLjUxMiAyYS42MjUuNjI1IDAgMCAwIDEuMjI2LS4yNWMtLjM1NC0xLjczOC0xLjkyNS0zLTMuNzM4LTNhMy43NTQgMy43NTQgMCAwIDAtMy43NSAzLjc1VjYuMjVoLTIuNUExLjI1IDEuMjUgMCAwIDAgMi41IDcuNXY4Ljc1YTEuMjUgMS4yNSAwIDAgMCAxLjI1IDEuMjVoMTIuNWExLjI1IDEuMjUgMCAwIDAgMS4yNS0xLjI1VjcuNWExLjI1IDEuMjUgMCAwIDAtMS4yNS0xLjI1Wm0wIDEwSDMuNzVWNy41aDEyLjV2OC43NVptLTUuMzEzLTQuMzc1YS45MzcuOTM3IDAgMSAxLTEuODc0IDAgLjkzNy45MzcgMCAwIDEgMS44NzQgMFoiLz48L3N2Zz4K", nt = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTIuNSA4LjEyNSAxMCAxMi41bDcuNS00LjM3NUwxMCAzLjc1IDIuNSA4LjEyNVoiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik05LjY4NSAzLjIxYS42MjUuNjI1IDAgMCAxIC42MyAwbDcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOGw3LjUtNC4zNzVaTTMuNzQgOC4xMjUgMTAgMTEuNzc2bDYuMjYtMy42NTFMMTAgNC40NzQgMy43NCA4LjEyNVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTUuNCA5LjQ2YS42MjUuNjI1IDAgMCAxIC42MyAwTDEwIDExLjc3NmwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCA5LjQ2Wm0tMS42NiAyLjQxNUwxMCAxNS41MjZsNi4yNi0zLjY1MS0xLjk3NC0xLjE1MS0zLjk3MSAyLjMxNmEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtMy45Ny0yLjMxNi0xLjk3NSAxLjE1MVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", ot = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOS42ODUgMy4yMWEuNjI1LjYyNSAwIDAgMSAuNjMgMGw3LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhsNy41LTQuMzc1Wk0zLjc0IDguMTI1IDEwIDExLjc3Nmw2LjI2LTMuNjUxTDEwIDQuNDc0IDMuNzQgOC4xMjVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjcxNCAxMCAxMCAxMi41bDQuMjg2LTIuNSAzLjIxNCAxLjg3NUwxMCAxNi4yNWwtNy41LTQuMzc1TDUuNzE0IDEwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS40IDkuNDZhLjYyNS42MjUgMCAwIDEgLjYzIDBMMTAgMTEuNzc2bDMuOTctMi4zMTZhLjYyNS42MjUgMCAwIDEgLjYzIDBsMy4yMTUgMS44NzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhMNS40IDkuNDZabS0xLjY2IDIuNDE1TDEwIDE1LjUyNmw2LjI2LTMuNjUxLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2LTEuOTc1IDEuMTUxWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+", at = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0ibTIuNSA2LjI1IDcuNSA0LjM3NSA3LjUtNC4zNzVMMTAgMS44NzUgMi41IDYuMjVaIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOS42ODUgMS4zMzVhLjYyNS42MjUgMCAwIDEgLjYzIDBsNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4bDcuNS00LjM3NVpNMy43NCA2LjI1IDEwIDkuOTAxbDYuMjYtMy42NTFMMTAgMi41OTkgMy43NCA2LjI1WiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNNS40IDExLjMzNWEuNjI1LjYyNSAwIDAgMSAuNjMgMEwxMCAxMy42NTFsMy45Ny0yLjMxNmEuNjI1LjYyNSAwIDAgMSAuNjMgMGwzLjIxNSAxLjg3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOEw1LjQgMTEuMzM1Wk0zLjc0IDEzLjc1IDEwIDE3LjQwMWw2LjI2LTMuNjUxLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2TDMuNzQgMTMuNzVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjQgNy41ODVhLjYyNS42MjUgMCAwIDEgLjYzIDBMMTAgOS45MDFsMy45Ny0yLjMxNmEuNjI1LjYyNSAwIDAgMSAuNjMgMGwzLjIxNSAxLjg3NWEuNjI1LjYyNSAwIDAgMSAwIDEuMDhsLTcuNSA0LjM3NWEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtNy41LTQuMzc1YS42MjUuNjI1IDAgMCAxIDAtMS4wOEw1LjQgNy41ODVaTTMuNzQgMTAgMTAgMTMuNjUxIDE2LjI2IDEwbC0xLjk3NC0xLjE1MS0zLjk3MSAyLjMxNmEuNjI1LjYyNSAwIDAgMS0uNjMgMGwtMy45Ny0yLjMxNkwzLjc0IDEwWiIgY2xpcC1ydWxlPSJldmVub2RkIi8+PC9zdmc+", it = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMS45NiAxMy40MzVhLjYyNS42MjUgMCAwIDEgLjg1NS0uMjI1TDEwIDE3LjQwMWw3LjE4NS00LjE5YS42MjUuNjI1IDAgMCAxIC42MyAxLjA3OWwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEtLjIyNS0uODU1Wk05LjY4NSAxLjMzNWEuNjI1LjYyNSAwIDAgMSAuNjMgMGw3LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEgMCAxLjA4bC03LjUgNC4zNzVhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTcuNS00LjM3NWEuNjI1LjYyNSAwIDAgMSAwLTEuMDhsNy41LTQuMzc1Wk0zLjc0IDYuMjUgMTAgOS45MDFsNi4yNi0zLjY1MUwxMCAyLjU5OSAzLjc0IDYuMjVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Im01LjcxNCAxMS44NzUgNC4yODYgMi41IDQuMjg2LTIuNUwxNy41IDEzLjc1IDEwIDE4LjEyNSAyLjUgMTMuNzVsMy4yMTQtMS44NzVaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48cGF0aCBmaWxsPSIjZmZmIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik01LjQgMTEuMzM1YS42MjUuNjI1IDAgMCAxIC42MyAwTDEwIDEzLjY1MWwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCAxMS4zMzVaTTMuNzQgMTMuNzUgMTAgMTcuNDAxbDYuMjYtMy42NTEtMS45NzQtMS4xNTEtMy45NzEgMi4zMTZhLjYyNS42MjUgMCAwIDEtLjYzIDBsLTMuOTctMi4zMTZMMy43NCAxMy43NVoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjxwYXRoIGZpbGw9IiNmZmYiIGZpbGwtcnVsZT0iZXZlbm9kZCIgZD0iTTUuNCA3LjU4NWEuNjI1LjYyNSAwIDAgMSAuNjMgMEwxMCA5LjkwMWwzLjk3LTIuMzE2YS42MjUuNjI1IDAgMCAxIC42MyAwbDMuMjE1IDEuODc1YS42MjUuNjI1IDAgMCAxIDAgMS4wOGwtNy41IDQuMzc1YS42MjUuNjI1IDAgMCAxLS42MyAwbC03LjUtNC4zNzVhLjYyNS42MjUgMCAwIDEgMC0xLjA4TDUuNCA3LjU4NVpNMy43NCAxMCAxMCAxMy42NTEgMTYuMjYgMTBsLTEuOTc0LTEuMTUxLTMuOTcxIDIuMzE2YS42MjUuNjI1IDAgMCAxLS42MyAwbC0zLjk3LTIuMzE2TDMuNzQgMTBaIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiLz48L3N2Zz4=", rt = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI0VDNEU0MCIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNOC4xMjUgMS4yNUExLjg3NSAxLjg3NSAwIDAgMCA2LjI1IDMuMTI1di42MjVIMy4xMjVhLjYyNS42MjUgMCAwIDAgMCAxLjI1aC42MjV2MTEuMjVBMS4yNSAxLjI1IDAgMCAwIDUgMTcuNWgxMGExLjI1IDEuMjUgMCAwIDAgMS4yNS0xLjI1VjVoLjYyNWEuNjI1LjYyNSAwIDAgMCAwLTEuMjVIMTMuNzV2LS42MjVhMS44NzUgMS44NzUgMCAwIDAtMS44NzUtMS44NzVoLTMuNzVabTQuMzc1IDIuNXYtLjYyNWEuNjI1LjYyNSAwIDAgMC0uNjI1LS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDAtLjYyNS42MjV2LjYyNWg1Wk01IDE2LjI1VjVoMTB2MTEuMjVINVpNOC4xMjUgNy41Yy4zNDUgMCAuNjI1LjI4LjYyNS42MjV2NWEuNjI1LjYyNSAwIDEgMS0xLjI1IDB2LTVjMC0uMzQ1LjI4LS42MjUuNjI1LS42MjVabTQuMzc1IDUuNjI1di01YS42MjUuNjI1IDAgMCAwLTEuMjUgMHY1YS42MjUuNjI1IDAgMSAwIDEuMjUgMFoiIGNsaXAtcnVsZT0iZXZlbm9kZCIvPjwvc3ZnPg==", P = {
|
|
553
567
|
style: {
|
|
554
568
|
position: "absolute",
|
|
555
569
|
display: "none",
|
|
@@ -616,54 +630,54 @@ const qe = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMj
|
|
|
616
630
|
],
|
|
617
631
|
offsetTop: 50,
|
|
618
632
|
icons: {
|
|
619
|
-
copyPaste:
|
|
620
|
-
delete:
|
|
621
|
-
lock:
|
|
622
|
-
unlock:
|
|
623
|
-
bringToFront:
|
|
624
|
-
sendToBack:
|
|
625
|
-
bringForward:
|
|
626
|
-
sendBackwards:
|
|
633
|
+
copyPaste: et,
|
|
634
|
+
delete: rt,
|
|
635
|
+
lock: tt,
|
|
636
|
+
unlock: st,
|
|
637
|
+
bringToFront: at,
|
|
638
|
+
sendToBack: it,
|
|
639
|
+
bringForward: nt,
|
|
640
|
+
sendBackwards: ot
|
|
627
641
|
},
|
|
628
642
|
handlers: {
|
|
629
|
-
copyPaste: (
|
|
630
|
-
|
|
643
|
+
copyPaste: (d) => y(null, null, function* () {
|
|
644
|
+
d.clipboardManager.copyPaste();
|
|
631
645
|
}),
|
|
632
|
-
delete: (
|
|
633
|
-
|
|
646
|
+
delete: (d) => {
|
|
647
|
+
d.deletionManager.deleteSelectedObjects();
|
|
634
648
|
},
|
|
635
|
-
lock: (
|
|
636
|
-
|
|
649
|
+
lock: (d) => {
|
|
650
|
+
d.objectLockManager.lockObject();
|
|
637
651
|
},
|
|
638
|
-
unlock: (
|
|
639
|
-
|
|
652
|
+
unlock: (d) => {
|
|
653
|
+
d.objectLockManager.unlockObject();
|
|
640
654
|
},
|
|
641
|
-
bringForward: (
|
|
642
|
-
|
|
655
|
+
bringForward: (d) => {
|
|
656
|
+
d.layerManager.bringForward();
|
|
643
657
|
},
|
|
644
|
-
bringToFront: (
|
|
645
|
-
|
|
658
|
+
bringToFront: (d) => {
|
|
659
|
+
d.layerManager.bringToFront();
|
|
646
660
|
},
|
|
647
|
-
sendToBack: (
|
|
648
|
-
|
|
661
|
+
sendToBack: (d) => {
|
|
662
|
+
d.layerManager.sendToBack();
|
|
649
663
|
},
|
|
650
|
-
sendBackwards: (
|
|
651
|
-
|
|
664
|
+
sendBackwards: (d) => {
|
|
665
|
+
d.layerManager.sendBackwards();
|
|
652
666
|
}
|
|
653
667
|
}
|
|
654
668
|
};
|
|
655
|
-
class
|
|
669
|
+
class ct {
|
|
656
670
|
constructor({ editor: e }) {
|
|
657
671
|
this.currentTarget = null, this.currentLocked = !1, this.isTransforming = !1, this.editor = e, this.canvas = e.canvas, this.options = e.options, this._initToolbar();
|
|
658
672
|
}
|
|
659
673
|
_initToolbar() {
|
|
660
674
|
if (!this.options.showToolbar) return;
|
|
661
675
|
const e = this.options.toolbar || {};
|
|
662
|
-
this.config = be(I(I({},
|
|
663
|
-
style: I(I({},
|
|
664
|
-
btnStyle: I(I({},
|
|
665
|
-
icons: I(I({},
|
|
666
|
-
handlers: I(I({},
|
|
676
|
+
this.config = be(I(I({}, P), e), {
|
|
677
|
+
style: I(I({}, P.style), e.style || {}),
|
|
678
|
+
btnStyle: I(I({}, P.btnStyle), e.btnStyle || {}),
|
|
679
|
+
icons: I(I({}, P.icons), e.icons || {}),
|
|
680
|
+
handlers: I(I({}, P.handlers), e.handlers || {})
|
|
667
681
|
}), 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 = () => {
|
|
668
682
|
this.el.style.display = "none";
|
|
669
683
|
}, this._createDOM(), this._bindEvents();
|
|
@@ -674,11 +688,11 @@ class rt {
|
|
|
674
688
|
_createDOM() {
|
|
675
689
|
const { style: e } = this.config;
|
|
676
690
|
this.el = document.createElement("div"), Object.assign(this.el.style, e), this.canvas.wrapperEl.appendChild(this.el), this._onBtnOver = (t) => {
|
|
677
|
-
const
|
|
678
|
-
|
|
691
|
+
const n = t.target.closest("button");
|
|
692
|
+
n && Object.assign(n.style, this.config.btnHover);
|
|
679
693
|
}, this._onBtnOut = (t) => {
|
|
680
|
-
const
|
|
681
|
-
|
|
694
|
+
const n = t.target.closest("button");
|
|
695
|
+
n && Object.assign(n.style, this.config.btnStyle);
|
|
682
696
|
}, this.el.addEventListener("mouseover", this._onBtnOver), this.el.addEventListener("mouseout", this._onBtnOut);
|
|
683
697
|
}
|
|
684
698
|
/**
|
|
@@ -690,13 +704,13 @@ class rt {
|
|
|
690
704
|
_renderButtons(e) {
|
|
691
705
|
this.el.innerHTML = "";
|
|
692
706
|
for (const t of e) {
|
|
693
|
-
const { name: s, handle:
|
|
694
|
-
r.innerHTML = n
|
|
695
|
-
var
|
|
696
|
-
return (
|
|
697
|
-
}, r.onmousedown = (
|
|
698
|
-
|
|
699
|
-
}, r.ondragstart = (
|
|
707
|
+
const { name: s, handle: n } = t, { icons: o = {}, btnStyle: a, handlers: i = {} } = this.config, r = document.createElement("button");
|
|
708
|
+
r.innerHTML = o[n] ? `<img src="${o[n]}" title="${s}" />` : s, Object.assign(r.style, a), r.onclick = () => {
|
|
709
|
+
var c;
|
|
710
|
+
return (c = i[n]) == null ? void 0 : c.call(i, this.editor);
|
|
711
|
+
}, r.onmousedown = (c) => {
|
|
712
|
+
c.stopPropagation(), c.preventDefault();
|
|
713
|
+
}, r.ondragstart = (c) => c.preventDefault(), this.el.appendChild(r);
|
|
700
714
|
}
|
|
701
715
|
}
|
|
702
716
|
/**
|
|
@@ -752,12 +766,12 @@ class rt {
|
|
|
752
766
|
this.el.style.display = "none";
|
|
753
767
|
return;
|
|
754
768
|
}
|
|
755
|
-
const { el: t, config: s, canvas:
|
|
769
|
+
const { el: t, config: s, canvas: n } = this;
|
|
756
770
|
e.setCoords();
|
|
757
|
-
const
|
|
771
|
+
const o = n.getZoom(), [, , , , a, i] = n.viewportTransform, { x: r } = e.getCenterPoint(), { top: c, height: h } = e.getBoundingRect(), g = r * o + a - t.offsetWidth / 2, u = s.offsetTop || 0, f = (c + h) * o + i + u;
|
|
758
772
|
Object.assign(t.style, {
|
|
759
|
-
left: `${
|
|
760
|
-
top: `${
|
|
773
|
+
left: `${g}px`,
|
|
774
|
+
top: `${f}px`,
|
|
761
775
|
display: "flex"
|
|
762
776
|
});
|
|
763
777
|
}
|
|
@@ -768,7 +782,7 @@ class rt {
|
|
|
768
782
|
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();
|
|
769
783
|
}
|
|
770
784
|
}
|
|
771
|
-
const
|
|
785
|
+
const dt = {
|
|
772
786
|
position: "absolute",
|
|
773
787
|
display: "none",
|
|
774
788
|
background: "#2B2D33",
|
|
@@ -782,8 +796,8 @@ const ct = {
|
|
|
782
796
|
"pointer-events": "none",
|
|
783
797
|
"white-space": "nowrap",
|
|
784
798
|
"box-shadow": "0 2px 8px rgba(0, 0, 0, 0.2)"
|
|
785
|
-
},
|
|
786
|
-
class
|
|
799
|
+
}, Ae = 16, Ce = 16, lt = "fabric-editor-angle-indicator";
|
|
800
|
+
class le {
|
|
787
801
|
constructor({ editor: e }) {
|
|
788
802
|
this.isActive = !1, this.currentAngle = 0, this.editor = e, this.canvas = e.canvas, this.options = e.options, this._createDOM(), this._bindEvents();
|
|
789
803
|
}
|
|
@@ -791,7 +805,7 @@ class de {
|
|
|
791
805
|
* Создание DOM-элемента индикатора
|
|
792
806
|
*/
|
|
793
807
|
_createDOM() {
|
|
794
|
-
this.el = document.createElement("div"), this.el.className =
|
|
808
|
+
this.el = document.createElement("div"), this.el.className = lt, Object.entries(dt).forEach(([e, t]) => {
|
|
795
809
|
this.el.style.setProperty(e, t);
|
|
796
810
|
}), this.canvas.wrapperEl.appendChild(this.el);
|
|
797
811
|
}
|
|
@@ -811,7 +825,7 @@ class de {
|
|
|
811
825
|
return;
|
|
812
826
|
}
|
|
813
827
|
const s = t.angle || 0;
|
|
814
|
-
this.currentAngle =
|
|
828
|
+
this.currentAngle = le._normalizeAngle(s), this.el.textContent = `${this.currentAngle}°`, this._positionIndicator(e.e), this.isActive || this._showIndicator();
|
|
815
829
|
}
|
|
816
830
|
/**
|
|
817
831
|
* Обработчик отпускания кнопки мыши
|
|
@@ -842,9 +856,9 @@ class de {
|
|
|
842
856
|
*/
|
|
843
857
|
_positionIndicator(e) {
|
|
844
858
|
const t = this.canvas.wrapperEl.getBoundingClientRect();
|
|
845
|
-
let s = e.clientX - t.left +
|
|
846
|
-
const
|
|
847
|
-
s +
|
|
859
|
+
let s = e.clientX - t.left + Ae, n = e.clientY - t.top + Ce;
|
|
860
|
+
const o = this.el.getBoundingClientRect(), a = o.width, i = o.height;
|
|
861
|
+
s + a > t.width && (s = e.clientX - t.left - a - Ae), n + i > t.height && (n = e.clientY - t.top - i - Ce), this.el.style.left = `${s}px`, this.el.style.top = `${n}px`;
|
|
848
862
|
}
|
|
849
863
|
/**
|
|
850
864
|
* Показать индикатор
|
|
@@ -875,7 +889,7 @@ class de {
|
|
|
875
889
|
this.canvas && (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:cleared", this._onSelectionCleared)), (e = this.el) != null && e.parentNode && this.el.parentNode.removeChild(this.el), this.el = null, this.editor = null, this.canvas = null, this.options = null;
|
|
876
890
|
}
|
|
877
891
|
}
|
|
878
|
-
class
|
|
892
|
+
class K {
|
|
879
893
|
constructor({ editor: e }) {
|
|
880
894
|
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();
|
|
881
895
|
}
|
|
@@ -887,7 +901,7 @@ class $ {
|
|
|
887
901
|
return this.patches[this.currentIndex - 1] || null;
|
|
888
902
|
}
|
|
889
903
|
_createDiffPatcher() {
|
|
890
|
-
this.diffPatcher =
|
|
904
|
+
this.diffPatcher = Ze({
|
|
891
905
|
objectHash(e) {
|
|
892
906
|
const t = e;
|
|
893
907
|
return [
|
|
@@ -943,10 +957,10 @@ class $ {
|
|
|
943
957
|
*/
|
|
944
958
|
getFullState() {
|
|
945
959
|
const { baseState: e, currentIndex: t, patches: s } = this;
|
|
946
|
-
let
|
|
947
|
-
for (let
|
|
948
|
-
|
|
949
|
-
return console.log("getFullState state",
|
|
960
|
+
let n = JSON.parse(JSON.stringify(e));
|
|
961
|
+
for (let o = 0; o < t; o += 1)
|
|
962
|
+
n = this.diffPatcher.patch(n, s[o].diff);
|
|
963
|
+
return console.log("getFullState state", n), n;
|
|
950
964
|
}
|
|
951
965
|
/**
|
|
952
966
|
* Сохраняем текущее состояние в виде диффа от последнего сохранённого полного состояния.
|
|
@@ -982,7 +996,7 @@ class $ {
|
|
|
982
996
|
console.log("Нет изменений для сохранения.");
|
|
983
997
|
return;
|
|
984
998
|
}
|
|
985
|
-
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:
|
|
999
|
+
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: C(), 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);
|
|
986
1000
|
}
|
|
987
1001
|
/**
|
|
988
1002
|
* Сериализует customData объектов в строку. Это необходимо чтобы при вызове loadFromJSON fabricjs не пытался обрабатывать свойства внутри customData, как свойства FabricObject, если их названия совпадают с зарезервированными.
|
|
@@ -1015,19 +1029,19 @@ class $ {
|
|
|
1015
1029
|
* @fires editor:history-state-loaded
|
|
1016
1030
|
*/
|
|
1017
1031
|
loadStateFromFullState(e) {
|
|
1018
|
-
return
|
|
1032
|
+
return y(this, null, function* () {
|
|
1019
1033
|
if (!e) return;
|
|
1020
1034
|
console.log("loadStateFromFullState fullState", e);
|
|
1021
|
-
const { canvas: t, canvasManager: s, interactionBlocker:
|
|
1022
|
-
|
|
1023
|
-
|
|
1035
|
+
const { canvas: t, canvasManager: s, interactionBlocker: n, backgroundManager: o } = this.editor, { width: a, height: i } = t;
|
|
1036
|
+
n.overlayMask = null, K._serializeCustomData(e), yield t.loadFromJSON(e, (l, g) => {
|
|
1037
|
+
K._deserializeCustomData(l, g);
|
|
1024
1038
|
});
|
|
1025
1039
|
const r = t.getObjects().find((l) => l.id === "montage-area");
|
|
1026
|
-
r && (this.editor.montageArea = r, (
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1040
|
+
r && (this.editor.montageArea = r, (a !== t.getWidth() || i !== t.getHeight()) && s.updateCanvas());
|
|
1041
|
+
const c = t.getObjects().find((l) => l.id === "overlay-mask");
|
|
1042
|
+
c && (n.overlayMask = c, n.overlayMask.visible = !1);
|
|
1029
1043
|
const h = t.getObjects().find((l) => l.id === "background");
|
|
1030
|
-
h ? (
|
|
1044
|
+
h ? (o.backgroundObject = h, o.refresh()) : o.removeBackground({ withoutSave: !0 }), t.renderAll(), t.fire("editor:history-state-loaded", {
|
|
1031
1045
|
fullState: e,
|
|
1032
1046
|
currentIndex: this.currentIndex,
|
|
1033
1047
|
totalChangesCount: this.totalChangesCount,
|
|
@@ -1042,7 +1056,7 @@ class $ {
|
|
|
1042
1056
|
* @fires editor:undo
|
|
1043
1057
|
*/
|
|
1044
1058
|
undo() {
|
|
1045
|
-
return
|
|
1059
|
+
return y(this, null, function* () {
|
|
1046
1060
|
if (!this.skipHistory) {
|
|
1047
1061
|
if (this.currentIndex <= 0) {
|
|
1048
1062
|
console.log("Нет предыдущих состояний для отмены.");
|
|
@@ -1079,7 +1093,7 @@ class $ {
|
|
|
1079
1093
|
* @fires editor:redo
|
|
1080
1094
|
*/
|
|
1081
1095
|
redo() {
|
|
1082
|
-
return
|
|
1096
|
+
return y(this, null, function* () {
|
|
1083
1097
|
if (!this.skipHistory) {
|
|
1084
1098
|
if (this.currentIndex >= this.patches.length) {
|
|
1085
1099
|
console.log("Нет состояний для повтора.");
|
|
@@ -1112,8 +1126,8 @@ class $ {
|
|
|
1112
1126
|
});
|
|
1113
1127
|
}
|
|
1114
1128
|
}
|
|
1115
|
-
const
|
|
1116
|
-
class
|
|
1129
|
+
const ht = 0.1, gt = 2, Se = 0.1, ut = 90, Z = 16, H = 16, B = 4096, x = 4096, De = "application/image-editor:";
|
|
1130
|
+
class _ {
|
|
1117
1131
|
constructor({ editor: e }) {
|
|
1118
1132
|
this.editor = e, this.options = e.options, this._createdBlobUrls = [], this.acceptContentTypes = this.editor.options.acceptContentTypes, this.acceptFormats = this.getAllowedFormatsFromContentTypes();
|
|
1119
1133
|
}
|
|
@@ -1130,111 +1144,111 @@ class N {
|
|
|
1130
1144
|
* @returns возвращает Promise с объектом изображения или null в случае ошибки
|
|
1131
1145
|
*/
|
|
1132
1146
|
importImage(e) {
|
|
1133
|
-
return
|
|
1147
|
+
return y(this, null, function* () {
|
|
1134
1148
|
const {
|
|
1135
1149
|
source: t,
|
|
1136
1150
|
scale: s = `image-${this.options.scaleType}`,
|
|
1137
|
-
withoutSave:
|
|
1138
|
-
fromClipboard:
|
|
1139
|
-
isBackground:
|
|
1151
|
+
withoutSave: n = !1,
|
|
1152
|
+
fromClipboard: o = !1,
|
|
1153
|
+
isBackground: a = !1,
|
|
1140
1154
|
withoutSelection: i = !1
|
|
1141
1155
|
} = e;
|
|
1142
1156
|
if (!t) return null;
|
|
1143
|
-
const { canvas: r, montageArea:
|
|
1144
|
-
if (!this.isAllowedContentType(
|
|
1145
|
-
const
|
|
1146
|
-
return
|
|
1157
|
+
const { canvas: r, montageArea: c, transformManager: h, historyManager: l, errorManager: g } = this.editor, u = yield this.getContentType(t), f = _.getFormatFromContentType(u), { acceptContentTypes: M, acceptFormats: b } = this;
|
|
1158
|
+
if (!this.isAllowedContentType(u)) {
|
|
1159
|
+
const m = `Неверный contentType для изображения: ${u}. Ожидается один из: ${this.acceptContentTypes.join(", ")}.`;
|
|
1160
|
+
return g.emitError({
|
|
1147
1161
|
origin: "ImageManager",
|
|
1148
1162
|
method: "importImage",
|
|
1149
1163
|
code: "INVALID_CONTENT_TYPE",
|
|
1150
|
-
message:
|
|
1164
|
+
message: m,
|
|
1151
1165
|
data: {
|
|
1152
1166
|
source: t,
|
|
1153
|
-
format:
|
|
1154
|
-
contentType:
|
|
1155
|
-
acceptContentTypes:
|
|
1156
|
-
acceptFormats:
|
|
1157
|
-
fromClipboard:
|
|
1158
|
-
isBackground:
|
|
1167
|
+
format: f,
|
|
1168
|
+
contentType: u,
|
|
1169
|
+
acceptContentTypes: M,
|
|
1170
|
+
acceptFormats: b,
|
|
1171
|
+
fromClipboard: o,
|
|
1172
|
+
isBackground: a,
|
|
1159
1173
|
withoutSelection: i
|
|
1160
1174
|
}
|
|
1161
1175
|
}), null;
|
|
1162
1176
|
}
|
|
1163
1177
|
l.suspendHistory();
|
|
1164
1178
|
try {
|
|
1165
|
-
let
|
|
1179
|
+
let m, p;
|
|
1166
1180
|
if (t instanceof File)
|
|
1167
|
-
|
|
1181
|
+
m = URL.createObjectURL(t);
|
|
1168
1182
|
else if (typeof t == "string") {
|
|
1169
|
-
const
|
|
1170
|
-
|
|
1183
|
+
const S = yield (yield fetch(t, { mode: "cors" })).blob();
|
|
1184
|
+
m = URL.createObjectURL(S);
|
|
1171
1185
|
} else
|
|
1172
|
-
return
|
|
1186
|
+
return g.emitError({
|
|
1173
1187
|
origin: "ImageManager",
|
|
1174
1188
|
method: "importImage",
|
|
1175
1189
|
code: "INVALID_SOURCE_TYPE",
|
|
1176
1190
|
message: "Неверный тип источника изображения. Ожидается URL или объект File.",
|
|
1177
1191
|
data: {
|
|
1178
1192
|
source: t,
|
|
1179
|
-
format:
|
|
1180
|
-
contentType:
|
|
1181
|
-
acceptContentTypes:
|
|
1182
|
-
acceptFormats:
|
|
1183
|
-
fromClipboard:
|
|
1184
|
-
isBackground:
|
|
1193
|
+
format: f,
|
|
1194
|
+
contentType: u,
|
|
1195
|
+
acceptContentTypes: M,
|
|
1196
|
+
acceptFormats: b,
|
|
1197
|
+
fromClipboard: o,
|
|
1198
|
+
isBackground: a,
|
|
1185
1199
|
withoutSelection: i
|
|
1186
1200
|
}
|
|
1187
1201
|
}), null;
|
|
1188
|
-
if (this._createdBlobUrls.push(
|
|
1189
|
-
const
|
|
1190
|
-
|
|
1202
|
+
if (this._createdBlobUrls.push(m), f === "svg") {
|
|
1203
|
+
const A = yield _e(m);
|
|
1204
|
+
p = F.groupSVGElements(A.objects, A.options);
|
|
1191
1205
|
} else
|
|
1192
|
-
|
|
1193
|
-
const { width:
|
|
1194
|
-
if (
|
|
1195
|
-
const
|
|
1196
|
-
let
|
|
1197
|
-
if (
|
|
1198
|
-
const
|
|
1199
|
-
this._createdBlobUrls.push(
|
|
1200
|
-
} else if (
|
|
1201
|
-
const
|
|
1202
|
-
this._createdBlobUrls.push(
|
|
1206
|
+
p = yield z.fromURL(m, { crossOrigin: "anonymous" });
|
|
1207
|
+
const { width: D, height: w } = p;
|
|
1208
|
+
if (p instanceof z) {
|
|
1209
|
+
const A = p.getElement();
|
|
1210
|
+
let S = "";
|
|
1211
|
+
if (A instanceof HTMLImageElement ? S = A.src : A instanceof HTMLCanvasElement && (S = A.toDataURL()), w > x || D > B) {
|
|
1212
|
+
const L = yield this.resizeImageToBoundaries(S, "max"), O = URL.createObjectURL(L);
|
|
1213
|
+
this._createdBlobUrls.push(O), p = yield z.fromURL(O, { crossOrigin: "anonymous" });
|
|
1214
|
+
} else if (w < H || D < Z) {
|
|
1215
|
+
const L = yield this.resizeImageToBoundaries(S, "min"), O = URL.createObjectURL(L);
|
|
1216
|
+
this._createdBlobUrls.push(O), p = yield z.fromURL(O, { crossOrigin: "anonymous" });
|
|
1203
1217
|
}
|
|
1204
1218
|
}
|
|
1205
|
-
if (
|
|
1206
|
-
this.editor.canvasManager.scaleMontageAreaToImage({ object:
|
|
1219
|
+
if (p.set("id", `${p.type}-${C()}`), p.set("format", f), s === "scale-montage")
|
|
1220
|
+
this.editor.canvasManager.scaleMontageAreaToImage({ object: p, withoutSave: !0 });
|
|
1207
1221
|
else {
|
|
1208
|
-
const { width:
|
|
1209
|
-
s === "image-contain" &&
|
|
1222
|
+
const { width: A, height: S } = c, L = this.calculateScaleFactor({ imageObject: p, scaleType: s });
|
|
1223
|
+
s === "image-contain" && L < 1 ? h.fitObject({ object: p, type: "contain", withoutSave: !0 }) : s === "image-cover" && (D > A || w > S) && h.fitObject({ object: p, type: "cover", withoutSave: !0 });
|
|
1210
1224
|
}
|
|
1211
|
-
r.add(
|
|
1212
|
-
const
|
|
1213
|
-
image:
|
|
1214
|
-
format:
|
|
1215
|
-
contentType:
|
|
1225
|
+
r.add(p), r.centerObject(p), i || r.setActiveObject(p), r.renderAll(), l.resumeHistory(), n || l.saveState();
|
|
1226
|
+
const T = {
|
|
1227
|
+
image: p,
|
|
1228
|
+
format: f,
|
|
1229
|
+
contentType: u,
|
|
1216
1230
|
scale: s,
|
|
1217
|
-
withoutSave:
|
|
1231
|
+
withoutSave: n,
|
|
1218
1232
|
source: t,
|
|
1219
|
-
fromClipboard:
|
|
1220
|
-
isBackground:
|
|
1233
|
+
fromClipboard: o,
|
|
1234
|
+
isBackground: a,
|
|
1221
1235
|
withoutSelection: i
|
|
1222
1236
|
};
|
|
1223
|
-
return r.fire("editor:image-imported",
|
|
1224
|
-
} catch (
|
|
1225
|
-
return
|
|
1237
|
+
return r.fire("editor:image-imported", T), T;
|
|
1238
|
+
} catch (m) {
|
|
1239
|
+
return g.emitError({
|
|
1226
1240
|
origin: "ImageManager",
|
|
1227
1241
|
method: "importImage",
|
|
1228
1242
|
code: "IMPORT_FAILED",
|
|
1229
|
-
message: `Ошибка импорта изображения: ${
|
|
1243
|
+
message: `Ошибка импорта изображения: ${m.message}`,
|
|
1230
1244
|
data: {
|
|
1231
1245
|
source: t,
|
|
1232
|
-
format:
|
|
1233
|
-
contentType:
|
|
1246
|
+
format: f,
|
|
1247
|
+
contentType: u,
|
|
1234
1248
|
scale: s,
|
|
1235
|
-
withoutSave:
|
|
1236
|
-
fromClipboard:
|
|
1237
|
-
isBackground:
|
|
1249
|
+
withoutSave: n,
|
|
1250
|
+
fromClipboard: o,
|
|
1251
|
+
isBackground: a,
|
|
1238
1252
|
withoutSelection: i
|
|
1239
1253
|
}
|
|
1240
1254
|
}), l.resumeHistory(), null;
|
|
@@ -1250,24 +1264,24 @@ class N {
|
|
|
1250
1264
|
* @returns возвращает Promise с Blob-объектом уменьшенного изображения
|
|
1251
1265
|
*/
|
|
1252
1266
|
resizeImageToBoundaries(e, t = "max") {
|
|
1253
|
-
return
|
|
1254
|
-
let s = `Размер изображения больше максимального размера канваса, поэтому оно будет уменьшено до максимальных размеров c сохранением пропорций: ${
|
|
1255
|
-
t === "min" && (s = `Размер изображения меньше минимального размера канваса, поэтому оно будет увеличено до минимальных размеров c сохранением пропорций: ${
|
|
1256
|
-
const
|
|
1267
|
+
return y(this, null, function* () {
|
|
1268
|
+
let s = `Размер изображения больше максимального размера канваса, поэтому оно будет уменьшено до максимальных размеров c сохранением пропорций: ${B}x${x}`;
|
|
1269
|
+
t === "min" && (s = `Размер изображения меньше минимального размера канваса, поэтому оно будет увеличено до минимальных размеров c сохранением пропорций: ${Z}x${H}`);
|
|
1270
|
+
const n = {
|
|
1257
1271
|
dataURL: e,
|
|
1258
1272
|
sizeType: t,
|
|
1259
|
-
maxWidth:
|
|
1260
|
-
maxHeight:
|
|
1261
|
-
minWidth:
|
|
1262
|
-
minHeight:
|
|
1273
|
+
maxWidth: B,
|
|
1274
|
+
maxHeight: x,
|
|
1275
|
+
minWidth: Z,
|
|
1276
|
+
minHeight: H
|
|
1263
1277
|
};
|
|
1264
1278
|
return this.editor.errorManager.emitWarning({
|
|
1265
1279
|
origin: "ImageManager",
|
|
1266
1280
|
method: "resizeImageToBoundaries",
|
|
1267
1281
|
code: "IMAGE_RESIZE_WARNING",
|
|
1268
1282
|
message: s,
|
|
1269
|
-
data:
|
|
1270
|
-
}), this.editor.workerManager.post("resizeImage",
|
|
1283
|
+
data: n
|
|
1284
|
+
}), this.editor.workerManager.post("resizeImage", n);
|
|
1271
1285
|
});
|
|
1272
1286
|
}
|
|
1273
1287
|
/**
|
|
@@ -1282,105 +1296,105 @@ class N {
|
|
|
1282
1296
|
* @fires editor:canvas-exported
|
|
1283
1297
|
*/
|
|
1284
1298
|
exportCanvasAsImageFile() {
|
|
1285
|
-
return
|
|
1299
|
+
return y(this, arguments, function* (e = {}) {
|
|
1286
1300
|
const {
|
|
1287
1301
|
fileName: t = "image.png",
|
|
1288
1302
|
contentType: s = "image/png",
|
|
1289
|
-
exportAsBase64:
|
|
1290
|
-
exportAsBlob:
|
|
1291
|
-
} = e, { canvas:
|
|
1303
|
+
exportAsBase64: n = !1,
|
|
1304
|
+
exportAsBlob: o = !1
|
|
1305
|
+
} = e, { canvas: a, montageArea: i, workerManager: r, interactionBlocker: c } = this.editor;
|
|
1292
1306
|
try {
|
|
1293
|
-
const h = s === "application/pdf", l = h ? "image/jpg" : s,
|
|
1307
|
+
const h = s === "application/pdf", l = h ? "image/jpg" : s, g = _.getFormatFromContentType(l);
|
|
1294
1308
|
i.setCoords();
|
|
1295
|
-
const { left:
|
|
1296
|
-
|
|
1297
|
-
const
|
|
1298
|
-
if (
|
|
1299
|
-
const
|
|
1300
|
-
|
|
1309
|
+
const { left: u, top: f, width: M, height: b } = i.getBoundingRect(), m = yield a.clone(["id", "format", "locked"]);
|
|
1310
|
+
m.enableRetinaScaling = !1, ["image/jpg", "image/jpeg"].includes(l) && (m.backgroundColor = "#ffffff");
|
|
1311
|
+
const p = m.getObjects().find((j) => j.id === i.id);
|
|
1312
|
+
if (p && (p.visible = !1), c != null && c.isBlocked) {
|
|
1313
|
+
const j = m.getObjects().find((E) => E.id === c.overlayMask.id);
|
|
1314
|
+
j && (j.visible = !1);
|
|
1301
1315
|
}
|
|
1302
|
-
|
|
1303
|
-
const
|
|
1304
|
-
if (
|
|
1305
|
-
const
|
|
1306
|
-
|
|
1307
|
-
const
|
|
1308
|
-
image:
|
|
1309
|
-
exportAsBase64:
|
|
1310
|
-
exportAsBlob:
|
|
1316
|
+
m.viewportTransform = [1, 0, 0, 1, -u, -f], m.setDimensions({ width: M, height: b }, { backstoreOnly: !0 }), m.renderAll();
|
|
1317
|
+
const D = m.getObjects().filter((j) => j.format).every((j) => j.format === "svg");
|
|
1318
|
+
if (g === "svg" && D) {
|
|
1319
|
+
const j = m.toSVG();
|
|
1320
|
+
m.dispose();
|
|
1321
|
+
const N = {
|
|
1322
|
+
image: _._exportSVGStringAsFile(j, {
|
|
1323
|
+
exportAsBase64: n,
|
|
1324
|
+
exportAsBlob: o,
|
|
1311
1325
|
fileName: t
|
|
1312
1326
|
}),
|
|
1313
1327
|
format: "svg",
|
|
1314
1328
|
contentType: "image/svg+xml",
|
|
1315
1329
|
fileName: t.replace(/\.[^/.]+$/, ".svg")
|
|
1316
1330
|
};
|
|
1317
|
-
return
|
|
1331
|
+
return a.fire("editor:canvas-exported", N), N;
|
|
1318
1332
|
}
|
|
1319
|
-
const
|
|
1320
|
-
|
|
1321
|
-
|
|
1333
|
+
const w = yield new Promise((j, E) => {
|
|
1334
|
+
m.getElement().toBlob((N) => {
|
|
1335
|
+
N ? j(N) : E(new Error("Failed to create Blob from canvas"));
|
|
1322
1336
|
});
|
|
1323
1337
|
});
|
|
1324
|
-
if (
|
|
1325
|
-
const
|
|
1326
|
-
image:
|
|
1327
|
-
format:
|
|
1338
|
+
if (m.dispose(), o) {
|
|
1339
|
+
const j = {
|
|
1340
|
+
image: w,
|
|
1341
|
+
format: g,
|
|
1328
1342
|
contentType: l,
|
|
1329
1343
|
fileName: t
|
|
1330
1344
|
};
|
|
1331
|
-
return
|
|
1345
|
+
return a.fire("editor:canvas-exported", j), j;
|
|
1332
1346
|
}
|
|
1333
|
-
const
|
|
1347
|
+
const T = yield createImageBitmap(w), A = yield r.post(
|
|
1334
1348
|
"toDataURL",
|
|
1335
|
-
{ format:
|
|
1336
|
-
[
|
|
1349
|
+
{ format: g, quality: 1, bitmap: T },
|
|
1350
|
+
[T]
|
|
1337
1351
|
);
|
|
1338
1352
|
if (h) {
|
|
1339
|
-
const
|
|
1340
|
-
orientation:
|
|
1353
|
+
const E = M * 0.264583, N = b * 0.264583, te = (yield this.editor.moduleLoader.loadModule("jspdf")).jsPDF, se = new te({
|
|
1354
|
+
orientation: E > N ? "landscape" : "portrait",
|
|
1341
1355
|
unit: "mm",
|
|
1342
|
-
format: [
|
|
1356
|
+
format: [E, N]
|
|
1343
1357
|
});
|
|
1344
|
-
if (
|
|
1345
|
-
const
|
|
1346
|
-
image:
|
|
1358
|
+
if (se.addImage(String(A), "JPG", 0, 0, E, N), n) {
|
|
1359
|
+
const fe = {
|
|
1360
|
+
image: se.output("datauristring"),
|
|
1347
1361
|
format: "pdf",
|
|
1348
1362
|
contentType: "application/pdf",
|
|
1349
1363
|
fileName: t
|
|
1350
1364
|
};
|
|
1351
|
-
return
|
|
1365
|
+
return a.fire("editor:canvas-exported", fe), fe;
|
|
1352
1366
|
}
|
|
1353
|
-
const
|
|
1354
|
-
image: new File([
|
|
1367
|
+
const we = se.output("blob"), ue = {
|
|
1368
|
+
image: new File([we], t, { type: "application/pdf" }),
|
|
1355
1369
|
format: "pdf",
|
|
1356
1370
|
contentType: "application/pdf",
|
|
1357
1371
|
fileName: t
|
|
1358
1372
|
};
|
|
1359
|
-
return
|
|
1373
|
+
return a.fire("editor:canvas-exported", ue), ue;
|
|
1360
1374
|
}
|
|
1361
|
-
if (
|
|
1362
|
-
const
|
|
1363
|
-
image:
|
|
1364
|
-
format:
|
|
1375
|
+
if (n) {
|
|
1376
|
+
const j = {
|
|
1377
|
+
image: A,
|
|
1378
|
+
format: g,
|
|
1365
1379
|
contentType: l,
|
|
1366
1380
|
fileName: t
|
|
1367
1381
|
};
|
|
1368
|
-
return
|
|
1382
|
+
return a.fire("editor:canvas-exported", j), j;
|
|
1369
1383
|
}
|
|
1370
|
-
const
|
|
1371
|
-
image: new File([
|
|
1372
|
-
format:
|
|
1384
|
+
const S = g === "svg" && !D ? t.replace(/\.[^/.]+$/, ".png") : t, O = {
|
|
1385
|
+
image: new File([w], S, { type: l }),
|
|
1386
|
+
format: g,
|
|
1373
1387
|
contentType: l,
|
|
1374
|
-
fileName:
|
|
1388
|
+
fileName: S
|
|
1375
1389
|
};
|
|
1376
|
-
return
|
|
1390
|
+
return a.fire("editor:canvas-exported", O), O;
|
|
1377
1391
|
} catch (h) {
|
|
1378
1392
|
return this.editor.errorManager.emitError({
|
|
1379
1393
|
origin: "ImageManager",
|
|
1380
1394
|
method: "exportCanvasAsImageFile",
|
|
1381
1395
|
code: "IMAGE_EXPORT_FAILED",
|
|
1382
1396
|
message: `Ошибка экспорта изображения: ${h.message}`,
|
|
1383
|
-
data: { contentType: s, fileName: t, exportAsBase64:
|
|
1397
|
+
data: { contentType: s, fileName: t, exportAsBase64: n, exportAsBlob: o }
|
|
1384
1398
|
}), null;
|
|
1385
1399
|
}
|
|
1386
1400
|
});
|
|
@@ -1397,88 +1411,88 @@ class N {
|
|
|
1397
1411
|
* @fires editor:object-exported
|
|
1398
1412
|
*/
|
|
1399
1413
|
exportObjectAsImageFile() {
|
|
1400
|
-
return
|
|
1414
|
+
return y(this, arguments, function* (e = {}) {
|
|
1401
1415
|
const {
|
|
1402
1416
|
object: t,
|
|
1403
1417
|
fileName: s = "image.png",
|
|
1404
|
-
contentType:
|
|
1405
|
-
exportAsBase64:
|
|
1406
|
-
exportAsBlob:
|
|
1407
|
-
} = e, { canvas: i, workerManager: r } = this.editor,
|
|
1408
|
-
if (!
|
|
1418
|
+
contentType: n = "image/png",
|
|
1419
|
+
exportAsBase64: o = !1,
|
|
1420
|
+
exportAsBlob: a = !1
|
|
1421
|
+
} = e, { canvas: i, workerManager: r } = this.editor, c = t || i.getActiveObject();
|
|
1422
|
+
if (!c)
|
|
1409
1423
|
return this.editor.errorManager.emitError({
|
|
1410
1424
|
origin: "ImageManager",
|
|
1411
1425
|
method: "exportObjectAsImageFile",
|
|
1412
1426
|
code: "NO_OBJECT_SELECTED",
|
|
1413
1427
|
message: "Не выбран объект для экспорта",
|
|
1414
|
-
data: { contentType:
|
|
1428
|
+
data: { contentType: n, fileName: s, exportAsBase64: o, exportAsBlob: a }
|
|
1415
1429
|
}), null;
|
|
1416
1430
|
try {
|
|
1417
|
-
const h =
|
|
1431
|
+
const h = _.getFormatFromContentType(n);
|
|
1418
1432
|
if (h === "svg") {
|
|
1419
|
-
const
|
|
1420
|
-
exportAsBase64:
|
|
1421
|
-
exportAsBlob:
|
|
1433
|
+
const M = c.toSVG(), b = _._exportSVGStringAsFile(M, {
|
|
1434
|
+
exportAsBase64: o,
|
|
1435
|
+
exportAsBlob: a,
|
|
1422
1436
|
fileName: s
|
|
1423
|
-
}),
|
|
1424
|
-
object:
|
|
1425
|
-
image:
|
|
1437
|
+
}), m = {
|
|
1438
|
+
object: c,
|
|
1439
|
+
image: b,
|
|
1426
1440
|
format: h,
|
|
1427
1441
|
contentType: "image/svg+xml",
|
|
1428
1442
|
fileName: s.replace(/\.[^/.]+$/, ".svg")
|
|
1429
1443
|
};
|
|
1430
|
-
return i.fire("editor:object-exported",
|
|
1444
|
+
return i.fire("editor:object-exported", m), m;
|
|
1431
1445
|
}
|
|
1432
|
-
if (
|
|
1433
|
-
const
|
|
1446
|
+
if (o && c instanceof z) {
|
|
1447
|
+
const M = yield createImageBitmap(c.getElement()), b = yield r.post(
|
|
1434
1448
|
"toDataURL",
|
|
1435
1449
|
{
|
|
1436
1450
|
format: h,
|
|
1437
1451
|
quality: 1,
|
|
1438
|
-
bitmap:
|
|
1452
|
+
bitmap: M
|
|
1439
1453
|
},
|
|
1440
|
-
[
|
|
1441
|
-
),
|
|
1442
|
-
object:
|
|
1443
|
-
image:
|
|
1454
|
+
[M]
|
|
1455
|
+
), m = {
|
|
1456
|
+
object: c,
|
|
1457
|
+
image: b,
|
|
1444
1458
|
format: h,
|
|
1445
|
-
contentType:
|
|
1459
|
+
contentType: n,
|
|
1446
1460
|
fileName: s
|
|
1447
1461
|
};
|
|
1448
|
-
return i.fire("editor:object-exported",
|
|
1462
|
+
return i.fire("editor:object-exported", m), m;
|
|
1449
1463
|
}
|
|
1450
|
-
const l =
|
|
1464
|
+
const l = c.toCanvasElement({
|
|
1451
1465
|
enableRetinaScaling: !1
|
|
1452
|
-
}),
|
|
1453
|
-
l.toBlob((
|
|
1454
|
-
|
|
1466
|
+
}), g = yield new Promise((M, b) => {
|
|
1467
|
+
l.toBlob((m) => {
|
|
1468
|
+
m ? M(m) : b(new Error("Failed to create Blob from canvas"));
|
|
1455
1469
|
});
|
|
1456
1470
|
});
|
|
1457
|
-
if (
|
|
1458
|
-
const
|
|
1459
|
-
object:
|
|
1460
|
-
image:
|
|
1471
|
+
if (a) {
|
|
1472
|
+
const M = {
|
|
1473
|
+
object: c,
|
|
1474
|
+
image: g,
|
|
1461
1475
|
format: h,
|
|
1462
|
-
contentType:
|
|
1476
|
+
contentType: n,
|
|
1463
1477
|
fileName: s
|
|
1464
1478
|
};
|
|
1465
|
-
return i.fire("editor:object-exported",
|
|
1479
|
+
return i.fire("editor:object-exported", M), M;
|
|
1466
1480
|
}
|
|
1467
|
-
const
|
|
1468
|
-
object:
|
|
1469
|
-
image:
|
|
1481
|
+
const u = new File([g], s, { type: n }), f = {
|
|
1482
|
+
object: c,
|
|
1483
|
+
image: u,
|
|
1470
1484
|
format: h,
|
|
1471
|
-
contentType:
|
|
1485
|
+
contentType: n,
|
|
1472
1486
|
fileName: s
|
|
1473
1487
|
};
|
|
1474
|
-
return i.fire("editor:object-exported",
|
|
1488
|
+
return i.fire("editor:object-exported", f), f;
|
|
1475
1489
|
} catch (h) {
|
|
1476
1490
|
return this.editor.errorManager.emitError({
|
|
1477
1491
|
origin: "ImageManager",
|
|
1478
1492
|
method: "exportObjectAsImageFile",
|
|
1479
1493
|
code: "IMAGE_EXPORT_FAILED",
|
|
1480
1494
|
message: `Ошибка экспорта объекта: ${h.message}`,
|
|
1481
|
-
data: { contentType:
|
|
1495
|
+
data: { contentType: n, fileName: s, exportAsBase64: o, exportAsBlob: a }
|
|
1482
1496
|
}), null;
|
|
1483
1497
|
}
|
|
1484
1498
|
});
|
|
@@ -1494,7 +1508,7 @@ class N {
|
|
|
1494
1508
|
* @returns массив допустимых форматов изображений
|
|
1495
1509
|
*/
|
|
1496
1510
|
getAllowedFormatsFromContentTypes() {
|
|
1497
|
-
return this.acceptContentTypes.map((e) =>
|
|
1511
|
+
return this.acceptContentTypes.map((e) => _.getFormatFromContentType(e)).filter((e) => e);
|
|
1498
1512
|
}
|
|
1499
1513
|
/**
|
|
1500
1514
|
* Проверяет, является ли contentType допустимым типом изображения.
|
|
@@ -1510,7 +1524,7 @@ class N {
|
|
|
1510
1524
|
* @public
|
|
1511
1525
|
*/
|
|
1512
1526
|
getContentType(e) {
|
|
1513
|
-
return
|
|
1527
|
+
return y(this, null, function* () {
|
|
1514
1528
|
return typeof e == "string" ? this.getContentTypeFromUrl(e) : e.type || "application/octet-stream";
|
|
1515
1529
|
});
|
|
1516
1530
|
}
|
|
@@ -1521,7 +1535,7 @@ class N {
|
|
|
1521
1535
|
* @public
|
|
1522
1536
|
*/
|
|
1523
1537
|
getContentTypeFromUrl(e) {
|
|
1524
|
-
return
|
|
1538
|
+
return y(this, null, function* () {
|
|
1525
1539
|
if (e.startsWith("data:")) {
|
|
1526
1540
|
const t = e.match(/^data:([^;]+)/);
|
|
1527
1541
|
return t ? t[1] : "application/octet-stream";
|
|
@@ -1545,11 +1559,11 @@ class N {
|
|
|
1545
1559
|
getContentTypeFromExtension(e) {
|
|
1546
1560
|
var t;
|
|
1547
1561
|
try {
|
|
1548
|
-
const
|
|
1549
|
-
return this.acceptContentTypes.forEach((
|
|
1550
|
-
const i =
|
|
1551
|
-
i && (
|
|
1552
|
-
}),
|
|
1562
|
+
const n = (t = new URL(e).pathname.split(".").pop()) == null ? void 0 : t.toLowerCase(), o = {};
|
|
1563
|
+
return this.acceptContentTypes.forEach((a) => {
|
|
1564
|
+
const i = _.getFormatFromContentType(a);
|
|
1565
|
+
i && (o[i] = a);
|
|
1566
|
+
}), n && o[n] || "application/octet-stream";
|
|
1553
1567
|
} catch (s) {
|
|
1554
1568
|
return console.warn("Не удалось определить расширение из URL:", e, s), "application/octet-stream";
|
|
1555
1569
|
}
|
|
@@ -1567,8 +1581,8 @@ class N {
|
|
|
1567
1581
|
}) {
|
|
1568
1582
|
const { montageArea: s } = this.editor;
|
|
1569
1583
|
if (!s || !e) return 1;
|
|
1570
|
-
const
|
|
1571
|
-
return t === "contain" || t === "image-contain" ? Math.min(
|
|
1584
|
+
const n = s.width, o = s.height, { width: a, height: i } = e;
|
|
1585
|
+
return t === "contain" || t === "image-contain" ? Math.min(n / a, o / i) : t === "cover" || t === "image-cover" ? Math.max(n / a, o / i) : 1;
|
|
1572
1586
|
}
|
|
1573
1587
|
/**
|
|
1574
1588
|
* Преобразует SVG-строку в Blob, файл, или base64
|
|
@@ -1584,9 +1598,9 @@ class N {
|
|
|
1584
1598
|
static _exportSVGStringAsFile(e, {
|
|
1585
1599
|
exportAsBase64: t,
|
|
1586
1600
|
exportAsBlob: s,
|
|
1587
|
-
fileName:
|
|
1601
|
+
fileName: n = "image.svg"
|
|
1588
1602
|
} = {}) {
|
|
1589
|
-
return s ? new Blob([e], { type: "image/svg+xml" }) : t ? `data:image/svg+xml;base64,${window.btoa(encodeURIComponent(e))}` : new File([e],
|
|
1603
|
+
return s ? new Blob([e], { type: "image/svg+xml" }) : t ? `data:image/svg+xml;base64,${window.btoa(encodeURIComponent(e))}` : new File([e], n.replace(/\.[^/.]+$/, ".svg"), { type: "image/svg+xml" });
|
|
1590
1604
|
}
|
|
1591
1605
|
/**
|
|
1592
1606
|
* Извлекает чистый формат (subtype) из contentType,
|
|
@@ -1600,11 +1614,11 @@ class N {
|
|
|
1600
1614
|
return t ? t[1] : "";
|
|
1601
1615
|
}
|
|
1602
1616
|
}
|
|
1603
|
-
const
|
|
1604
|
-
function
|
|
1605
|
-
return ((
|
|
1617
|
+
const R = (d, e, t) => Math.max(Math.min(d, t), e), Ee = (d, e) => d * e, ft = (d, e) => new $(d / 2, e / 2);
|
|
1618
|
+
function mt(d) {
|
|
1619
|
+
return ((d == null ? void 0 : d.type) === "image" || (d == null ? void 0 : d.format) === "svg") && typeof (d == null ? void 0 : d.width) == "number" && typeof (d == null ? void 0 : d.height) == "number";
|
|
1606
1620
|
}
|
|
1607
|
-
class
|
|
1621
|
+
class Mt {
|
|
1608
1622
|
/**
|
|
1609
1623
|
* @param options
|
|
1610
1624
|
* @param options.editor – экземпляр редактора
|
|
@@ -1628,26 +1642,26 @@ class mt {
|
|
|
1628
1642
|
* @param options.adaptCanvasToContainer - Адаптировать канвас к контейнеру
|
|
1629
1643
|
* @fires editor:resolution-width-changed
|
|
1630
1644
|
*/
|
|
1631
|
-
setResolutionWidth(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer:
|
|
1632
|
-
var
|
|
1645
|
+
setResolutionWidth(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer: n } = {}) {
|
|
1646
|
+
var f;
|
|
1633
1647
|
if (!e) return;
|
|
1634
1648
|
const {
|
|
1635
|
-
canvas:
|
|
1636
|
-
montageArea:
|
|
1649
|
+
canvas: o,
|
|
1650
|
+
montageArea: a,
|
|
1637
1651
|
options: { canvasBackstoreWidth: i }
|
|
1638
|
-
} = this.editor, { width: r, height:
|
|
1639
|
-
if (!i || i === "auto" ||
|
|
1640
|
-
const
|
|
1641
|
-
this.setResolutionHeight(
|
|
1652
|
+
} = this.editor, { width: r, height: c } = a, h = R(Number(e), Z, B);
|
|
1653
|
+
if (!i || i === "auto" || n ? this.adaptCanvasToContainer() : i ? this.setCanvasBackstoreWidth(Number(i)) : this.setCanvasBackstoreWidth(h), a.set({ width: h }), (f = o.clipPath) == null || f.set({ width: h }), t) {
|
|
1654
|
+
const M = h / r, b = Ee(c, M);
|
|
1655
|
+
this.setResolutionHeight(b);
|
|
1642
1656
|
return;
|
|
1643
1657
|
}
|
|
1644
|
-
const { left: l, top:
|
|
1645
|
-
|
|
1658
|
+
const { left: l, top: g } = this.getObjectDefaultCoords(a), u = o.getZoom();
|
|
1659
|
+
o.setViewportTransform([u, 0, 0, u, l, g]), this.centerMontageArea(), s || this.editor.historyManager.saveState(), o.fire("editor:resolution-width-changed", {
|
|
1646
1660
|
width: h,
|
|
1647
1661
|
preserveProportional: t,
|
|
1648
1662
|
withoutSave: s,
|
|
1649
|
-
adaptCanvasToContainer:
|
|
1650
|
-
});
|
|
1663
|
+
adaptCanvasToContainer: n
|
|
1664
|
+
}), this.editor.panConstraintManager.updateBounds();
|
|
1651
1665
|
}
|
|
1652
1666
|
/**
|
|
1653
1667
|
* Устанавливаем внутреннюю высоту канваса (для экспорта)
|
|
@@ -1658,26 +1672,26 @@ class mt {
|
|
|
1658
1672
|
* @param options.adaptCanvasToContainer - Адаптировать канвас к контейнеру
|
|
1659
1673
|
* @fires editor:resolution-height-changed
|
|
1660
1674
|
*/
|
|
1661
|
-
setResolutionHeight(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer:
|
|
1662
|
-
var
|
|
1675
|
+
setResolutionHeight(e, { preserveProportional: t, withoutSave: s, adaptCanvasToContainer: n } = {}) {
|
|
1676
|
+
var f;
|
|
1663
1677
|
if (!e) return;
|
|
1664
1678
|
const {
|
|
1665
|
-
canvas:
|
|
1666
|
-
montageArea:
|
|
1679
|
+
canvas: o,
|
|
1680
|
+
montageArea: a,
|
|
1667
1681
|
options: { canvasBackstoreHeight: i }
|
|
1668
|
-
} = this.editor, { width: r, height:
|
|
1669
|
-
if (!i || i === "auto" ||
|
|
1670
|
-
const
|
|
1671
|
-
this.setResolutionWidth(
|
|
1682
|
+
} = this.editor, { width: r, height: c } = a, h = R(Number(e), H, x);
|
|
1683
|
+
if (!i || i === "auto" || n ? this.adaptCanvasToContainer() : i ? this.setCanvasBackstoreHeight(Number(i)) : this.setCanvasBackstoreHeight(h), a.set({ height: h }), (f = o.clipPath) == null || f.set({ height: h }), t) {
|
|
1684
|
+
const M = h / c, b = Ee(r, M);
|
|
1685
|
+
this.setResolutionWidth(b);
|
|
1672
1686
|
return;
|
|
1673
1687
|
}
|
|
1674
|
-
const { left: l, top:
|
|
1675
|
-
|
|
1688
|
+
const { left: l, top: g } = this.getObjectDefaultCoords(a), u = o.getZoom();
|
|
1689
|
+
o.setViewportTransform([u, 0, 0, u, l, g]), this.centerMontageArea(), s || this.editor.historyManager.saveState(), o.fire("editor:resolution-height-changed", {
|
|
1676
1690
|
height: h,
|
|
1677
1691
|
preserveProportional: t,
|
|
1678
1692
|
withoutSave: s,
|
|
1679
|
-
adaptCanvasToContainer:
|
|
1680
|
-
});
|
|
1693
|
+
adaptCanvasToContainer: n
|
|
1694
|
+
}), this.editor.panConstraintManager.updateBounds();
|
|
1681
1695
|
}
|
|
1682
1696
|
/**
|
|
1683
1697
|
* Центрирует монтажную область и ClipPath точно по центру канваса
|
|
@@ -1685,16 +1699,16 @@ class mt {
|
|
|
1685
1699
|
*/
|
|
1686
1700
|
centerMontageArea() {
|
|
1687
1701
|
var r;
|
|
1688
|
-
const { canvas: e, montageArea: t } = this.editor, s = e.getWidth(),
|
|
1702
|
+
const { canvas: e, montageArea: t } = this.editor, s = e.getWidth(), n = e.getHeight(), o = e.getZoom(), a = ft(s, n);
|
|
1689
1703
|
t.set({
|
|
1690
1704
|
left: s / 2,
|
|
1691
|
-
top:
|
|
1705
|
+
top: n / 2
|
|
1692
1706
|
}), (r = e.clipPath) == null || r.set({
|
|
1693
1707
|
left: s / 2,
|
|
1694
|
-
top:
|
|
1708
|
+
top: n / 2
|
|
1695
1709
|
}), e.renderAll();
|
|
1696
1710
|
const i = e.viewportTransform;
|
|
1697
|
-
i[4] = s / 2 -
|
|
1711
|
+
i[4] = s / 2 - a.x * o, i[5] = n / 2 - a.y * o, e.setViewportTransform(i), e.renderAll();
|
|
1698
1712
|
}
|
|
1699
1713
|
/**
|
|
1700
1714
|
* Метод для получения координат объекта с учетом текущего зума
|
|
@@ -1710,7 +1724,7 @@ class mt {
|
|
|
1710
1724
|
code: "NO_ACTIVE_OBJECT",
|
|
1711
1725
|
message: "Не выбран объект для получения координат"
|
|
1712
1726
|
}), { left: 0, top: 0 };
|
|
1713
|
-
const { width:
|
|
1727
|
+
const { width: n, height: o } = s, a = t.getZoom(), i = (n - n * a) / 2, r = (o - o * a) / 2;
|
|
1714
1728
|
return { left: i, top: r };
|
|
1715
1729
|
}
|
|
1716
1730
|
/**
|
|
@@ -1718,7 +1732,7 @@ class mt {
|
|
|
1718
1732
|
*/
|
|
1719
1733
|
setCanvasBackstoreWidth(e) {
|
|
1720
1734
|
if (!e || typeof e != "number") return;
|
|
1721
|
-
const t =
|
|
1735
|
+
const t = R(e, Z, B);
|
|
1722
1736
|
this.editor.canvas.setDimensions({ width: t }, { backstoreOnly: !0 });
|
|
1723
1737
|
}
|
|
1724
1738
|
/**
|
|
@@ -1727,7 +1741,7 @@ class mt {
|
|
|
1727
1741
|
*/
|
|
1728
1742
|
setCanvasBackstoreHeight(e) {
|
|
1729
1743
|
if (!e || typeof e != "number") return;
|
|
1730
|
-
const t =
|
|
1744
|
+
const t = R(e, H, x);
|
|
1731
1745
|
this.editor.canvas.setDimensions({ height: t }, { backstoreOnly: !0 });
|
|
1732
1746
|
}
|
|
1733
1747
|
/**
|
|
@@ -1736,8 +1750,8 @@ class mt {
|
|
|
1736
1750
|
* с учётом минимальных и максимальных значений.
|
|
1737
1751
|
*/
|
|
1738
1752
|
adaptCanvasToContainer() {
|
|
1739
|
-
const { canvas: e } = this.editor, t = this.getEditorContainer(), s = t.clientWidth,
|
|
1740
|
-
e.setDimensions({ width:
|
|
1753
|
+
const { canvas: e } = this.editor, t = this.getEditorContainer(), s = t.clientWidth, n = t.clientHeight, o = R(s, Z, B), a = R(n, H, x);
|
|
1754
|
+
e.setDimensions({ width: o, height: a }, { backstoreOnly: !0 });
|
|
1741
1755
|
}
|
|
1742
1756
|
/**
|
|
1743
1757
|
* Обновляет размеры канваса без изменения позиций объектов.
|
|
@@ -1750,15 +1764,15 @@ class mt {
|
|
|
1750
1764
|
montageArea: t,
|
|
1751
1765
|
montageArea: {
|
|
1752
1766
|
width: s,
|
|
1753
|
-
height:
|
|
1767
|
+
height: n
|
|
1754
1768
|
}
|
|
1755
|
-
} = this.editor,
|
|
1756
|
-
this.setResolutionWidth(s, { adaptCanvasToContainer: !0, withoutSave: !0 }), this.setResolutionHeight(
|
|
1757
|
-
const i = t.left -
|
|
1769
|
+
} = this.editor, o = t.left, a = t.top;
|
|
1770
|
+
this.setResolutionWidth(s, { adaptCanvasToContainer: !0, withoutSave: !0 }), this.setResolutionHeight(n, { adaptCanvasToContainer: !0, withoutSave: !0 }), this.centerMontageArea();
|
|
1771
|
+
const i = t.left - o, r = t.top - a;
|
|
1758
1772
|
if (i !== 0 || r !== 0) {
|
|
1759
|
-
const
|
|
1760
|
-
if ((
|
|
1761
|
-
const l =
|
|
1773
|
+
const c = e.getActiveObject(), h = [];
|
|
1774
|
+
if ((c == null ? void 0 : c.type) === "activeselection") {
|
|
1775
|
+
const l = c;
|
|
1762
1776
|
h.push(...l.getObjects()), e.discardActiveObject();
|
|
1763
1777
|
}
|
|
1764
1778
|
if (e.getObjects().forEach((l) => {
|
|
@@ -1778,8 +1792,8 @@ class mt {
|
|
|
1778
1792
|
}
|
|
1779
1793
|
e.renderAll(), e.fire("editor:canvas-updated", {
|
|
1780
1794
|
width: s,
|
|
1781
|
-
height:
|
|
1782
|
-
});
|
|
1795
|
+
height: n
|
|
1796
|
+
}), this.editor.panConstraintManager.updateBounds();
|
|
1783
1797
|
}
|
|
1784
1798
|
/**
|
|
1785
1799
|
* Заготовка.
|
|
@@ -1888,32 +1902,32 @@ class mt {
|
|
|
1888
1902
|
*/
|
|
1889
1903
|
setDisplayDimension({ element: e = "canvas", dimension: t, value: s } = {}) {
|
|
1890
1904
|
if (!s) return;
|
|
1891
|
-
const { canvas:
|
|
1905
|
+
const { canvas: n } = this.editor, o = [];
|
|
1892
1906
|
switch (e) {
|
|
1893
1907
|
case "canvas":
|
|
1894
|
-
|
|
1908
|
+
o.push(n.lowerCanvasEl, n.upperCanvasEl);
|
|
1895
1909
|
break;
|
|
1896
1910
|
case "wrapper":
|
|
1897
|
-
|
|
1911
|
+
o.push(n.wrapperEl);
|
|
1898
1912
|
break;
|
|
1899
1913
|
case "container":
|
|
1900
|
-
|
|
1914
|
+
o.push(this.getEditorContainer());
|
|
1901
1915
|
break;
|
|
1902
1916
|
default:
|
|
1903
|
-
|
|
1917
|
+
o.push(n.lowerCanvasEl, n.upperCanvasEl);
|
|
1904
1918
|
}
|
|
1905
|
-
const
|
|
1919
|
+
const a = t === "width" ? "width" : "height";
|
|
1906
1920
|
if (typeof s == "string") {
|
|
1907
|
-
|
|
1908
|
-
r.style[
|
|
1921
|
+
o.forEach((r) => {
|
|
1922
|
+
r.style[a] = s;
|
|
1909
1923
|
});
|
|
1910
1924
|
return;
|
|
1911
1925
|
}
|
|
1912
1926
|
if (isNaN(s)) return;
|
|
1913
1927
|
const i = `${s}px`;
|
|
1914
|
-
|
|
1915
|
-
r.style[
|
|
1916
|
-
}),
|
|
1928
|
+
o.forEach((r) => {
|
|
1929
|
+
r.style[a] = i;
|
|
1930
|
+
}), n.fire(`editor:display-${e}-${a}-changed`, {
|
|
1917
1931
|
element: e,
|
|
1918
1932
|
value: s
|
|
1919
1933
|
});
|
|
@@ -1928,28 +1942,28 @@ class mt {
|
|
|
1928
1942
|
*/
|
|
1929
1943
|
scaleMontageAreaToImage({ object: e, preserveAspectRatio: t, withoutSave: s } = {}) {
|
|
1930
1944
|
const {
|
|
1931
|
-
canvas:
|
|
1932
|
-
montageArea:
|
|
1933
|
-
transformManager:
|
|
1945
|
+
canvas: n,
|
|
1946
|
+
montageArea: o,
|
|
1947
|
+
transformManager: a,
|
|
1934
1948
|
options: {
|
|
1935
1949
|
montageAreaWidth: i,
|
|
1936
1950
|
montageAreaHeight: r
|
|
1937
1951
|
}
|
|
1938
|
-
} = this.editor,
|
|
1939
|
-
if (!
|
|
1940
|
-
const { width: h, height: l } =
|
|
1941
|
-
let
|
|
1952
|
+
} = this.editor, c = e || n.getActiveObject();
|
|
1953
|
+
if (!mt(c)) return;
|
|
1954
|
+
const { width: h, height: l } = c;
|
|
1955
|
+
let g = Math.min(h, B), u = Math.min(l, x);
|
|
1942
1956
|
if (t) {
|
|
1943
1957
|
const {
|
|
1944
|
-
width:
|
|
1945
|
-
height:
|
|
1946
|
-
} =
|
|
1947
|
-
|
|
1958
|
+
width: f,
|
|
1959
|
+
height: M
|
|
1960
|
+
} = o, b = h / f, m = l / M, p = Math.max(b, m);
|
|
1961
|
+
g = f * p, u = M * p;
|
|
1948
1962
|
}
|
|
1949
|
-
this.setResolutionWidth(
|
|
1950
|
-
object:
|
|
1951
|
-
width:
|
|
1952
|
-
height:
|
|
1963
|
+
this.setResolutionWidth(g, { withoutSave: !0 }), this.setResolutionHeight(u, { withoutSave: !0 }), this.editor.backgroundManager.backgroundObject && this.editor.backgroundManager.refresh(), (h > i || l > r) && this.editor.zoomManager.calculateAndApplyDefaultZoom(), a.resetObject({ object: c, withoutSave: !0 }), n.centerObject(c), n.renderAll(), s || this.editor.historyManager.saveState(), n.fire("editor:montage-area-scaled-to-image", {
|
|
1964
|
+
object: c,
|
|
1965
|
+
width: g,
|
|
1966
|
+
height: u,
|
|
1953
1967
|
preserveAspectRatio: t,
|
|
1954
1968
|
withoutSave: s
|
|
1955
1969
|
});
|
|
@@ -1972,13 +1986,13 @@ class mt {
|
|
|
1972
1986
|
const {
|
|
1973
1987
|
canvas: t,
|
|
1974
1988
|
transformManager: s,
|
|
1975
|
-
historyManager:
|
|
1989
|
+
historyManager: n,
|
|
1976
1990
|
options: {
|
|
1977
|
-
montageAreaWidth:
|
|
1978
|
-
montageAreaHeight:
|
|
1991
|
+
montageAreaWidth: o,
|
|
1992
|
+
montageAreaHeight: a
|
|
1979
1993
|
}
|
|
1980
1994
|
} = this.editor;
|
|
1981
|
-
|
|
1995
|
+
this.editor.zoomManager.resetZoom(), this.setResolutionWidth(o, { withoutSave: !0 }), this.setResolutionHeight(a, { withoutSave: !0 }), t.renderAll(), s.resetObjects(), e || n.saveState(), t.fire("editor:default-scale-set");
|
|
1982
1996
|
}
|
|
1983
1997
|
/**
|
|
1984
1998
|
* Получение всех объектов внутри монтажной области редактора
|
|
@@ -1989,72 +2003,16 @@ class mt {
|
|
|
1989
2003
|
canvas: e,
|
|
1990
2004
|
montageArea: t,
|
|
1991
2005
|
interactionBlocker: { overlayMask: s },
|
|
1992
|
-
backgroundManager: { backgroundObject:
|
|
2006
|
+
backgroundManager: { backgroundObject: n }
|
|
1993
2007
|
} = this.editor;
|
|
1994
2008
|
return e.getObjects().filter(
|
|
1995
|
-
(
|
|
2009
|
+
(a) => a.id !== t.id && a.id !== (s == null ? void 0 : s.id) && a.id !== (n == null ? void 0 : n.id)
|
|
1996
2010
|
);
|
|
1997
2011
|
}
|
|
1998
2012
|
}
|
|
1999
|
-
class
|
|
2013
|
+
class pt {
|
|
2000
2014
|
constructor({ editor: e }) {
|
|
2001
|
-
this.editor = e, this.options = e.options
|
|
2002
|
-
}
|
|
2003
|
-
/**
|
|
2004
|
-
* Метод рассчитывает и применяет зум по умолчанию для монтажной области редактора.
|
|
2005
|
-
* Зум рассчитывается исходя из размеров контейнера редактора и текущих размеров монтажной области.
|
|
2006
|
-
* Расчёт происходит таким образом, чтобы монтажная область визуально целиком помещалась в контейнер редактора.
|
|
2007
|
-
* Если scale не передан, то используется значение из options.defaultScale.
|
|
2008
|
-
* @param scale - Желаемый масштаб относительно размеров контейнера редактора.
|
|
2009
|
-
*/
|
|
2010
|
-
calculateAndApplyDefaultZoom(e = this.options.defaultScale) {
|
|
2011
|
-
const { canvas: t } = this.editor, s = t.editorContainer, a = s.clientWidth, n = s.clientHeight, { width: o, height: i } = this.editor.montageArea, r = a / o * e, d = n / i * e;
|
|
2012
|
-
this.defaultZoom = Math.min(r, d), this.setZoom();
|
|
2013
|
-
}
|
|
2014
|
-
/**
|
|
2015
|
-
* Увеличение/уменьшение масштаба
|
|
2016
|
-
* @param scale - Шаг зума
|
|
2017
|
-
* @param options - Координаты зума (по умолчанию центр канваса)
|
|
2018
|
-
* @param options.pointX - Координата X точки зума
|
|
2019
|
-
* @param options.pointY - Координата Y точки зума
|
|
2020
|
-
* @fires editor:zoom-changed
|
|
2021
|
-
* Если передавать координаты курсора, то нужно быть аккуратнее, так как юзер может выйти за пределы рабочей области
|
|
2022
|
-
*/
|
|
2023
|
-
zoom(e = ut, t = {}) {
|
|
2024
|
-
var u, g;
|
|
2025
|
-
if (!e) return;
|
|
2026
|
-
const { minZoom: s, maxZoom: a } = this, { canvas: n } = this.editor, o = n.getZoom(), i = n.getCenterPoint(), r = (u = t.pointX) != null ? u : i.x, d = (g = t.pointY) != null ? g : i.y, h = new X(r, d);
|
|
2027
|
-
let l = Number((o + Number(e)).toFixed(2));
|
|
2028
|
-
l > a && (l = a), l < s && (l = s), n.zoomToPoint(h, l), n.fire("editor:zoom-changed", {
|
|
2029
|
-
currentZoom: n.getZoom(),
|
|
2030
|
-
zoom: l,
|
|
2031
|
-
point: h
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2034
|
-
/**
|
|
2035
|
-
* Установка зума
|
|
2036
|
-
* @param zoom - Зум
|
|
2037
|
-
* @fires editor:zoom-changed
|
|
2038
|
-
*/
|
|
2039
|
-
setZoom(e = this.defaultZoom) {
|
|
2040
|
-
const { minZoom: t, maxZoom: s } = this, { canvas: a } = this.editor, n = new X(a.getCenterPoint());
|
|
2041
|
-
let o = e;
|
|
2042
|
-
e > s && (o = s), e < t && (o = t), a.zoomToPoint(n, o), a.fire("editor:zoom-changed", {
|
|
2043
|
-
currentZoom: a.getZoom(),
|
|
2044
|
-
zoom: o,
|
|
2045
|
-
point: n
|
|
2046
|
-
});
|
|
2047
|
-
}
|
|
2048
|
-
/**
|
|
2049
|
-
* Сброс зума
|
|
2050
|
-
* @fires editor:zoom-changed
|
|
2051
|
-
*/
|
|
2052
|
-
resetZoom() {
|
|
2053
|
-
const { canvas: e } = this.editor, t = new X(e.getCenterPoint());
|
|
2054
|
-
e.zoomToPoint(t, this.defaultZoom), this.editor.canvas.fire("editor:zoom-changed", {
|
|
2055
|
-
currentZoom: e.getZoom(),
|
|
2056
|
-
point: t
|
|
2057
|
-
});
|
|
2015
|
+
this.editor = e, this.options = e.options;
|
|
2058
2016
|
}
|
|
2059
2017
|
/**
|
|
2060
2018
|
* Поворот объекта на заданный угол
|
|
@@ -2063,14 +2021,14 @@ class bt {
|
|
|
2063
2021
|
* @param options.withoutSave - Не сохранять состояние
|
|
2064
2022
|
* @fires editor:object-rotated
|
|
2065
2023
|
*/
|
|
2066
|
-
rotate(e =
|
|
2067
|
-
const { canvas: s, historyManager:
|
|
2068
|
-
if (!
|
|
2069
|
-
const
|
|
2070
|
-
|
|
2071
|
-
object:
|
|
2024
|
+
rotate(e = ut, { withoutSave: t } = {}) {
|
|
2025
|
+
const { canvas: s, historyManager: n } = this.editor, o = s.getActiveObject();
|
|
2026
|
+
if (!o) return;
|
|
2027
|
+
const a = o.angle + e;
|
|
2028
|
+
o.rotate(a), o.setCoords(), s.renderAll(), t || n.saveState(), s.fire("editor:object-rotated", {
|
|
2029
|
+
object: o,
|
|
2072
2030
|
withoutSave: t,
|
|
2073
|
-
angle:
|
|
2031
|
+
angle: a
|
|
2074
2032
|
});
|
|
2075
2033
|
}
|
|
2076
2034
|
/**
|
|
@@ -2080,9 +2038,9 @@ class bt {
|
|
|
2080
2038
|
* @fires editor:object-flipped-x
|
|
2081
2039
|
*/
|
|
2082
2040
|
flipX({ withoutSave: e } = {}) {
|
|
2083
|
-
const { canvas: t, historyManager: s } = this.editor,
|
|
2084
|
-
|
|
2085
|
-
object:
|
|
2041
|
+
const { canvas: t, historyManager: s } = this.editor, n = t.getActiveObject();
|
|
2042
|
+
n && (n.flipX = !n.flipX, t.renderAll(), e || s.saveState(), t.fire("editor:object-flipped-x", {
|
|
2043
|
+
object: n,
|
|
2086
2044
|
withoutSave: e
|
|
2087
2045
|
}));
|
|
2088
2046
|
}
|
|
@@ -2093,9 +2051,9 @@ class bt {
|
|
|
2093
2051
|
* @fires editor:object-flipped-y
|
|
2094
2052
|
*/
|
|
2095
2053
|
flipY({ withoutSave: e } = {}) {
|
|
2096
|
-
const { canvas: t, historyManager: s } = this.editor,
|
|
2097
|
-
|
|
2098
|
-
object:
|
|
2054
|
+
const { canvas: t, historyManager: s } = this.editor, n = t.getActiveObject();
|
|
2055
|
+
n && (n.flipY = !n.flipY, t.renderAll(), e || s.saveState(), t.fire("editor:object-flipped-y", {
|
|
2056
|
+
object: n,
|
|
2099
2057
|
withoutSave: e
|
|
2100
2058
|
}));
|
|
2101
2059
|
}
|
|
@@ -2112,11 +2070,11 @@ class bt {
|
|
|
2112
2070
|
opacity: t = 1,
|
|
2113
2071
|
withoutSave: s
|
|
2114
2072
|
} = {}) {
|
|
2115
|
-
const { canvas:
|
|
2116
|
-
|
|
2073
|
+
const { canvas: n, historyManager: o } = this.editor, a = e || n.getActiveObject();
|
|
2074
|
+
a && (a instanceof v ? a.getObjects().forEach((i) => {
|
|
2117
2075
|
i.set("opacity", t);
|
|
2118
|
-
}) :
|
|
2119
|
-
object:
|
|
2076
|
+
}) : a.set("opacity", t), n.renderAll(), s || o.saveState(), n.fire("editor:object-opacity-changed", {
|
|
2077
|
+
object: a,
|
|
2120
2078
|
opacity: t,
|
|
2121
2079
|
withoutSave: s
|
|
2122
2080
|
}));
|
|
@@ -2136,24 +2094,24 @@ class bt {
|
|
|
2136
2094
|
object: e,
|
|
2137
2095
|
type: t = this.options.scaleType,
|
|
2138
2096
|
withoutSave: s,
|
|
2139
|
-
fitAsOneObject:
|
|
2097
|
+
fitAsOneObject: n
|
|
2140
2098
|
} = {}) {
|
|
2141
|
-
const { canvas:
|
|
2099
|
+
const { canvas: o, historyManager: a } = this.editor, i = e || o.getActiveObject();
|
|
2142
2100
|
if (i) {
|
|
2143
|
-
if (i instanceof v && !
|
|
2101
|
+
if (i instanceof v && !n) {
|
|
2144
2102
|
const r = i.getObjects();
|
|
2145
|
-
|
|
2103
|
+
o.discardActiveObject(), r.forEach((h) => {
|
|
2146
2104
|
this._fitSingleObject(h, t);
|
|
2147
2105
|
});
|
|
2148
|
-
const
|
|
2149
|
-
|
|
2106
|
+
const c = new v(r, { canvas: o });
|
|
2107
|
+
o.setActiveObject(c);
|
|
2150
2108
|
} else
|
|
2151
2109
|
this._fitSingleObject(i, t);
|
|
2152
|
-
|
|
2110
|
+
o.renderAll(), s || a.saveState(), o.fire("editor:object-fitted", {
|
|
2153
2111
|
object: i,
|
|
2154
2112
|
type: t,
|
|
2155
2113
|
withoutSave: s,
|
|
2156
|
-
fitAsOneObject:
|
|
2114
|
+
fitAsOneObject: n
|
|
2157
2115
|
});
|
|
2158
2116
|
}
|
|
2159
2117
|
}
|
|
@@ -2164,11 +2122,11 @@ class bt {
|
|
|
2164
2122
|
* @private
|
|
2165
2123
|
*/
|
|
2166
2124
|
_fitSingleObject(e, t) {
|
|
2167
|
-
const { canvas: s, montageArea:
|
|
2168
|
-
let
|
|
2169
|
-
t === "contain" ?
|
|
2170
|
-
scaleX: i *
|
|
2171
|
-
scaleY: r *
|
|
2125
|
+
const { canvas: s, montageArea: n } = this.editor, { width: o, height: a, scaleX: i = 1, scaleY: r = 1, angle: c = 0 } = e, h = o * Math.abs(i), l = a * Math.abs(r), g = c * Math.PI / 180, u = Math.abs(Math.cos(g)), f = Math.abs(Math.sin(g)), M = h * u + l * f, b = h * f + l * u, m = n.width, p = n.height;
|
|
2126
|
+
let D;
|
|
2127
|
+
t === "contain" ? D = Math.min(m / M, p / b) : D = Math.max(m / M, p / b), e.set({
|
|
2128
|
+
scaleX: i * D,
|
|
2129
|
+
scaleY: r * D
|
|
2172
2130
|
}), s.centerObject(e);
|
|
2173
2131
|
}
|
|
2174
2132
|
/**
|
|
@@ -2189,35 +2147,239 @@ class bt {
|
|
|
2189
2147
|
*/
|
|
2190
2148
|
resetObject({ object: e, alwaysFitObject: t = !1, withoutSave: s = !1 } = {}) {
|
|
2191
2149
|
const {
|
|
2192
|
-
canvas:
|
|
2193
|
-
montageArea:
|
|
2194
|
-
imageManager:
|
|
2150
|
+
canvas: n,
|
|
2151
|
+
montageArea: o,
|
|
2152
|
+
imageManager: a,
|
|
2195
2153
|
historyManager: i,
|
|
2196
2154
|
options: { scaleType: r }
|
|
2197
|
-
} = this.editor,
|
|
2198
|
-
if (!
|
|
2199
|
-
if (i.suspendHistory(),
|
|
2155
|
+
} = this.editor, c = e || n.getActiveObject();
|
|
2156
|
+
if (!c || c.locked) return;
|
|
2157
|
+
if (i.suspendHistory(), c.type === "image" || c.format === "svg" || c.set({
|
|
2200
2158
|
scaleX: 1,
|
|
2201
2159
|
scaleY: 1,
|
|
2202
2160
|
flipX: !1,
|
|
2203
2161
|
flipY: !1,
|
|
2204
2162
|
angle: 0
|
|
2205
2163
|
}), t)
|
|
2206
|
-
this.fitObject({ object:
|
|
2164
|
+
this.fitObject({ object: c, withoutSave: !0, fitAsOneObject: !0 });
|
|
2207
2165
|
else {
|
|
2208
|
-
const { width: l, height:
|
|
2209
|
-
imageObject:
|
|
2166
|
+
const { width: l, height: g } = o, { width: u, height: f } = c, M = a.calculateScaleFactor({
|
|
2167
|
+
imageObject: c,
|
|
2210
2168
|
scaleType: r
|
|
2211
2169
|
});
|
|
2212
|
-
r === "contain" &&
|
|
2170
|
+
r === "contain" && M < 1 || r === "cover" && (u > l || f > g) ? this.fitObject({ object: c, withoutSave: !0, fitAsOneObject: !0 }) : c.set({ scaleX: 1, scaleY: 1 });
|
|
2213
2171
|
}
|
|
2214
|
-
|
|
2215
|
-
object:
|
|
2172
|
+
c.set({ flipX: !1, flipY: !1, angle: 0 }), n.centerObject(c), n.renderAll(), i.resumeHistory(), s || i.saveState(), n.fire("editor:object-reset", {
|
|
2173
|
+
object: c,
|
|
2216
2174
|
withoutSave: s,
|
|
2217
2175
|
alwaysFitObject: t
|
|
2218
2176
|
});
|
|
2219
2177
|
}
|
|
2220
2178
|
}
|
|
2179
|
+
class bt {
|
|
2180
|
+
constructor({ editor: e }) {
|
|
2181
|
+
this.editor = e, this.options = e.options, this.minZoom = this.options.minZoom || ht, this.maxZoom = this.options.maxZoom || gt, this.defaultZoom = this.options.defaultScale;
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* Вспомогательный метод для вычисления размеров масштабированной монтажной области
|
|
2185
|
+
* @param zoom - Масштаб для расчета
|
|
2186
|
+
* @returns Размеры масштабированной монтажной области
|
|
2187
|
+
* @private
|
|
2188
|
+
*/
|
|
2189
|
+
_getScaledMontageDimensions(e) {
|
|
2190
|
+
const { montageArea: t } = this.editor;
|
|
2191
|
+
return {
|
|
2192
|
+
width: t.width * e,
|
|
2193
|
+
height: t.height * e
|
|
2194
|
+
};
|
|
2195
|
+
}
|
|
2196
|
+
/**
|
|
2197
|
+
* Ограничивает координаты курсора видимыми границами монтажной области
|
|
2198
|
+
* @param event - Событие колеса мыши
|
|
2199
|
+
* @returns Ограниченные координаты в canvas-пространстве
|
|
2200
|
+
* @private
|
|
2201
|
+
*/
|
|
2202
|
+
_getClampedPointerCoordinates(e) {
|
|
2203
|
+
const { canvas: t, montageArea: s } = this.editor, n = t.getPointer(e, !0), o = t.viewportTransform, a = t.getZoom(), i = s.left - s.width / 2, r = s.left + s.width / 2, c = s.top - s.height / 2, h = s.top + s.height / 2, l = i * a + o[4], g = r * a + o[4], u = c * a + o[5], f = h * a + o[5], M = Math.max(l, Math.min(g, n.x)), b = Math.max(u, Math.min(f, n.y));
|
|
2204
|
+
return {
|
|
2205
|
+
x: M,
|
|
2206
|
+
y: b
|
|
2207
|
+
};
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* Вычисляет зум при котором монтажная область точно помещается в viewport
|
|
2211
|
+
* @returns Минимальный зум для полного размещения монтажной области
|
|
2212
|
+
* @private
|
|
2213
|
+
*/
|
|
2214
|
+
_calculateFitZoom() {
|
|
2215
|
+
const { canvas: e, montageArea: t } = this.editor, s = e.getWidth(), n = e.getHeight(), o = s / t.width, a = n / t.height;
|
|
2216
|
+
return Math.max(o, a);
|
|
2217
|
+
}
|
|
2218
|
+
/**
|
|
2219
|
+
* Вычисляет целевую позицию viewport для центрирования монтажной области
|
|
2220
|
+
* @param zoom - Текущий зум
|
|
2221
|
+
* @returns Целевые координаты viewport transform
|
|
2222
|
+
* @private
|
|
2223
|
+
*/
|
|
2224
|
+
_calculateTargetViewportPosition(e) {
|
|
2225
|
+
const { canvas: t, montageArea: s } = this.editor, n = t.getWidth(), o = t.getHeight(), a = n / 2, i = o / 2, r = s.left, c = s.top;
|
|
2226
|
+
return {
|
|
2227
|
+
x: a - r * e,
|
|
2228
|
+
y: i - c * e
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
/**
|
|
2232
|
+
* Проверяет наличие пустого пространства вокруг монтажной области
|
|
2233
|
+
* @param zoom - Текущий зум
|
|
2234
|
+
* @returns Максимальное соотношение пустого пространства к размеру viewport
|
|
2235
|
+
* @private
|
|
2236
|
+
*/
|
|
2237
|
+
_calculateEmptySpaceRatio(e) {
|
|
2238
|
+
const { canvas: t, montageArea: s } = this.editor, n = t.viewportTransform, o = t.getWidth(), a = t.getHeight(), i = s.left - s.width / 2, r = s.left + s.width / 2, c = s.top - s.height / 2, h = s.top + s.height / 2, l = -n[4] / e, g = (-n[4] + o) / e, u = -n[5] / e, f = (-n[5] + a) / e, M = l < i, b = g > r, m = u < c, p = f > h;
|
|
2239
|
+
if (!(M || b || m || p)) return 0;
|
|
2240
|
+
const w = Math.max(0, i - l), T = Math.max(0, g - r), A = Math.max(0, c - u), S = Math.max(0, f - h), L = Math.max(w, T), O = Math.max(A, S), j = L / o, E = O / a;
|
|
2241
|
+
return Math.max(j, E);
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Вычисляет плавный шаг перемещения viewport к центру с ускорением
|
|
2245
|
+
* @param targetVpt - Целевая позиция viewport
|
|
2246
|
+
* @param zoom - Текущий зум
|
|
2247
|
+
* @param fitZoom - Зум при котором монтажная область помещается в viewport
|
|
2248
|
+
* @param zoomStep - Шаг изменения зума
|
|
2249
|
+
* @param maxEmptyRatio - Максимальная доля пустого пространства
|
|
2250
|
+
* @returns Вычисленный шаг перемещения viewport
|
|
2251
|
+
* @private
|
|
2252
|
+
*/
|
|
2253
|
+
_calculateSmoothCenteringStep(e, t, s, n, o) {
|
|
2254
|
+
const { canvas: a, montageArea: i } = this.editor, r = a.viewportTransform, c = a.getWidth(), h = a.getHeight(), l = e.x - r[4], g = e.y - r[5], u = Math.abs(n), f = t - s;
|
|
2255
|
+
if (Math.abs(f) / u <= 0.1)
|
|
2256
|
+
return { x: l, y: g };
|
|
2257
|
+
const b = c / 2, m = h / 2, p = i.left, D = i.top, w = b - p * s, T = m - D * s, A = (w - r[4]) / (t - s), S = (T - r[5]) / (t - s), L = A * u, O = S * u, j = L * o, E = O * o, N = Math.abs(j) > Math.abs(l) ? l : j, te = Math.abs(E) > Math.abs(g) ? g : E;
|
|
2258
|
+
return { x: N, y: te };
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Применяет плавное центрирование viewport при приближении к defaultZoom.
|
|
2262
|
+
* При zoom <= defaultZoom монтажная область полностью центрируется.
|
|
2263
|
+
* При zoom > defaultZoom применяется плавная интерполяция в пределах переходного диапазона.
|
|
2264
|
+
* @param zoom - Текущий зум
|
|
2265
|
+
* @param isZoomingOut - Флаг, указывающий что происходит zoom-out (уменьшение масштаба)
|
|
2266
|
+
* @param zoomStep - Шаг зума (адаптивно рассчитанный)
|
|
2267
|
+
* @returns true если центрирование было применено
|
|
2268
|
+
* @private
|
|
2269
|
+
*/
|
|
2270
|
+
_applyViewportCentering(e, t = !1, s = Se) {
|
|
2271
|
+
const { canvas: n } = this.editor, o = this._getScaledMontageDimensions(e), a = n.getWidth(), i = n.getHeight(), r = o.width > a || o.height > i, c = this._calculateFitZoom(), h = e - c;
|
|
2272
|
+
if (!(!r || h) && !t)
|
|
2273
|
+
return !1;
|
|
2274
|
+
const g = n.viewportTransform, u = this._calculateTargetViewportPosition(e);
|
|
2275
|
+
if (!r)
|
|
2276
|
+
return g[4] = u.x, g[5] = u.y, n.setViewportTransform(g), !0;
|
|
2277
|
+
if (t && !r) {
|
|
2278
|
+
const f = this._calculateEmptySpaceRatio(e);
|
|
2279
|
+
if (f > 0) {
|
|
2280
|
+
const M = this._calculateSmoothCenteringStep(u, e, c, s, f);
|
|
2281
|
+
return g[4] += M.x, g[5] += M.y, n.setViewportTransform(g), !0;
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
return !1;
|
|
2285
|
+
}
|
|
2286
|
+
/**
|
|
2287
|
+
* Метод рассчитывает и применяет зум по умолчанию для монтажной области редактора.
|
|
2288
|
+
* Зум рассчитывается исходя из размеров контейнера редактора и текущих размеров монтажной области.
|
|
2289
|
+
* Расчёт происходит таким образом, чтобы монтажная область визуально целиком помещалась в контейнер редактора.
|
|
2290
|
+
* Если scale не передан, то используется значение из options.defaultScale.
|
|
2291
|
+
* @param scale - Желаемый масштаб относительно размеров контейнера редактора.
|
|
2292
|
+
*/
|
|
2293
|
+
calculateAndApplyDefaultZoom(e = this.options.defaultScale) {
|
|
2294
|
+
const { canvas: t } = this.editor, s = t.editorContainer, n = s.clientWidth || t.getWidth(), o = s.clientHeight || t.getHeight(), { width: a, height: i } = this.editor.montageArea, r = n / a * e, c = o / i * e;
|
|
2295
|
+
this.defaultZoom = Math.min(r, c), this.setZoom(), this.editor.panConstraintManager.updateBounds();
|
|
2296
|
+
}
|
|
2297
|
+
/**
|
|
2298
|
+
* Обработчик зума колесом мыши с автоматическим определением точки зума.
|
|
2299
|
+
* Логика выбора точки зума:
|
|
2300
|
+
* - При zoom-out (уменьшении): зум к текущему центру монтажной области
|
|
2301
|
+
* - При zoom-in (увеличении): зум к позиции курсора (ограниченной границами монтажной области)
|
|
2302
|
+
* - Если zoom < defaultZoom или монтажная область помещается во viewport - зум к центру монтажной области
|
|
2303
|
+
* @param scale - Шаг зума
|
|
2304
|
+
* @param event - Событие колеса мыши
|
|
2305
|
+
* @fires editor:zoom-changed
|
|
2306
|
+
*/
|
|
2307
|
+
handleMouseWheelZoom(e, t) {
|
|
2308
|
+
const { canvas: s, montageArea: n } = this.editor, o = s.getZoom(), a = e < 0, i = this._getScaledMontageDimensions(o), r = s.getWidth(), c = s.getHeight(), h = i.width > r || i.height > c;
|
|
2309
|
+
if (a) {
|
|
2310
|
+
if (!h)
|
|
2311
|
+
this.zoom(e, {
|
|
2312
|
+
pointX: n.left,
|
|
2313
|
+
pointY: n.top
|
|
2314
|
+
});
|
|
2315
|
+
else {
|
|
2316
|
+
const g = this._getClampedPointerCoordinates(t);
|
|
2317
|
+
this.zoom(e, {
|
|
2318
|
+
pointX: g.x,
|
|
2319
|
+
pointY: g.y
|
|
2320
|
+
});
|
|
2321
|
+
}
|
|
2322
|
+
return;
|
|
2323
|
+
}
|
|
2324
|
+
if (e < 0 || !h) {
|
|
2325
|
+
this.zoom(e, {
|
|
2326
|
+
pointX: n.left,
|
|
2327
|
+
pointY: n.top
|
|
2328
|
+
});
|
|
2329
|
+
return;
|
|
2330
|
+
}
|
|
2331
|
+
const l = this._getClampedPointerCoordinates(t);
|
|
2332
|
+
this.zoom(e, {
|
|
2333
|
+
pointX: l.x,
|
|
2334
|
+
pointY: l.y
|
|
2335
|
+
});
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Увеличение/уменьшение масштаба
|
|
2339
|
+
* @param scale - Шаг зума
|
|
2340
|
+
* @param options - Координаты зума (по умолчанию центр канваса)
|
|
2341
|
+
* @param options.pointX - Координата X точки зума
|
|
2342
|
+
* @param options.pointY - Координата Y точки зума
|
|
2343
|
+
* @fires editor:zoom-changed
|
|
2344
|
+
*/
|
|
2345
|
+
zoom(e = Se, t = {}) {
|
|
2346
|
+
var u, f;
|
|
2347
|
+
if (!e) return;
|
|
2348
|
+
const { minZoom: s, maxZoom: n } = this, { canvas: o } = this.editor, a = e < 0, i = o.getZoom(), r = o.getCenterPoint(), c = (u = t.pointX) != null ? u : r.x, h = (f = t.pointY) != null ? f : r.y, l = new $(c, h);
|
|
2349
|
+
this.editor.montageArea.setCoords(), this.editor.canvas.requestRenderAll();
|
|
2350
|
+
let g = Number((i + Number(e)).toFixed(3));
|
|
2351
|
+
g > n && (g = n), g < s && (g = s), o.zoomToPoint(l, g), this.editor.panConstraintManager.updateBounds(), this._applyViewportCentering(g, a, e), o.fire("editor:zoom-changed", {
|
|
2352
|
+
currentZoom: o.getZoom(),
|
|
2353
|
+
zoom: g,
|
|
2354
|
+
point: l
|
|
2355
|
+
});
|
|
2356
|
+
}
|
|
2357
|
+
/**
|
|
2358
|
+
* Установка зума
|
|
2359
|
+
* @param zoom - Зум
|
|
2360
|
+
* @fires editor:zoom-changed
|
|
2361
|
+
*/
|
|
2362
|
+
setZoom(e = this.defaultZoom) {
|
|
2363
|
+
const { minZoom: t, maxZoom: s } = this, { canvas: n } = this.editor, o = new $(n.getCenterPoint());
|
|
2364
|
+
let a = e;
|
|
2365
|
+
e > s && (a = s), e < t && (a = t), n.zoomToPoint(o, a), n.fire("editor:zoom-changed", {
|
|
2366
|
+
currentZoom: n.getZoom(),
|
|
2367
|
+
zoom: a,
|
|
2368
|
+
point: o
|
|
2369
|
+
}), this.editor.panConstraintManager.updateBounds();
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Сброс зума
|
|
2373
|
+
* @fires editor:zoom-changed
|
|
2374
|
+
*/
|
|
2375
|
+
resetZoom() {
|
|
2376
|
+
const { canvas: e } = this.editor, t = new $(e.getCenterPoint());
|
|
2377
|
+
e.zoomToPoint(t, this.defaultZoom), this.editor.canvas.fire("editor:zoom-changed", {
|
|
2378
|
+
currentZoom: e.getZoom(),
|
|
2379
|
+
point: t
|
|
2380
|
+
}), this.editor.panConstraintManager.updateBounds();
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2221
2383
|
class jt {
|
|
2222
2384
|
constructor({ editor: e }) {
|
|
2223
2385
|
this.editor = e, this.isBlocked = !1, this.overlayMask = null, this._createOverlay();
|
|
@@ -2248,8 +2410,8 @@ class jt {
|
|
|
2248
2410
|
const { canvas: e, montageArea: t, historyManager: s } = this.editor;
|
|
2249
2411
|
if (!t || !this.overlayMask) return;
|
|
2250
2412
|
s.suspendHistory(), t.setCoords();
|
|
2251
|
-
const { left:
|
|
2252
|
-
this.overlayMask.set({ left:
|
|
2413
|
+
const { left: n, top: o, width: a, height: i } = t.getBoundingRect();
|
|
2414
|
+
this.overlayMask.set({ left: n, top: o, width: a, height: i }), e.discardActiveObject(), this.editor.layerManager.bringToFront(this.overlayMask, { withoutSave: !0 }), s.resumeHistory();
|
|
2253
2415
|
}
|
|
2254
2416
|
/**
|
|
2255
2417
|
* Выключает редактор:
|
|
@@ -2260,8 +2422,8 @@ class jt {
|
|
|
2260
2422
|
block() {
|
|
2261
2423
|
if (this.isBlocked || !this.overlayMask) return;
|
|
2262
2424
|
const { canvas: e, canvasManager: t, historyManager: s } = this.editor;
|
|
2263
|
-
s.suspendHistory(), this.isBlocked = !0, e.discardActiveObject(), e.selection = !1, e.skipTargetFind = !0, t.getObjects().forEach((
|
|
2264
|
-
|
|
2425
|
+
s.suspendHistory(), this.isBlocked = !0, e.discardActiveObject(), e.selection = !1, e.skipTargetFind = !0, t.getObjects().forEach((n) => {
|
|
2426
|
+
n.evented = !1, n.selectable = !1;
|
|
2265
2427
|
}), e.upperCanvasEl.style.pointerEvents = "none", e.lowerCanvasEl.style.pointerEvents = "none", this.overlayMask.visible = !0, this.refresh(), e.fire("editor:disabled"), s.resumeHistory();
|
|
2266
2428
|
}
|
|
2267
2429
|
/**
|
|
@@ -2270,12 +2432,12 @@ class jt {
|
|
|
2270
2432
|
unblock() {
|
|
2271
2433
|
if (!this.isBlocked || !this.overlayMask) return;
|
|
2272
2434
|
const { canvas: e, canvasManager: t, historyManager: s } = this.editor;
|
|
2273
|
-
s.suspendHistory(), this.isBlocked = !1, e.selection = !0, e.skipTargetFind = !1, t.getObjects().forEach((
|
|
2274
|
-
|
|
2435
|
+
s.suspendHistory(), this.isBlocked = !1, e.selection = !0, e.skipTargetFind = !1, t.getObjects().forEach((n) => {
|
|
2436
|
+
n.evented = !0, n.selectable = !0;
|
|
2275
2437
|
}), e.upperCanvasEl.style.pointerEvents = "", e.lowerCanvasEl.style.pointerEvents = "", this.overlayMask.visible = !1, e.requestRenderAll(), e.fire("editor:enabled"), s.resumeHistory();
|
|
2276
2438
|
}
|
|
2277
2439
|
}
|
|
2278
|
-
class
|
|
2440
|
+
class Y {
|
|
2279
2441
|
constructor({ editor: e }) {
|
|
2280
2442
|
this.editor = e, this.backgroundObject = null;
|
|
2281
2443
|
}
|
|
@@ -2290,28 +2452,28 @@ class R {
|
|
|
2290
2452
|
customData: t = {},
|
|
2291
2453
|
withoutSave: s = !1
|
|
2292
2454
|
}) {
|
|
2293
|
-
var
|
|
2455
|
+
var n;
|
|
2294
2456
|
try {
|
|
2295
|
-
const { historyManager:
|
|
2296
|
-
if (
|
|
2297
|
-
if (
|
|
2298
|
-
|
|
2457
|
+
const { historyManager: o } = this.editor, { backgroundObject: a } = this;
|
|
2458
|
+
if (o.suspendHistory(), a && a.backgroundType === "color") {
|
|
2459
|
+
if (a.fill === e) {
|
|
2460
|
+
o.resumeHistory();
|
|
2299
2461
|
return;
|
|
2300
2462
|
}
|
|
2301
|
-
|
|
2463
|
+
a.set({
|
|
2302
2464
|
fill: e,
|
|
2303
|
-
backgroundId: `background-${
|
|
2465
|
+
backgroundId: `background-${C()}`
|
|
2304
2466
|
}), this.editor.canvas.requestRenderAll();
|
|
2305
2467
|
} else
|
|
2306
2468
|
this._removeCurrentBackground(), this._createColorBackground(e);
|
|
2307
|
-
(
|
|
2308
|
-
} catch (
|
|
2469
|
+
(n = this.backgroundObject) == null || n.set({ customData: t }), this.editor.canvas.fire("editor:background:changed", { type: "color", color: e }), o.resumeHistory(), s || o.saveState();
|
|
2470
|
+
} catch (o) {
|
|
2309
2471
|
this.editor.errorManager.emitError({
|
|
2310
2472
|
code: "BACKGROUND_CREATION_FAILED",
|
|
2311
2473
|
origin: "BackgroundManager",
|
|
2312
2474
|
method: "setColorBackground",
|
|
2313
2475
|
message: "Не удалось установить цветовой фон",
|
|
2314
|
-
data: { error:
|
|
2476
|
+
data: { error: o }
|
|
2315
2477
|
});
|
|
2316
2478
|
}
|
|
2317
2479
|
}
|
|
@@ -2326,32 +2488,32 @@ class R {
|
|
|
2326
2488
|
customData: t = {},
|
|
2327
2489
|
withoutSave: s = !1
|
|
2328
2490
|
}) {
|
|
2329
|
-
var
|
|
2491
|
+
var n;
|
|
2330
2492
|
try {
|
|
2331
|
-
const { historyManager:
|
|
2332
|
-
if (
|
|
2333
|
-
const i =
|
|
2334
|
-
if (
|
|
2335
|
-
|
|
2493
|
+
const { historyManager: o } = this.editor, { backgroundObject: a } = this;
|
|
2494
|
+
if (o.suspendHistory(), a && a.backgroundType === "gradient") {
|
|
2495
|
+
const i = Y._createFabricGradient(e);
|
|
2496
|
+
if (Y._isGradientEqual(a.fill, i)) {
|
|
2497
|
+
o.resumeHistory();
|
|
2336
2498
|
return;
|
|
2337
2499
|
}
|
|
2338
|
-
|
|
2500
|
+
a.set({
|
|
2339
2501
|
fill: i,
|
|
2340
|
-
backgroundId: `background-${
|
|
2502
|
+
backgroundId: `background-${C()}`
|
|
2341
2503
|
}), this.editor.canvas.requestRenderAll();
|
|
2342
2504
|
} else
|
|
2343
2505
|
this._removeCurrentBackground(), this._createGradientBackground(e);
|
|
2344
|
-
(
|
|
2506
|
+
(n = this.backgroundObject) == null || n.set({ customData: t }), this.editor.canvas.fire("editor:background:changed", {
|
|
2345
2507
|
type: "gradient",
|
|
2346
2508
|
gradientParams: e
|
|
2347
|
-
}),
|
|
2348
|
-
} catch (
|
|
2509
|
+
}), o.resumeHistory(), s || o.saveState();
|
|
2510
|
+
} catch (o) {
|
|
2349
2511
|
this.editor.errorManager.emitError({
|
|
2350
2512
|
code: "BACKGROUND_CREATION_FAILED",
|
|
2351
2513
|
origin: "BackgroundManager",
|
|
2352
2514
|
method: "setGradientBackground",
|
|
2353
2515
|
message: "Не удалось установить градиентный фон",
|
|
2354
|
-
data: { error:
|
|
2516
|
+
data: { error: o }
|
|
2355
2517
|
});
|
|
2356
2518
|
}
|
|
2357
2519
|
}
|
|
@@ -2363,9 +2525,9 @@ class R {
|
|
|
2363
2525
|
angle: e,
|
|
2364
2526
|
startColor: t,
|
|
2365
2527
|
endColor: s,
|
|
2366
|
-
startPosition:
|
|
2367
|
-
endPosition:
|
|
2368
|
-
customData:
|
|
2528
|
+
startPosition: n,
|
|
2529
|
+
endPosition: o,
|
|
2530
|
+
customData: a = {},
|
|
2369
2531
|
withoutSave: i = !1
|
|
2370
2532
|
}) {
|
|
2371
2533
|
this.setGradientBackground({
|
|
@@ -2374,10 +2536,10 @@ class R {
|
|
|
2374
2536
|
angle: e,
|
|
2375
2537
|
startColor: t,
|
|
2376
2538
|
endColor: s,
|
|
2377
|
-
startPosition:
|
|
2378
|
-
endPosition:
|
|
2539
|
+
startPosition: n,
|
|
2540
|
+
endPosition: o
|
|
2379
2541
|
},
|
|
2380
|
-
customData:
|
|
2542
|
+
customData: a,
|
|
2381
2543
|
withoutSave: i
|
|
2382
2544
|
});
|
|
2383
2545
|
}
|
|
@@ -2389,12 +2551,12 @@ class R {
|
|
|
2389
2551
|
centerX: e,
|
|
2390
2552
|
centerY: t,
|
|
2391
2553
|
radius: s,
|
|
2392
|
-
startColor:
|
|
2393
|
-
endColor:
|
|
2394
|
-
startPosition:
|
|
2554
|
+
startColor: n,
|
|
2555
|
+
endColor: o,
|
|
2556
|
+
startPosition: a,
|
|
2395
2557
|
endPosition: i,
|
|
2396
2558
|
customData: r = {},
|
|
2397
|
-
withoutSave:
|
|
2559
|
+
withoutSave: c = !1
|
|
2398
2560
|
}) {
|
|
2399
2561
|
this.setGradientBackground({
|
|
2400
2562
|
gradient: {
|
|
@@ -2402,13 +2564,13 @@ class R {
|
|
|
2402
2564
|
centerX: e,
|
|
2403
2565
|
centerY: t,
|
|
2404
2566
|
radius: s,
|
|
2405
|
-
startColor:
|
|
2406
|
-
endColor:
|
|
2407
|
-
startPosition:
|
|
2567
|
+
startColor: n,
|
|
2568
|
+
endColor: o,
|
|
2569
|
+
startPosition: a,
|
|
2408
2570
|
endPosition: i
|
|
2409
2571
|
},
|
|
2410
2572
|
customData: r,
|
|
2411
|
-
withoutSave:
|
|
2573
|
+
withoutSave: c
|
|
2412
2574
|
});
|
|
2413
2575
|
}
|
|
2414
2576
|
/**
|
|
@@ -2417,26 +2579,26 @@ class R {
|
|
|
2417
2579
|
* @param options.imageUrl - URL изображения
|
|
2418
2580
|
* @param options.withoutSave - Если true, не сохранять состояние в историю
|
|
2419
2581
|
*/
|
|
2420
|
-
setImageBackground(
|
|
2421
|
-
return
|
|
2582
|
+
setImageBackground(n) {
|
|
2583
|
+
return y(this, arguments, function* ({
|
|
2422
2584
|
imageSource: e,
|
|
2423
2585
|
customData: t = {},
|
|
2424
2586
|
withoutSave: s = !1
|
|
2425
2587
|
}) {
|
|
2426
2588
|
try {
|
|
2427
|
-
const { historyManager:
|
|
2428
|
-
|
|
2589
|
+
const { historyManager: o } = this.editor;
|
|
2590
|
+
o.suspendHistory(), yield this._createImageBackground(e, t), this.editor.canvas.fire("editor:background:changed", {
|
|
2429
2591
|
type: "image",
|
|
2430
2592
|
imageSource: e,
|
|
2431
2593
|
backgroundObject: this.backgroundObject
|
|
2432
|
-
}),
|
|
2433
|
-
} catch (
|
|
2594
|
+
}), o.resumeHistory(), s || o.saveState();
|
|
2595
|
+
} catch (o) {
|
|
2434
2596
|
this.editor.errorManager.emitError({
|
|
2435
2597
|
code: "BACKGROUND_CREATION_FAILED",
|
|
2436
2598
|
origin: "BackgroundManager",
|
|
2437
2599
|
method: "setImageBackground",
|
|
2438
2600
|
message: "Не удалось установить изображение в качестве фона",
|
|
2439
|
-
data: { error:
|
|
2601
|
+
data: { error: o }
|
|
2440
2602
|
});
|
|
2441
2603
|
}
|
|
2442
2604
|
});
|
|
@@ -2468,8 +2630,8 @@ class R {
|
|
|
2468
2630
|
const { canvas: e, montageArea: t, historyManager: s } = this.editor;
|
|
2469
2631
|
if (!t || !this.backgroundObject) return;
|
|
2470
2632
|
s.suspendHistory(), this.editor.transformManager.fitObject({ object: this.backgroundObject, withoutSave: !0, type: "cover" });
|
|
2471
|
-
const
|
|
2472
|
-
this.backgroundObject &&
|
|
2633
|
+
const n = e.getObjects(), o = n.indexOf(t), a = n.indexOf(this.backgroundObject);
|
|
2634
|
+
this.backgroundObject && a !== o + 1 && e.moveObjectTo(this.backgroundObject, o + 1), e.requestRenderAll(), s.resumeHistory();
|
|
2473
2635
|
}
|
|
2474
2636
|
/**
|
|
2475
2637
|
* Создает цветовой фон.
|
|
@@ -2484,7 +2646,7 @@ class R {
|
|
|
2484
2646
|
hasControls: !1,
|
|
2485
2647
|
id: "background",
|
|
2486
2648
|
backgroundType: "color",
|
|
2487
|
-
backgroundId: `background-${
|
|
2649
|
+
backgroundId: `background-${C()}`
|
|
2488
2650
|
}, { withoutSelection: !0 }), this.refresh();
|
|
2489
2651
|
}
|
|
2490
2652
|
/**
|
|
@@ -2501,9 +2663,9 @@ class R {
|
|
|
2501
2663
|
hasControls: !1,
|
|
2502
2664
|
id: "background",
|
|
2503
2665
|
backgroundType: "gradient",
|
|
2504
|
-
backgroundId: `background-${
|
|
2666
|
+
backgroundId: `background-${C()}`
|
|
2505
2667
|
}, { withoutSelection: !0 }), this.refresh();
|
|
2506
|
-
const t =
|
|
2668
|
+
const t = Y._createFabricGradient(e);
|
|
2507
2669
|
this.backgroundObject.set("fill", t), this.editor.canvas.requestRenderAll();
|
|
2508
2670
|
}
|
|
2509
2671
|
/**
|
|
@@ -2511,15 +2673,15 @@ class R {
|
|
|
2511
2673
|
* @param source - источник изображения (URL или File)
|
|
2512
2674
|
*/
|
|
2513
2675
|
_createImageBackground(e, t) {
|
|
2514
|
-
return
|
|
2515
|
-
var
|
|
2516
|
-
const { image: s } = (
|
|
2676
|
+
return y(this, null, function* () {
|
|
2677
|
+
var n;
|
|
2678
|
+
const { image: s } = (n = yield this.editor.imageManager.importImage({
|
|
2517
2679
|
source: e,
|
|
2518
2680
|
withoutSave: !0,
|
|
2519
2681
|
isBackground: !0,
|
|
2520
2682
|
withoutSelection: !0,
|
|
2521
2683
|
scale: "image-cover"
|
|
2522
|
-
})) != null ?
|
|
2684
|
+
})) != null ? n : {};
|
|
2523
2685
|
if (!s)
|
|
2524
2686
|
throw new Error("Не удалось загрузить изображение");
|
|
2525
2687
|
s.set({
|
|
@@ -2529,7 +2691,7 @@ class R {
|
|
|
2529
2691
|
hasControls: !1,
|
|
2530
2692
|
id: "background",
|
|
2531
2693
|
backgroundType: "image",
|
|
2532
|
-
backgroundId: `background-${
|
|
2694
|
+
backgroundId: `background-${C()}`,
|
|
2533
2695
|
customData: t
|
|
2534
2696
|
}), this._removeCurrentBackground(), this.backgroundObject = s, this.refresh();
|
|
2535
2697
|
});
|
|
@@ -2548,38 +2710,38 @@ class R {
|
|
|
2548
2710
|
const {
|
|
2549
2711
|
startColor: t,
|
|
2550
2712
|
endColor: s,
|
|
2551
|
-
startPosition:
|
|
2552
|
-
endPosition:
|
|
2553
|
-
} = e,
|
|
2554
|
-
{ offset:
|
|
2555
|
-
{ offset:
|
|
2713
|
+
startPosition: n = 0,
|
|
2714
|
+
endPosition: o = 100
|
|
2715
|
+
} = e, a = [
|
|
2716
|
+
{ offset: n / 100, color: t },
|
|
2717
|
+
{ offset: o / 100, color: s }
|
|
2556
2718
|
];
|
|
2557
2719
|
if (e.type === "linear") {
|
|
2558
|
-
const l = e.angle * Math.PI / 180,
|
|
2559
|
-
return new
|
|
2720
|
+
const l = e.angle * Math.PI / 180, g = Y._angleToCoords(l);
|
|
2721
|
+
return new ye({
|
|
2560
2722
|
type: "linear",
|
|
2561
2723
|
gradientUnits: "percentage",
|
|
2562
|
-
coords:
|
|
2563
|
-
colorStops:
|
|
2724
|
+
coords: g,
|
|
2725
|
+
colorStops: a
|
|
2564
2726
|
});
|
|
2565
2727
|
}
|
|
2566
2728
|
const {
|
|
2567
2729
|
centerX: i = 50,
|
|
2568
2730
|
centerY: r = 50,
|
|
2569
|
-
radius:
|
|
2731
|
+
radius: c = 50
|
|
2570
2732
|
} = e, h = {
|
|
2571
2733
|
x1: i / 100,
|
|
2572
2734
|
y1: r / 100,
|
|
2573
2735
|
x2: i / 100,
|
|
2574
2736
|
y2: r / 100,
|
|
2575
2737
|
r1: 0,
|
|
2576
|
-
r2:
|
|
2738
|
+
r2: c / 100
|
|
2577
2739
|
};
|
|
2578
|
-
return new
|
|
2740
|
+
return new ye({
|
|
2579
2741
|
type: "radial",
|
|
2580
2742
|
gradientUnits: "percentage",
|
|
2581
2743
|
coords: h,
|
|
2582
|
-
colorStops:
|
|
2744
|
+
colorStops: a
|
|
2583
2745
|
});
|
|
2584
2746
|
}
|
|
2585
2747
|
/**
|
|
@@ -2603,14 +2765,14 @@ class R {
|
|
|
2603
2765
|
*/
|
|
2604
2766
|
static _isGradientEqual(e, t) {
|
|
2605
2767
|
if (!e || !t || e.type !== t.type) return !1;
|
|
2606
|
-
const s = e.colorStops || [],
|
|
2607
|
-
return s.length !==
|
|
2608
|
-
const r =
|
|
2609
|
-
return
|
|
2768
|
+
const s = e.colorStops || [], n = t.colorStops || [];
|
|
2769
|
+
return s.length !== n.length || !s.every((a, i) => {
|
|
2770
|
+
const r = n[i];
|
|
2771
|
+
return a.color === r.color && Math.abs(a.offset - r.offset) < 1e-4;
|
|
2610
2772
|
}) ? !1 : e.type === "linear" && t.type === "linear" ? Math.abs(e.coords.x1 - t.coords.x1) < 1e-4 && Math.abs(e.coords.y1 - t.coords.y1) < 1e-4 && Math.abs(e.coords.x2 - t.coords.x2) < 1e-4 && Math.abs(e.coords.y2 - t.coords.y2) < 1e-4 : e.type === "radial" && t.type === "radial" ? Math.abs(e.coords.x1 - t.coords.x1) < 1e-4 && Math.abs(e.coords.y1 - t.coords.y1) < 1e-4 && Math.abs(e.coords.x2 - t.coords.x2) < 1e-4 && Math.abs(e.coords.y2 - t.coords.y2) < 1e-4 && Math.abs(e.coords.r1 - t.coords.r1) < 1e-4 && Math.abs(e.coords.r2 - t.coords.r2) < 1e-4 : !1;
|
|
2611
2773
|
}
|
|
2612
2774
|
}
|
|
2613
|
-
class
|
|
2775
|
+
class J {
|
|
2614
2776
|
constructor({ editor: e }) {
|
|
2615
2777
|
this.editor = e;
|
|
2616
2778
|
}
|
|
@@ -2622,13 +2784,13 @@ class K {
|
|
|
2622
2784
|
* @fires editor:object-bring-to-front
|
|
2623
2785
|
*/
|
|
2624
2786
|
bringToFront(e, { withoutSave: t } = {}) {
|
|
2625
|
-
const { canvas: s, historyManager:
|
|
2626
|
-
|
|
2627
|
-
const
|
|
2628
|
-
|
|
2629
|
-
s.bringObjectToFront(
|
|
2630
|
-
}) : s.bringObjectToFront(
|
|
2631
|
-
object:
|
|
2787
|
+
const { canvas: s, historyManager: n } = this.editor;
|
|
2788
|
+
n.suspendHistory();
|
|
2789
|
+
const o = e || s.getActiveObject();
|
|
2790
|
+
o && (o instanceof v ? o.getObjects().forEach((a) => {
|
|
2791
|
+
s.bringObjectToFront(a);
|
|
2792
|
+
}) : s.bringObjectToFront(o), s.renderAll(), n.resumeHistory(), t || n.saveState(), s.fire("editor:object-bring-to-front", {
|
|
2793
|
+
object: o,
|
|
2632
2794
|
withoutSave: t
|
|
2633
2795
|
}));
|
|
2634
2796
|
}
|
|
@@ -2640,11 +2802,11 @@ class K {
|
|
|
2640
2802
|
* @fires editor:object-bring-forward
|
|
2641
2803
|
*/
|
|
2642
2804
|
bringForward(e, { withoutSave: t } = {}) {
|
|
2643
|
-
const { canvas: s, historyManager:
|
|
2644
|
-
|
|
2645
|
-
const
|
|
2646
|
-
|
|
2647
|
-
object:
|
|
2805
|
+
const { canvas: s, historyManager: n } = this.editor;
|
|
2806
|
+
n.suspendHistory();
|
|
2807
|
+
const o = e || s.getActiveObject();
|
|
2808
|
+
o && (o instanceof v ? J._moveSelectionForward(s, o) : s.bringObjectForward(o), s.renderAll(), n.resumeHistory(), t || n.saveState(), s.fire("editor:object-bring-forward", {
|
|
2809
|
+
object: o,
|
|
2648
2810
|
withoutSave: t
|
|
2649
2811
|
}));
|
|
2650
2812
|
}
|
|
@@ -2658,21 +2820,21 @@ class K {
|
|
|
2658
2820
|
sendToBack(e, { withoutSave: t } = {}) {
|
|
2659
2821
|
const {
|
|
2660
2822
|
canvas: s,
|
|
2661
|
-
montageArea:
|
|
2662
|
-
historyManager:
|
|
2663
|
-
interactionBlocker: { overlayMask:
|
|
2823
|
+
montageArea: n,
|
|
2824
|
+
historyManager: o,
|
|
2825
|
+
interactionBlocker: { overlayMask: a },
|
|
2664
2826
|
backgroundManager: { backgroundObject: i }
|
|
2665
2827
|
} = this.editor;
|
|
2666
|
-
|
|
2828
|
+
o.suspendHistory();
|
|
2667
2829
|
const r = e || s.getActiveObject();
|
|
2668
2830
|
if (r) {
|
|
2669
2831
|
if (r instanceof v) {
|
|
2670
|
-
const
|
|
2671
|
-
for (let h =
|
|
2672
|
-
s.sendObjectToBack(
|
|
2832
|
+
const c = r.getObjects();
|
|
2833
|
+
for (let h = c.length - 1; h >= 0; h -= 1)
|
|
2834
|
+
s.sendObjectToBack(c[h]);
|
|
2673
2835
|
} else
|
|
2674
2836
|
s.sendObjectToBack(r);
|
|
2675
|
-
i && s.sendObjectToBack(i), s.sendObjectToBack(
|
|
2837
|
+
i && s.sendObjectToBack(i), s.sendObjectToBack(n), a && s.sendObjectToBack(a), s.renderAll(), o.resumeHistory(), t || o.saveState(), s.fire("editor:object-send-to-back", {
|
|
2676
2838
|
object: r,
|
|
2677
2839
|
withoutSave: t
|
|
2678
2840
|
});
|
|
@@ -2687,14 +2849,14 @@ class K {
|
|
|
2687
2849
|
sendBackwards(e, { withoutSave: t } = {}) {
|
|
2688
2850
|
const {
|
|
2689
2851
|
canvas: s,
|
|
2690
|
-
montageArea:
|
|
2691
|
-
historyManager:
|
|
2692
|
-
interactionBlocker: { overlayMask:
|
|
2852
|
+
montageArea: n,
|
|
2853
|
+
historyManager: o,
|
|
2854
|
+
interactionBlocker: { overlayMask: a },
|
|
2693
2855
|
backgroundManager: { backgroundObject: i }
|
|
2694
2856
|
} = this.editor;
|
|
2695
|
-
|
|
2857
|
+
o.suspendHistory();
|
|
2696
2858
|
const r = e || s.getActiveObject();
|
|
2697
|
-
r && (r instanceof v ?
|
|
2859
|
+
r && (r instanceof v ? J._moveSelectionBackwards(s, r) : s.sendObjectBackwards(r), i && s.sendObjectToBack(i), s.sendObjectToBack(n), a && s.sendObjectToBack(a), s.renderAll(), o.resumeHistory(), t || o.saveState(), s.fire("editor:object-send-backwards", {
|
|
2698
2860
|
object: r,
|
|
2699
2861
|
withoutSave: t
|
|
2700
2862
|
}));
|
|
@@ -2706,15 +2868,15 @@ class K {
|
|
|
2706
2868
|
* @param activeSelection - активное выделение
|
|
2707
2869
|
*/
|
|
2708
2870
|
static _moveSelectionForward(e, t) {
|
|
2709
|
-
const s = e.getObjects(),
|
|
2710
|
-
if (!
|
|
2871
|
+
const s = e.getObjects(), n = t.getObjects();
|
|
2872
|
+
if (!n.some((i) => {
|
|
2711
2873
|
const r = s.indexOf(i);
|
|
2712
|
-
for (let
|
|
2713
|
-
if (!
|
|
2874
|
+
for (let c = r + 1; c < s.length; c += 1)
|
|
2875
|
+
if (!n.includes(s[c]))
|
|
2714
2876
|
return !0;
|
|
2715
2877
|
return !1;
|
|
2716
2878
|
})) return;
|
|
2717
|
-
|
|
2879
|
+
n.map((i) => ({ obj: i, index: s.indexOf(i) })).sort((i, r) => r.index - i.index).forEach((i) => {
|
|
2718
2880
|
e.bringObjectForward(i.obj);
|
|
2719
2881
|
});
|
|
2720
2882
|
}
|
|
@@ -2725,20 +2887,20 @@ class K {
|
|
|
2725
2887
|
* @param activeSelection - активное выделение
|
|
2726
2888
|
*/
|
|
2727
2889
|
static _moveSelectionBackwards(e, t) {
|
|
2728
|
-
const s = e.getObjects(),
|
|
2729
|
-
if (!
|
|
2890
|
+
const s = e.getObjects(), n = t.getObjects();
|
|
2891
|
+
if (!n.some((i) => {
|
|
2730
2892
|
const r = s.indexOf(i);
|
|
2731
|
-
for (let
|
|
2732
|
-
if (!
|
|
2893
|
+
for (let c = r - 1; c >= 0; c -= 1)
|
|
2894
|
+
if (!n.includes(s[c]))
|
|
2733
2895
|
return !0;
|
|
2734
2896
|
return !1;
|
|
2735
2897
|
})) return;
|
|
2736
|
-
|
|
2898
|
+
n.map((i) => ({ obj: i, index: s.indexOf(i) })).sort((i, r) => i.index - r.index).forEach((i) => {
|
|
2737
2899
|
e.sendObjectBackwards(i.obj);
|
|
2738
2900
|
});
|
|
2739
2901
|
}
|
|
2740
2902
|
}
|
|
2741
|
-
class
|
|
2903
|
+
class yt {
|
|
2742
2904
|
/**
|
|
2743
2905
|
* Менеджер фигур для редактора.
|
|
2744
2906
|
* @param options - Опции и настройки менеджера фигур.
|
|
@@ -2762,15 +2924,15 @@ class pt {
|
|
|
2762
2924
|
* @param flags.withoutSelection - Не выделять объект
|
|
2763
2925
|
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2764
2926
|
*/
|
|
2765
|
-
addRectangle(h = {}, { withoutSelection: r, withoutAdding:
|
|
2927
|
+
addRectangle(h = {}, { withoutSelection: r, withoutAdding: c } = {}) {
|
|
2766
2928
|
var l = h, {
|
|
2767
|
-
id: e = `rect-${
|
|
2929
|
+
id: e = `rect-${C()}`,
|
|
2768
2930
|
left: t,
|
|
2769
2931
|
top: s,
|
|
2770
|
-
width:
|
|
2771
|
-
height:
|
|
2772
|
-
fill:
|
|
2773
|
-
} = l, i =
|
|
2932
|
+
width: n = 100,
|
|
2933
|
+
height: o = 100,
|
|
2934
|
+
fill: a = "blue"
|
|
2935
|
+
} = l, i = G(l, [
|
|
2774
2936
|
"id",
|
|
2775
2937
|
"left",
|
|
2776
2938
|
"top",
|
|
@@ -2778,15 +2940,15 @@ class pt {
|
|
|
2778
2940
|
"height",
|
|
2779
2941
|
"fill"
|
|
2780
2942
|
]);
|
|
2781
|
-
const { canvas:
|
|
2943
|
+
const { canvas: g } = this.editor, u = new Be(I({
|
|
2782
2944
|
id: e,
|
|
2783
2945
|
left: t,
|
|
2784
2946
|
top: s,
|
|
2785
|
-
width:
|
|
2786
|
-
height:
|
|
2787
|
-
fill:
|
|
2947
|
+
width: n,
|
|
2948
|
+
height: o,
|
|
2949
|
+
fill: a
|
|
2788
2950
|
}, i));
|
|
2789
|
-
return !t && !s &&
|
|
2951
|
+
return !t && !s && g.centerObject(u), c || (g.add(u), r || g.setActiveObject(u), g.renderAll()), u;
|
|
2790
2952
|
}
|
|
2791
2953
|
/**
|
|
2792
2954
|
* Добавление круга
|
|
@@ -2804,28 +2966,28 @@ class pt {
|
|
|
2804
2966
|
* @param flags.withoutSelection - Не выделять объект
|
|
2805
2967
|
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2806
2968
|
*/
|
|
2807
|
-
addCircle(
|
|
2808
|
-
var h =
|
|
2809
|
-
id: e = `circle-${
|
|
2969
|
+
addCircle(c = {}, { withoutSelection: i, withoutAdding: r } = {}) {
|
|
2970
|
+
var h = c, {
|
|
2971
|
+
id: e = `circle-${C()}`,
|
|
2810
2972
|
left: t,
|
|
2811
2973
|
top: s,
|
|
2812
|
-
radius:
|
|
2813
|
-
fill:
|
|
2814
|
-
} = h,
|
|
2974
|
+
radius: n = 50,
|
|
2975
|
+
fill: o = "green"
|
|
2976
|
+
} = h, a = G(h, [
|
|
2815
2977
|
"id",
|
|
2816
2978
|
"left",
|
|
2817
2979
|
"top",
|
|
2818
2980
|
"radius",
|
|
2819
2981
|
"fill"
|
|
2820
2982
|
]);
|
|
2821
|
-
const { canvas: l } = this.editor,
|
|
2983
|
+
const { canvas: l } = this.editor, g = new xe(I({
|
|
2822
2984
|
id: e,
|
|
2823
2985
|
left: t,
|
|
2824
2986
|
top: s,
|
|
2825
|
-
fill:
|
|
2826
|
-
radius:
|
|
2827
|
-
},
|
|
2828
|
-
return !t && !s && l.centerObject(
|
|
2987
|
+
fill: o,
|
|
2988
|
+
radius: n
|
|
2989
|
+
}, a));
|
|
2990
|
+
return !t && !s && l.centerObject(g), r || (l.add(g), i || l.setActiveObject(g), l.renderAll()), g;
|
|
2829
2991
|
}
|
|
2830
2992
|
/**
|
|
2831
2993
|
* Добавление треугольника
|
|
@@ -2844,15 +3006,15 @@ class pt {
|
|
|
2844
3006
|
* @param flags.withoutSelection - Не выделять объект
|
|
2845
3007
|
* @param flags.withoutAdding - Не добавлять объект в canvas
|
|
2846
3008
|
*/
|
|
2847
|
-
addTriangle(h = {}, { withoutSelection: r, withoutAdding:
|
|
3009
|
+
addTriangle(h = {}, { withoutSelection: r, withoutAdding: c } = {}) {
|
|
2848
3010
|
var l = h, {
|
|
2849
|
-
id: e = `triangle-${
|
|
3011
|
+
id: e = `triangle-${C()}`,
|
|
2850
3012
|
left: t,
|
|
2851
3013
|
top: s,
|
|
2852
|
-
width:
|
|
2853
|
-
height:
|
|
2854
|
-
fill:
|
|
2855
|
-
} = l, i =
|
|
3014
|
+
width: n = 100,
|
|
3015
|
+
height: o = 100,
|
|
3016
|
+
fill: a = "yellow"
|
|
3017
|
+
} = l, i = G(l, [
|
|
2856
3018
|
"id",
|
|
2857
3019
|
"left",
|
|
2858
3020
|
"top",
|
|
@@ -2860,18 +3022,18 @@ class pt {
|
|
|
2860
3022
|
"height",
|
|
2861
3023
|
"fill"
|
|
2862
3024
|
]);
|
|
2863
|
-
const { canvas:
|
|
3025
|
+
const { canvas: g } = this.editor, u = new Re(I({
|
|
2864
3026
|
id: e,
|
|
2865
3027
|
left: t,
|
|
2866
3028
|
top: s,
|
|
2867
|
-
fill:
|
|
2868
|
-
width:
|
|
2869
|
-
height:
|
|
3029
|
+
fill: a,
|
|
3030
|
+
width: n,
|
|
3031
|
+
height: o
|
|
2870
3032
|
}, i));
|
|
2871
|
-
return !t && !s &&
|
|
3033
|
+
return !t && !s && g.centerObject(u), c || (g.add(u), r || g.setActiveObject(u), g.renderAll()), u;
|
|
2872
3034
|
}
|
|
2873
3035
|
}
|
|
2874
|
-
class
|
|
3036
|
+
class vt {
|
|
2875
3037
|
/**
|
|
2876
3038
|
* @param options
|
|
2877
3039
|
* @param options.editor - экземпляр редактора с доступом к canvas
|
|
@@ -2899,18 +3061,18 @@ class yt {
|
|
|
2899
3061
|
* Асинхронное клонирование для внутреннего буфера
|
|
2900
3062
|
*/
|
|
2901
3063
|
_cloneToInternalClipboard(e) {
|
|
2902
|
-
return
|
|
3064
|
+
return y(this, null, function* () {
|
|
2903
3065
|
const { canvas: t, errorManager: s } = this.editor;
|
|
2904
3066
|
try {
|
|
2905
|
-
const
|
|
2906
|
-
this.clipboard =
|
|
2907
|
-
} catch (
|
|
3067
|
+
const n = yield e.clone(["format"]);
|
|
3068
|
+
this.clipboard = n, t.fire("editor:object-copied", { object: n });
|
|
3069
|
+
} catch (n) {
|
|
2908
3070
|
s.emitError({
|
|
2909
3071
|
origin: "ClipboardManager",
|
|
2910
3072
|
method: "_cloneToInternalClipboard",
|
|
2911
3073
|
code: "CLONE_FAILED",
|
|
2912
3074
|
message: "Ошибка клонирования объекта для внутреннего буфера",
|
|
2913
|
-
data:
|
|
3075
|
+
data: n
|
|
2914
3076
|
});
|
|
2915
3077
|
}
|
|
2916
3078
|
});
|
|
@@ -2919,7 +3081,7 @@ class yt {
|
|
|
2919
3081
|
* Копирование в системный буфер обмена
|
|
2920
3082
|
*/
|
|
2921
3083
|
_copyToSystemClipboard(e) {
|
|
2922
|
-
return
|
|
3084
|
+
return y(this, null, function* () {
|
|
2923
3085
|
const { errorManager: t } = this.editor;
|
|
2924
3086
|
if (typeof ClipboardItem == "undefined" || !navigator.clipboard)
|
|
2925
3087
|
return t.emitWarning({
|
|
@@ -2929,8 +3091,8 @@ class yt {
|
|
|
2929
3091
|
message: "navigator.clipboard не поддерживается в этом браузере или отсутствует HTTPS-соединение."
|
|
2930
3092
|
}), !1;
|
|
2931
3093
|
try {
|
|
2932
|
-
const s = e.toObject(["format"]),
|
|
2933
|
-
return e.type === "image" ? this._copyImageToClipboard(e,
|
|
3094
|
+
const s = e.toObject(["format"]), n = JSON.stringify(s);
|
|
3095
|
+
return e.type === "image" ? this._copyImageToClipboard(e, n) : this._copyTextToClipboard(n);
|
|
2934
3096
|
} catch (s) {
|
|
2935
3097
|
return t.emitError({
|
|
2936
3098
|
origin: "ClipboardManager",
|
|
@@ -2946,12 +3108,12 @@ class yt {
|
|
|
2946
3108
|
* Копирование изображения в буфер обмена
|
|
2947
3109
|
*/
|
|
2948
3110
|
_copyImageToClipboard(e, t) {
|
|
2949
|
-
return
|
|
3111
|
+
return y(this, null, function* () {
|
|
2950
3112
|
try {
|
|
2951
|
-
const
|
|
3113
|
+
const n = e.toCanvasElement({ enableRetinaScaling: !1 }).toDataURL(), o = n.slice(5).split(";")[0], a = n.split(",")[1], i = atob(a), r = new Uint8Array(i.length);
|
|
2952
3114
|
for (let l = 0; l < i.length; l += 1)
|
|
2953
3115
|
r[l] = i.charCodeAt(l);
|
|
2954
|
-
const
|
|
3116
|
+
const c = new Blob([r.buffer], { type: o }), h = new ClipboardItem({ [o]: c });
|
|
2955
3117
|
return yield navigator.clipboard.write([h]), console.info("Image copied to clipboard successfully"), !0;
|
|
2956
3118
|
} catch (s) {
|
|
2957
3119
|
return this.editor.errorManager.emitWarning({
|
|
@@ -2968,9 +3130,9 @@ class yt {
|
|
|
2968
3130
|
* Копирование текста в буфер обмена
|
|
2969
3131
|
*/
|
|
2970
3132
|
_copyTextToClipboard(e) {
|
|
2971
|
-
return
|
|
3133
|
+
return y(this, null, function* () {
|
|
2972
3134
|
try {
|
|
2973
|
-
const t = `${
|
|
3135
|
+
const t = `${De}${e}`;
|
|
2974
3136
|
return yield navigator.clipboard.writeText(t), console.info("Text copied to clipboard successfully"), !0;
|
|
2975
3137
|
} catch (t) {
|
|
2976
3138
|
const { errorManager: s } = this.editor;
|
|
@@ -2991,8 +3153,8 @@ class yt {
|
|
|
2991
3153
|
_addClonedObjectToCanvas(e) {
|
|
2992
3154
|
const { canvas: t, historyManager: s } = this.editor;
|
|
2993
3155
|
if (t.discardActiveObject(), e instanceof v) {
|
|
2994
|
-
s.suspendHistory(), e.canvas = t, e.forEachObject((
|
|
2995
|
-
t.add(
|
|
3156
|
+
s.suspendHistory(), e.canvas = t, e.forEachObject((n) => {
|
|
3157
|
+
t.add(n);
|
|
2996
3158
|
}), t.setActiveObject(e), t.requestRenderAll(), s.resumeHistory(), s.saveState();
|
|
2997
3159
|
return;
|
|
2998
3160
|
}
|
|
@@ -3003,7 +3165,7 @@ class yt {
|
|
|
3003
3165
|
* @param source - источник изображения (data URL или URL)
|
|
3004
3166
|
*/
|
|
3005
3167
|
_handleImageImport(e) {
|
|
3006
|
-
return
|
|
3168
|
+
return y(this, null, function* () {
|
|
3007
3169
|
var s;
|
|
3008
3170
|
const { image: t } = (s = yield this.editor.imageManager.importImage({
|
|
3009
3171
|
source: e,
|
|
@@ -3019,25 +3181,30 @@ class yt {
|
|
|
3019
3181
|
* @fires editor:object-pasted
|
|
3020
3182
|
*/
|
|
3021
3183
|
copyPaste(e) {
|
|
3022
|
-
return
|
|
3184
|
+
return y(this, null, function* () {
|
|
3023
3185
|
const { canvas: t } = this.editor, s = e || t.getActiveObject();
|
|
3024
3186
|
if (!s || s.locked) return !1;
|
|
3025
3187
|
try {
|
|
3026
|
-
const
|
|
3027
|
-
return
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3188
|
+
const n = yield s.clone(["format"]);
|
|
3189
|
+
return n instanceof v && n.forEachObject((o) => {
|
|
3190
|
+
o.set({
|
|
3191
|
+
id: `${o.type}-${C()}`,
|
|
3192
|
+
evented: !0
|
|
3193
|
+
});
|
|
3194
|
+
}), n.set({
|
|
3195
|
+
id: `${n.type}-${C()}`,
|
|
3196
|
+
left: n.left + 10,
|
|
3197
|
+
top: n.top + 10,
|
|
3031
3198
|
evented: !0
|
|
3032
|
-
}), this._addClonedObjectToCanvas(
|
|
3033
|
-
} catch (
|
|
3034
|
-
const { errorManager:
|
|
3035
|
-
return
|
|
3199
|
+
}), this._addClonedObjectToCanvas(n), t.fire("editor:object-duplicated", { object: n }), !0;
|
|
3200
|
+
} catch (n) {
|
|
3201
|
+
const { errorManager: o } = this.editor;
|
|
3202
|
+
return o.emitError({
|
|
3036
3203
|
origin: "ClipboardManager",
|
|
3037
3204
|
method: "copyPaste",
|
|
3038
3205
|
code: "COPY_PASTE_FAILED",
|
|
3039
3206
|
message: "Ошибка создания копии объекта",
|
|
3040
|
-
data:
|
|
3207
|
+
data: n
|
|
3041
3208
|
}), !1;
|
|
3042
3209
|
}
|
|
3043
3210
|
});
|
|
@@ -3049,21 +3216,21 @@ class yt {
|
|
|
3049
3216
|
* @param event.clipboardData.items — элементы буфера обмена
|
|
3050
3217
|
*/
|
|
3051
3218
|
handlePasteEvent(t) {
|
|
3052
|
-
return
|
|
3219
|
+
return y(this, arguments, function* ({ clipboardData: e }) {
|
|
3053
3220
|
var r;
|
|
3054
3221
|
if (!((r = e == null ? void 0 : e.items) != null && r.length)) {
|
|
3055
3222
|
this.paste();
|
|
3056
3223
|
return;
|
|
3057
3224
|
}
|
|
3058
3225
|
const s = e.getData("text/plain");
|
|
3059
|
-
if (s && s.startsWith(
|
|
3226
|
+
if (s && s.startsWith(De)) {
|
|
3060
3227
|
this.paste();
|
|
3061
3228
|
return;
|
|
3062
3229
|
}
|
|
3063
|
-
const { items:
|
|
3064
|
-
if (
|
|
3065
|
-
const
|
|
3066
|
-
|
|
3230
|
+
const { items: n } = e, o = n[n.length - 1], a = o.getAsFile();
|
|
3231
|
+
if (o.type !== "text/html" && a) {
|
|
3232
|
+
const c = new FileReader();
|
|
3233
|
+
c.onload = (h) => {
|
|
3067
3234
|
h.target && this._handleImageImport(h.target.result).catch((l) => {
|
|
3068
3235
|
this.editor.errorManager.emitError({
|
|
3069
3236
|
origin: "ClipboardManager",
|
|
@@ -3073,20 +3240,20 @@ class yt {
|
|
|
3073
3240
|
data: l
|
|
3074
3241
|
});
|
|
3075
3242
|
});
|
|
3076
|
-
},
|
|
3243
|
+
}, c.readAsDataURL(a);
|
|
3077
3244
|
return;
|
|
3078
3245
|
}
|
|
3079
3246
|
const i = e.getData("text/html");
|
|
3080
3247
|
if (i) {
|
|
3081
3248
|
const l = new DOMParser().parseFromString(i, "text/html").querySelector("img");
|
|
3082
3249
|
if (l != null && l.src) {
|
|
3083
|
-
this._handleImageImport(l.src).catch((
|
|
3250
|
+
this._handleImageImport(l.src).catch((g) => {
|
|
3084
3251
|
this.editor.errorManager.emitError({
|
|
3085
3252
|
origin: "ClipboardManager",
|
|
3086
3253
|
method: "handlePasteEvent",
|
|
3087
3254
|
code: "PASTE_HTML_IMAGE_FAILED",
|
|
3088
3255
|
message: "Ошибка вставки изображения из HTML",
|
|
3089
|
-
data:
|
|
3256
|
+
data: g
|
|
3090
3257
|
});
|
|
3091
3258
|
});
|
|
3092
3259
|
return;
|
|
@@ -3100,13 +3267,18 @@ class yt {
|
|
|
3100
3267
|
* @fires editor:object-pasted
|
|
3101
3268
|
*/
|
|
3102
3269
|
paste() {
|
|
3103
|
-
return
|
|
3270
|
+
return y(this, null, function* () {
|
|
3104
3271
|
const { canvas: e } = this.editor;
|
|
3105
3272
|
if (!this.clipboard) return !1;
|
|
3106
3273
|
try {
|
|
3107
3274
|
const t = yield this.clipboard.clone(["format"]);
|
|
3108
|
-
return e.discardActiveObject(), t.
|
|
3109
|
-
|
|
3275
|
+
return e.discardActiveObject(), t instanceof v && t.forEachObject((s) => {
|
|
3276
|
+
s.set({
|
|
3277
|
+
id: `${s.type}-${C()}`,
|
|
3278
|
+
evented: !0
|
|
3279
|
+
});
|
|
3280
|
+
}), t.set({
|
|
3281
|
+
id: `${t.type}-${C()}`,
|
|
3110
3282
|
left: t.left + 10,
|
|
3111
3283
|
top: t.top + 10,
|
|
3112
3284
|
evented: !0
|
|
@@ -3124,7 +3296,7 @@ class yt {
|
|
|
3124
3296
|
});
|
|
3125
3297
|
}
|
|
3126
3298
|
}
|
|
3127
|
-
class
|
|
3299
|
+
class q {
|
|
3128
3300
|
constructor({ editor: e }) {
|
|
3129
3301
|
this.editor = e;
|
|
3130
3302
|
}
|
|
@@ -3137,8 +3309,8 @@ class J {
|
|
|
3137
3309
|
* @fires editor:object-locked
|
|
3138
3310
|
*/
|
|
3139
3311
|
lockObject({ object: e, skipInnerObjects: t, withoutSave: s } = {}) {
|
|
3140
|
-
const { canvas:
|
|
3141
|
-
if (!
|
|
3312
|
+
const { canvas: n, historyManager: o } = this.editor, a = e || n.getActiveObject();
|
|
3313
|
+
if (!a || a.locked) return;
|
|
3142
3314
|
const i = {
|
|
3143
3315
|
lockMovementX: !0,
|
|
3144
3316
|
lockMovementY: !0,
|
|
@@ -3149,10 +3321,10 @@ class J {
|
|
|
3149
3321
|
lockSkewingY: !0,
|
|
3150
3322
|
locked: !0
|
|
3151
3323
|
};
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
}),
|
|
3155
|
-
object:
|
|
3324
|
+
a.set(i), !t && q._isGroupOrSelection(a) && a.getObjects().forEach((c) => {
|
|
3325
|
+
c.set(i);
|
|
3326
|
+
}), n.renderAll(), s || o.saveState(), n.fire("editor:object-locked", {
|
|
3327
|
+
object: a,
|
|
3156
3328
|
skipInnerObjects: t,
|
|
3157
3329
|
withoutSave: s
|
|
3158
3330
|
});
|
|
@@ -3165,9 +3337,9 @@ class J {
|
|
|
3165
3337
|
* @fires editor:object-unlocked
|
|
3166
3338
|
*/
|
|
3167
3339
|
unlockObject({ object: e, withoutSave: t } = {}) {
|
|
3168
|
-
const { canvas: s, historyManager:
|
|
3169
|
-
if (!
|
|
3170
|
-
const
|
|
3340
|
+
const { canvas: s, historyManager: n } = this.editor, o = e || s.getActiveObject();
|
|
3341
|
+
if (!o) return;
|
|
3342
|
+
const a = {
|
|
3171
3343
|
lockMovementX: !1,
|
|
3172
3344
|
lockMovementY: !1,
|
|
3173
3345
|
lockRotation: !1,
|
|
@@ -3177,15 +3349,15 @@ class J {
|
|
|
3177
3349
|
lockSkewingY: !1,
|
|
3178
3350
|
locked: !1
|
|
3179
3351
|
};
|
|
3180
|
-
|
|
3181
|
-
i.set(
|
|
3182
|
-
}), s.renderAll(), t ||
|
|
3183
|
-
object:
|
|
3352
|
+
o.set(a), q._isGroupOrSelection(o) && o.getObjects().forEach((i) => {
|
|
3353
|
+
i.set(a);
|
|
3354
|
+
}), s.renderAll(), t || n.saveState(), s.fire("editor:object-unlocked", {
|
|
3355
|
+
object: o,
|
|
3184
3356
|
withoutSave: t
|
|
3185
3357
|
});
|
|
3186
3358
|
}
|
|
3187
3359
|
static _isGroupOrSelection(e) {
|
|
3188
|
-
return e instanceof v || e instanceof
|
|
3360
|
+
return e instanceof v || e instanceof U;
|
|
3189
3361
|
}
|
|
3190
3362
|
}
|
|
3191
3363
|
class It {
|
|
@@ -3193,58 +3365,103 @@ class It {
|
|
|
3193
3365
|
this.editor = e;
|
|
3194
3366
|
}
|
|
3195
3367
|
/**
|
|
3196
|
-
*
|
|
3197
|
-
* @
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3368
|
+
* Получить объекты для группировки
|
|
3369
|
+
* @private
|
|
3370
|
+
*/
|
|
3371
|
+
_getObjectsToGroup(e) {
|
|
3372
|
+
if (Array.isArray(e))
|
|
3373
|
+
return e.length > 0 ? e : null;
|
|
3374
|
+
const t = e || this.editor.canvas.getActiveObject();
|
|
3375
|
+
return !t || !(t instanceof v) ? null : t.getObjects();
|
|
3376
|
+
}
|
|
3377
|
+
/**
|
|
3378
|
+
* Получить группы для разгруппировки
|
|
3379
|
+
* @private
|
|
3201
3380
|
*/
|
|
3381
|
+
_getGroupsToUngroup(e) {
|
|
3382
|
+
if (Array.isArray(e)) {
|
|
3383
|
+
const s = e.filter((n) => n instanceof U);
|
|
3384
|
+
return s.length > 0 ? s : null;
|
|
3385
|
+
}
|
|
3386
|
+
if (e instanceof v) {
|
|
3387
|
+
const s = e.getObjects().filter((n) => n instanceof U);
|
|
3388
|
+
return s.length > 0 ? s : null;
|
|
3389
|
+
}
|
|
3390
|
+
const t = e || this.editor.canvas.getActiveObject();
|
|
3391
|
+
if (!t) return null;
|
|
3392
|
+
if (t instanceof v) {
|
|
3393
|
+
const s = t.getObjects().filter((n) => n instanceof U);
|
|
3394
|
+
return s.length > 0 ? s : null;
|
|
3395
|
+
}
|
|
3396
|
+
return t instanceof U ? [t] : null;
|
|
3397
|
+
}
|
|
3398
|
+
/**
|
|
3399
|
+
* Группировка объектов
|
|
3400
|
+
* @param options
|
|
3401
|
+
* @param options.target - объект ActiveSelection или массив объектов для группировки
|
|
3402
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
3403
|
+
* @fires editor:objects-grouped
|
|
3404
|
+
*/
|
|
3202
3405
|
group({
|
|
3203
|
-
|
|
3204
|
-
withoutSave: t
|
|
3406
|
+
target: e,
|
|
3407
|
+
withoutSave: t = !1
|
|
3205
3408
|
} = {}) {
|
|
3206
|
-
const { canvas: s, historyManager:
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3409
|
+
const { canvas: s, historyManager: n } = this.editor, o = this._getObjectsToGroup(e);
|
|
3410
|
+
if (!o) return null;
|
|
3411
|
+
try {
|
|
3412
|
+
n.suspendHistory();
|
|
3413
|
+
const a = new U(o, {
|
|
3414
|
+
id: `group-${C()}`
|
|
3415
|
+
});
|
|
3416
|
+
o.forEach((r) => s.remove(r)), s.add(a), s.setActiveObject(a), s.requestRenderAll();
|
|
3417
|
+
const i = {
|
|
3418
|
+
group: a,
|
|
3419
|
+
withoutSave: t
|
|
3420
|
+
};
|
|
3421
|
+
return s.fire("editor:objects-grouped", i), i;
|
|
3422
|
+
} finally {
|
|
3423
|
+
n.resumeHistory(), t || n.saveState();
|
|
3424
|
+
}
|
|
3216
3425
|
}
|
|
3217
3426
|
/**
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3427
|
+
* Разгруппировка объектов
|
|
3428
|
+
* @param options
|
|
3429
|
+
* @param options.target - объект Group, массив групп или ActiveSelection с группами для разгруппировки
|
|
3430
|
+
* @param options.withoutSave - Не сохранять состояние
|
|
3431
|
+
* @returns данные о разгруппировке или null, если нет групп для разгруппировки
|
|
3432
|
+
* @fires editor:objects-ungrouped
|
|
3433
|
+
*/
|
|
3225
3434
|
ungroup({
|
|
3226
|
-
|
|
3227
|
-
withoutSave: t
|
|
3435
|
+
target: e,
|
|
3436
|
+
withoutSave: t = !1
|
|
3228
3437
|
} = {}) {
|
|
3229
|
-
const { canvas: s, historyManager:
|
|
3230
|
-
if (!
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3438
|
+
const { canvas: s, historyManager: n } = this.editor, o = this._getGroupsToUngroup(e);
|
|
3439
|
+
if (!o) return null;
|
|
3440
|
+
try {
|
|
3441
|
+
n.suspendHistory();
|
|
3442
|
+
const a = [];
|
|
3443
|
+
o.forEach((c) => {
|
|
3444
|
+
const h = c.removeAll();
|
|
3445
|
+
s.remove(c), h.forEach((l) => {
|
|
3446
|
+
s.add(l), a.push(l);
|
|
3447
|
+
});
|
|
3448
|
+
});
|
|
3449
|
+
const i = new v(a, {
|
|
3450
|
+
canvas: s
|
|
3451
|
+
});
|
|
3452
|
+
s.setActiveObject(i), s.requestRenderAll();
|
|
3453
|
+
const r = {
|
|
3454
|
+
selection: i,
|
|
3455
|
+
ungroupedObjects: a,
|
|
3456
|
+
withoutSave: t
|
|
3457
|
+
};
|
|
3458
|
+
return s.fire("editor:objects-ungrouped", r), r;
|
|
3459
|
+
} finally {
|
|
3460
|
+
n.resumeHistory(), t || n.saveState();
|
|
3461
|
+
}
|
|
3245
3462
|
}
|
|
3246
3463
|
}
|
|
3247
|
-
class
|
|
3464
|
+
class At {
|
|
3248
3465
|
constructor({ editor: e }) {
|
|
3249
3466
|
this.editor = e;
|
|
3250
3467
|
}
|
|
@@ -3255,11 +3472,11 @@ class vt {
|
|
|
3255
3472
|
selectAll() {
|
|
3256
3473
|
const { canvas: e, canvasManager: t, objectLockManager: s } = this.editor;
|
|
3257
3474
|
e.discardActiveObject();
|
|
3258
|
-
const
|
|
3259
|
-
|
|
3475
|
+
const n = t.getObjects(), o = n.some((i) => i.locked), a = n.length > 1 ? new v(t.getObjects(), { canvas: e }) : n[0];
|
|
3476
|
+
o && s.lockObject({ object: a, skipInnerObjects: !0, withoutSave: !0 }), e.setActiveObject(a), e.requestRenderAll(), e.fire("editor:all-objects-selected", { selected: a });
|
|
3260
3477
|
}
|
|
3261
3478
|
}
|
|
3262
|
-
class
|
|
3479
|
+
class he {
|
|
3263
3480
|
constructor({ editor: e }) {
|
|
3264
3481
|
this.editor = e;
|
|
3265
3482
|
}
|
|
@@ -3277,11 +3494,11 @@ class le {
|
|
|
3277
3494
|
* @returns массив всех удаленных объектов (включая саму группу)
|
|
3278
3495
|
*/
|
|
3279
3496
|
_handleGroupDeletion(e) {
|
|
3280
|
-
var
|
|
3281
|
-
const { groupingManager: t } = this.editor, { ungroupedObjects: s = [] } = (
|
|
3497
|
+
var n;
|
|
3498
|
+
const { groupingManager: t } = this.editor, { ungroupedObjects: s = [] } = (n = t.ungroup({
|
|
3282
3499
|
object: e,
|
|
3283
3500
|
withoutSave: !0
|
|
3284
|
-
})) != null ?
|
|
3501
|
+
})) != null ? n : {};
|
|
3285
3502
|
return this.deleteSelectedObjects({
|
|
3286
3503
|
objects: s,
|
|
3287
3504
|
withoutSave: !0,
|
|
@@ -3301,27 +3518,27 @@ class le {
|
|
|
3301
3518
|
withoutSave: t = !1,
|
|
3302
3519
|
_isRecursiveCall: s = !1
|
|
3303
3520
|
} = {}) {
|
|
3304
|
-
const { canvas:
|
|
3521
|
+
const { canvas: n, historyManager: o } = this.editor, i = (e || n.getActiveObjects()).filter((h) => !h.locked);
|
|
3305
3522
|
if (!(i != null && i.length)) return null;
|
|
3306
|
-
s ||
|
|
3523
|
+
s || o.suspendHistory();
|
|
3307
3524
|
const r = [];
|
|
3308
3525
|
if (i.forEach((h) => {
|
|
3309
|
-
if (
|
|
3526
|
+
if (he._isUngroupableGroup(h)) {
|
|
3310
3527
|
const l = this._handleGroupDeletion(h);
|
|
3311
3528
|
r.push(...l);
|
|
3312
3529
|
return;
|
|
3313
3530
|
}
|
|
3314
|
-
|
|
3531
|
+
n.remove(h), r.push(h);
|
|
3315
3532
|
}), s) return null;
|
|
3316
|
-
|
|
3317
|
-
const
|
|
3533
|
+
n.discardActiveObject(), n.renderAll(), o.resumeHistory(), t || o.saveState();
|
|
3534
|
+
const c = {
|
|
3318
3535
|
objects: r,
|
|
3319
3536
|
withoutSave: t
|
|
3320
3537
|
};
|
|
3321
|
-
return
|
|
3538
|
+
return n.fire("editor:objects-deleted", c), c;
|
|
3322
3539
|
}
|
|
3323
3540
|
}
|
|
3324
|
-
const
|
|
3541
|
+
const Ct = {
|
|
3325
3542
|
IMAGE_MANAGER: {
|
|
3326
3543
|
/**
|
|
3327
3544
|
* Некорректный Content-Type изображения
|
|
@@ -3420,7 +3637,7 @@ const At = {
|
|
|
3420
3637
|
INVALID_GRADIENT_FORMAT: "INVALID_GRADIENT_FORMAT"
|
|
3421
3638
|
}
|
|
3422
3639
|
};
|
|
3423
|
-
class
|
|
3640
|
+
class ee {
|
|
3424
3641
|
constructor({ editor: e }) {
|
|
3425
3642
|
this._buffer = [], this.editor = e;
|
|
3426
3643
|
}
|
|
@@ -3446,20 +3663,20 @@ class q {
|
|
|
3446
3663
|
* @param options.message — текст ошибки (опционально, если не передан, то используется код ошибки)
|
|
3447
3664
|
* @fires editor:error
|
|
3448
3665
|
*/
|
|
3449
|
-
emitError({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, data:
|
|
3450
|
-
if (!
|
|
3666
|
+
emitError({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, data: n, message: o }) {
|
|
3667
|
+
if (!ee.isValidErrorCode(s)) {
|
|
3451
3668
|
console.warn("Неизвестный код ошибки: ", { code: s, origin: e, method: t });
|
|
3452
3669
|
return;
|
|
3453
3670
|
}
|
|
3454
3671
|
if (!s) return;
|
|
3455
|
-
const
|
|
3456
|
-
console.error(`${e}. ${t}. ${s}. ${
|
|
3672
|
+
const a = o || s;
|
|
3673
|
+
console.error(`${e}. ${t}. ${s}. ${a}`, n);
|
|
3457
3674
|
const i = {
|
|
3458
3675
|
code: s,
|
|
3459
3676
|
origin: e,
|
|
3460
3677
|
method: t,
|
|
3461
|
-
message:
|
|
3462
|
-
data:
|
|
3678
|
+
message: a,
|
|
3679
|
+
data: n
|
|
3463
3680
|
};
|
|
3464
3681
|
this._buffer.push(I({
|
|
3465
3682
|
type: "editor:error"
|
|
@@ -3475,19 +3692,19 @@ class q {
|
|
|
3475
3692
|
* @param options.message — текст предупреждения (опционально, если не передан, то используется код предупреждения)
|
|
3476
3693
|
* @fires editor:warning
|
|
3477
3694
|
*/
|
|
3478
|
-
emitWarning({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, message:
|
|
3479
|
-
if (!
|
|
3695
|
+
emitWarning({ origin: e = "ImageEditor", method: t = "Unknown Method", code: s, message: n, data: o }) {
|
|
3696
|
+
if (!ee.isValidErrorCode(s)) {
|
|
3480
3697
|
console.warn("Неизвестный код предупреждения: ", { code: s, origin: e, method: t });
|
|
3481
3698
|
return;
|
|
3482
3699
|
}
|
|
3483
|
-
const
|
|
3484
|
-
console.warn(`${e}. ${t}. ${s}. ${
|
|
3700
|
+
const a = n || s;
|
|
3701
|
+
console.warn(`${e}. ${t}. ${s}. ${a}`, o);
|
|
3485
3702
|
const i = {
|
|
3486
3703
|
code: s,
|
|
3487
3704
|
origin: e,
|
|
3488
3705
|
method: t,
|
|
3489
|
-
message:
|
|
3490
|
-
data:
|
|
3706
|
+
message: a,
|
|
3707
|
+
data: o
|
|
3491
3708
|
};
|
|
3492
3709
|
this._buffer.push(I({
|
|
3493
3710
|
type: "editor:warning"
|
|
@@ -3499,17 +3716,102 @@ class q {
|
|
|
3499
3716
|
* @returns true, если код допустим, иначе false
|
|
3500
3717
|
*/
|
|
3501
3718
|
static isValidErrorCode(e) {
|
|
3502
|
-
return e ? Object.values(
|
|
3719
|
+
return e ? Object.values(Ct).some((t) => Object.values(t).includes(e)) : !1;
|
|
3503
3720
|
}
|
|
3504
3721
|
}
|
|
3505
|
-
class
|
|
3722
|
+
class St {
|
|
3723
|
+
constructor({ editor: e }) {
|
|
3724
|
+
this.currentBounds = null, this.editor = e;
|
|
3725
|
+
}
|
|
3726
|
+
/**
|
|
3727
|
+
* Рассчитывает границы перетаскивания на основе текущего зума.
|
|
3728
|
+
* Границы зависят от соотношения currentZoom к defaultZoom.
|
|
3729
|
+
* Если currentZoom <= defaultZoom, перетаскивание блокируется.
|
|
3730
|
+
* Если currentZoom > defaultZoom, границы рассчитываются как ~50% размера монтажной области.
|
|
3731
|
+
*
|
|
3732
|
+
* @returns Объект с границами перетаскивания
|
|
3733
|
+
*/
|
|
3734
|
+
calculatePanBounds() {
|
|
3735
|
+
const { canvas: e, montageArea: t, zoomManager: s } = this.editor, { defaultZoom: n } = s, o = e.getZoom();
|
|
3736
|
+
if (o <= n)
|
|
3737
|
+
return {
|
|
3738
|
+
minX: 0,
|
|
3739
|
+
maxX: 0,
|
|
3740
|
+
minY: 0,
|
|
3741
|
+
maxY: 0,
|
|
3742
|
+
canPan: !1
|
|
3743
|
+
};
|
|
3744
|
+
const a = t.width * o, i = t.height * o, r = a / 2, c = i / 2;
|
|
3745
|
+
return {
|
|
3746
|
+
minX: -r,
|
|
3747
|
+
maxX: r,
|
|
3748
|
+
minY: -c,
|
|
3749
|
+
maxY: c,
|
|
3750
|
+
canPan: !0
|
|
3751
|
+
};
|
|
3752
|
+
}
|
|
3753
|
+
/**
|
|
3754
|
+
* Проверяет, разрешено ли перетаскивание при текущем зуме.
|
|
3755
|
+
* @returns true если можно перетаскивать
|
|
3756
|
+
*/
|
|
3757
|
+
isPanAllowed() {
|
|
3758
|
+
var e, t;
|
|
3759
|
+
return this.currentBounds || this.updateBounds(), (t = (e = this.currentBounds) == null ? void 0 : e.canPan) != null ? t : !1;
|
|
3760
|
+
}
|
|
3761
|
+
/**
|
|
3762
|
+
* Ограничивает координаты viewportTransform границами.
|
|
3763
|
+
* Координаты vpt[4] и vpt[5] представляют смещение канваса.
|
|
3764
|
+
*
|
|
3765
|
+
* @param vptX - текущее смещение по X из viewportTransform[4]
|
|
3766
|
+
* @param vptY - текущее смещение по Y из viewportTransform[5]
|
|
3767
|
+
* @returns Скорректированные координаты смещения
|
|
3768
|
+
*/
|
|
3769
|
+
constrainPan(e, t) {
|
|
3770
|
+
if (!this.currentBounds || !this.currentBounds.canPan)
|
|
3771
|
+
return { x: 0, y: 0 };
|
|
3772
|
+
const { canvas: s, montageArea: n } = this.editor, o = s.getZoom(), a = n.left, i = n.top, r = s.getWidth() / 2, c = s.getHeight() / 2, h = a * o + e - r, l = i * o + t - c, g = Math.max(
|
|
3773
|
+
this.currentBounds.minX,
|
|
3774
|
+
Math.min(this.currentBounds.maxX, h)
|
|
3775
|
+
), u = Math.max(
|
|
3776
|
+
this.currentBounds.minY,
|
|
3777
|
+
Math.min(this.currentBounds.maxY, l)
|
|
3778
|
+
), f = g + r - a * o, M = u + c - i * o;
|
|
3779
|
+
return {
|
|
3780
|
+
x: f,
|
|
3781
|
+
y: M
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
/**
|
|
3785
|
+
* Получить текущие границы перетаскивания (геттер для внешнего использования).
|
|
3786
|
+
* @returns Текущие границы или null если они ещё не рассчитаны
|
|
3787
|
+
*/
|
|
3788
|
+
getPanBounds() {
|
|
3789
|
+
return this.currentBounds;
|
|
3790
|
+
}
|
|
3791
|
+
/**
|
|
3792
|
+
* Получить текущее смещение монтажной области относительно центра канваса.
|
|
3793
|
+
* @returns Объект с координатами смещения
|
|
3794
|
+
*/
|
|
3795
|
+
getCurrentOffset() {
|
|
3796
|
+
const { canvas: e, montageArea: t } = this.editor, s = e.getZoom(), n = e.viewportTransform, o = t.left, a = t.top, i = e.getWidth() / 2, r = e.getHeight() / 2, c = o * s + n[4] - i, h = a * s + n[5] - r;
|
|
3797
|
+
return { x: c, y: h };
|
|
3798
|
+
}
|
|
3799
|
+
/**
|
|
3800
|
+
* Обновить границы перетаскивания.
|
|
3801
|
+
* Вызывается при изменении зума или размеров монтажной области.
|
|
3802
|
+
*/
|
|
3803
|
+
updateBounds() {
|
|
3804
|
+
this.currentBounds = this.calculatePanBounds();
|
|
3805
|
+
}
|
|
3806
|
+
}
|
|
3807
|
+
class ge {
|
|
3506
3808
|
/**
|
|
3507
3809
|
* Конструктор класса ImageEditor.
|
|
3508
3810
|
* @param canvasId - идентификатор канваса, в котором будет создан редактор
|
|
3509
3811
|
* @param options - опции и настройки редактора
|
|
3510
3812
|
*/
|
|
3511
3813
|
constructor(e, t) {
|
|
3512
|
-
this.options = t, this.containerId = e, this.editorId = `${e}-${
|
|
3814
|
+
this.options = t, this.containerId = e, this.editorId = `${e}-${C()}`, this.clipboard = null, this.init();
|
|
3513
3815
|
}
|
|
3514
3816
|
/**
|
|
3515
3817
|
* Инициализация редактора.
|
|
@@ -3517,27 +3819,27 @@ class he {
|
|
|
3517
3819
|
* @fires editor:ready
|
|
3518
3820
|
*/
|
|
3519
3821
|
init() {
|
|
3520
|
-
return
|
|
3822
|
+
return y(this, null, function* () {
|
|
3521
3823
|
const {
|
|
3522
3824
|
editorContainerWidth: e,
|
|
3523
3825
|
editorContainerHeight: t,
|
|
3524
3826
|
canvasWrapperWidth: s,
|
|
3525
|
-
canvasWrapperHeight:
|
|
3526
|
-
canvasCSSWidth:
|
|
3527
|
-
canvasCSSHeight:
|
|
3827
|
+
canvasWrapperHeight: n,
|
|
3828
|
+
canvasCSSWidth: o,
|
|
3829
|
+
canvasCSSHeight: a,
|
|
3528
3830
|
initialImage: i,
|
|
3529
3831
|
initialStateJSON: r,
|
|
3530
|
-
scaleType:
|
|
3832
|
+
scaleType: c,
|
|
3531
3833
|
showRotationAngle: h,
|
|
3532
3834
|
_onReadyCallback: l
|
|
3533
3835
|
} = this.options;
|
|
3534
|
-
if (
|
|
3836
|
+
if (qe.apply(), this.canvas = new Ue(this.containerId, this.options), this.moduleLoader = new Pe(), this.workerManager = new Fe(), this.errorManager = new ee({ editor: this }), this.historyManager = new K({ editor: this }), this.toolbar = new ct({ editor: this }), this.transformManager = new pt({ editor: this }), this.zoomManager = new bt({ editor: this }), this.canvasManager = new Mt({ editor: this }), this.imageManager = new _({ editor: this }), this.layerManager = new J({ editor: this }), this.shapeManager = new yt({ editor: this }), this.interactionBlocker = new jt({ editor: this }), this.backgroundManager = new Y({ editor: this }), this.clipboardManager = new vt({ editor: this }), this.objectLockManager = new q({ editor: this }), this.groupingManager = new It({ editor: this }), this.selectionManager = new At({ editor: this }), this.deletionManager = new he({ editor: this }), this.panConstraintManager = new St({ editor: this }), h && (this.angleIndicator = new le({ editor: this })), this._createMontageArea(), this._createClippingArea(), this.listeners = new W({ editor: this, options: this.options }), this.canvasManager.setEditorContainerWidth(e), this.canvasManager.setEditorContainerHeight(t), this.canvasManager.setCanvasWrapperWidth(s), this.canvasManager.setCanvasWrapperHeight(n), this.canvasManager.setCanvasCSSWidth(o), this.canvasManager.setCanvasCSSHeight(a), this.canvasManager.updateCanvas(), this.zoomManager.calculateAndApplyDefaultZoom(), i != null && i.source) {
|
|
3535
3837
|
const {
|
|
3536
|
-
source:
|
|
3537
|
-
scale:
|
|
3538
|
-
withoutSave:
|
|
3838
|
+
source: g,
|
|
3839
|
+
scale: u = `image-${c}`,
|
|
3840
|
+
withoutSave: f = !0
|
|
3539
3841
|
} = i;
|
|
3540
|
-
yield this.imageManager.importImage({ source:
|
|
3842
|
+
yield this.imageManager.importImage({ source: g, scale: u, withoutSave: f });
|
|
3541
3843
|
}
|
|
3542
3844
|
r && this.historyManager.loadStateFromFullState(r), this.historyManager.saveState(), console.log("editor:ready"), this.canvas.fire("editor:ready", this), typeof l == "function" && l(this);
|
|
3543
3845
|
});
|
|
@@ -3553,7 +3855,7 @@ class he {
|
|
|
3553
3855
|
this.montageArea = this.shapeManager.addRectangle({
|
|
3554
3856
|
width: e,
|
|
3555
3857
|
height: t,
|
|
3556
|
-
fill:
|
|
3858
|
+
fill: ge._createMosaicPattern(),
|
|
3557
3859
|
stroke: null,
|
|
3558
3860
|
strokeWidth: 0,
|
|
3559
3861
|
selectable: !1,
|
|
@@ -3604,13 +3906,13 @@ class he {
|
|
|
3604
3906
|
const e = document.createElement("canvas");
|
|
3605
3907
|
e.width = 20, e.height = 20;
|
|
3606
3908
|
const t = e.getContext("2d");
|
|
3607
|
-
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
|
|
3909
|
+
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 Ye({
|
|
3608
3910
|
source: e,
|
|
3609
3911
|
repeat: "repeat"
|
|
3610
3912
|
});
|
|
3611
3913
|
}
|
|
3612
3914
|
}
|
|
3613
|
-
const
|
|
3915
|
+
const Dt = {
|
|
3614
3916
|
/**
|
|
3615
3917
|
* Опции редактора
|
|
3616
3918
|
*/
|
|
@@ -3700,18 +4002,18 @@ const Ct = {
|
|
|
3700
4002
|
resetObjectFitByDoubleClick: !0,
|
|
3701
4003
|
keyboardIgnoreSelectors: []
|
|
3702
4004
|
};
|
|
3703
|
-
function
|
|
3704
|
-
const t = I(I({},
|
|
4005
|
+
function kt(d, e = {}) {
|
|
4006
|
+
const t = I(I({}, Dt), e), s = document.getElementById(d);
|
|
3705
4007
|
if (!s)
|
|
3706
|
-
return Promise.reject(new Error(`Контейнер с ID "${
|
|
3707
|
-
const
|
|
3708
|
-
return
|
|
3709
|
-
t._onReadyCallback =
|
|
3710
|
-
const
|
|
3711
|
-
window[
|
|
4008
|
+
return Promise.reject(new Error(`Контейнер с ID "${d}" не найден.`));
|
|
4009
|
+
const n = document.createElement("canvas");
|
|
4010
|
+
return n.id = `${d}-canvas`, s.appendChild(n), t.editorContainer = s, new Promise((o) => {
|
|
4011
|
+
t._onReadyCallback = o;
|
|
4012
|
+
const a = new ge(n.id, t);
|
|
4013
|
+
window[d] = a;
|
|
3712
4014
|
});
|
|
3713
4015
|
}
|
|
3714
4016
|
export {
|
|
3715
|
-
|
|
4017
|
+
kt as default
|
|
3716
4018
|
};
|
|
3717
4019
|
//# sourceMappingURL=main.js.map
|