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