@anu3ev/fabric-image-editor 0.1.12 → 0.1.19

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