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