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