@anu3ev/fabric-image-editor 0.3.1 → 0.4.0
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 +40 -38
- package/package.json +1 -1
- package/readme.md +9 -6
package/dist/main.js
CHANGED
|
@@ -35,7 +35,7 @@ var C = (h, t, e) => new Promise((s, n) => {
|
|
|
35
35
|
}, i = (r) => r.done ? s(r.value) : Promise.resolve(r.value).then(o, a);
|
|
36
36
|
i((e = e.apply(h, t)).next());
|
|
37
37
|
});
|
|
38
|
-
import { ActiveSelection as D, Textbox as gt, util as mt, controlsUtils as pe, InteractiveFabricObject as Me, loadSVGFromURL as Ne, FabricImage as ht, Point as bt, Gradient as ye, Rect as Le, Circle as xe, Triangle as ke, Group as $, Canvas as
|
|
38
|
+
import { ActiveSelection as D, Textbox as gt, util as mt, controlsUtils as pe, InteractiveFabricObject as Me, loadSVGFromURL as Ne, FabricImage as ht, Point as bt, Gradient as ye, Rect as Le, Circle as xe, Triangle as ke, Group as $, Canvas as _e, Pattern as Be } from "fabric";
|
|
39
39
|
import { create as Re } from "jsondiffpatch";
|
|
40
40
|
import Ue from "diff-match-patch";
|
|
41
41
|
var ze = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict", x = function() {
|
|
@@ -463,18 +463,18 @@ class He {
|
|
|
463
463
|
this.worker.terminate();
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
|
-
const F = 12, Ze = 2, Dt = 8, Ot = 20, We = 100, Tt = 20, Nt = 8, Pe = 100, vt = 32, xt = 1, Ve = "#2B2D33", kt = "#3D8BF4",
|
|
466
|
+
const F = 12, Ze = 2, Dt = 8, Ot = 20, We = 100, Tt = 20, Nt = 8, Pe = 100, vt = 32, xt = 1, Ve = "#2B2D33", kt = "#3D8BF4", _t = "#FFFFFF";
|
|
467
467
|
function Mt(h, t, e, s, n) {
|
|
468
468
|
const o = F, a = Ze;
|
|
469
|
-
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle =
|
|
469
|
+
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -o / 2, o, o, a), h.fill(), h.stroke(), h.restore();
|
|
470
470
|
}
|
|
471
471
|
function be(h, t, e, s, n) {
|
|
472
472
|
const o = Dt, a = Ot, i = We;
|
|
473
|
-
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle =
|
|
473
|
+
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
|
|
474
474
|
}
|
|
475
475
|
function ve(h, t, e, s, n) {
|
|
476
476
|
const o = Tt, a = Nt, i = Pe;
|
|
477
|
-
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle =
|
|
477
|
+
h.save(), h.translate(t, e), h.rotate(mt.degreesToRadians(n.angle)), h.fillStyle = _t, h.strokeStyle = kt, h.lineWidth = xt, h.beginPath(), h.roundRect(-o / 2, -a / 2, o, a, i), h.fill(), h.stroke(), h.restore();
|
|
478
478
|
}
|
|
479
479
|
const Ge = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMCIgaGVpZ2h0PSIyMCIgZmlsbD0ibm9uZSI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE4Ljc1IDQuMzc1djMuNzVhLjYyNS42MjUgMCAwIDEtLjYyNS42MjVoLTMuNzVhLjYyNS42MjUgMCAwIDEgMC0xLjI1aDIuMTRsLTIuMDc3LTEuOTAzLS4wMi0uMDE5YTYuMjUgNi4yNSAwIDEgMC0uMTMgOC45NjcuNjI2LjYyNiAwIDAgMSAuODYuOTA5QTcuNDU2IDcuNDU2IDAgMCAxIDEwIDE3LjVoLS4xMDNhNy41IDcuNSAwIDEgMSA1LjM5Ni0xMi44MTJMMTcuNSA2LjcwM1Y0LjM3NWEuNjI1LjYyNSAwIDAgMSAxLjI1IDBaIi8+PC9zdmc+", we = new Image();
|
|
480
480
|
we.src = Ge;
|
|
@@ -972,7 +972,7 @@ const as = {
|
|
|
972
972
|
"white-space": "nowrap",
|
|
973
973
|
"box-shadow": "0 2px 8px rgba(0, 0, 0, 0.2)"
|
|
974
974
|
}, je = 16, Ie = 16, is = "fabric-editor-angle-indicator";
|
|
975
|
-
class
|
|
975
|
+
class Bt {
|
|
976
976
|
constructor({ editor: t }) {
|
|
977
977
|
this.isActive = !1, this.currentAngle = 0, this.editor = t, this.canvas = t.canvas, this.options = t.options, this._createDOM(), this._bindEvents();
|
|
978
978
|
}
|
|
@@ -1000,7 +1000,7 @@ class _t {
|
|
|
1000
1000
|
return;
|
|
1001
1001
|
}
|
|
1002
1002
|
const s = e.angle || 0;
|
|
1003
|
-
this.currentAngle =
|
|
1003
|
+
this.currentAngle = Bt._normalizeAngle(s), this.el.textContent = `${this.currentAngle}°`, this._positionIndicator(t.e), this.isActive || this._showIndicator();
|
|
1004
1004
|
}
|
|
1005
1005
|
/**
|
|
1006
1006
|
* Обработчик отпускания кнопки мыши
|
|
@@ -1538,7 +1538,7 @@ class H {
|
|
|
1538
1538
|
[T]
|
|
1539
1539
|
);
|
|
1540
1540
|
if (d) {
|
|
1541
|
-
const w = m * 0.264583, L = b * 0.264583,
|
|
1541
|
+
const w = m * 0.264583, L = b * 0.264583, _ = (yield this.editor.moduleLoader.loadModule("jspdf")).jsPDF, Y = new _({
|
|
1542
1542
|
orientation: w > L ? "landscape" : "portrait",
|
|
1543
1543
|
unit: "mm",
|
|
1544
1544
|
format: [w, L]
|
|
@@ -1552,8 +1552,8 @@ class H {
|
|
|
1552
1552
|
};
|
|
1553
1553
|
return a.fire("editor:canvas-exported", W), W;
|
|
1554
1554
|
}
|
|
1555
|
-
const
|
|
1556
|
-
image: new File([
|
|
1555
|
+
const B = Y.output("blob"), Z = {
|
|
1556
|
+
image: new File([B], e, { type: "application/pdf" }),
|
|
1557
1557
|
format: "pdf",
|
|
1558
1558
|
contentType: "application/pdf",
|
|
1559
1559
|
fileName: e
|
|
@@ -2442,8 +2442,8 @@ class ps {
|
|
|
2442
2442
|
const { canvas: a, montageArea: i } = this.editor, r = a.viewportTransform, c = a.getWidth(), d = a.getHeight(), l = t.x - r[4], u = t.y - r[5], g = Math.abs(n), f = e - s;
|
|
2443
2443
|
if (Math.abs(f) / g <= 0.1)
|
|
2444
2444
|
return { x: l, y: u };
|
|
2445
|
-
const b = c / 2, p = d / 2, M = i.left, S = i.top, O = b - M * s, T = p - S * s, y = (O - r[4]) / (e - s), A = (T - r[5]) / (e - s), N = y * g, I = A * g, v = N * o, w = I * o, L = Math.abs(v) > Math.abs(l) ? l : v,
|
|
2446
|
-
return { x: L, y:
|
|
2445
|
+
const b = c / 2, p = d / 2, M = i.left, S = i.top, O = b - M * s, T = p - S * s, y = (O - r[4]) / (e - s), A = (T - r[5]) / (e - s), N = y * g, I = A * g, v = N * o, w = I * o, L = Math.abs(v) > Math.abs(l) ? l : v, _ = Math.abs(w) > Math.abs(u) ? u : w;
|
|
2446
|
+
return { x: L, y: _ };
|
|
2447
2447
|
}
|
|
2448
2448
|
/**
|
|
2449
2449
|
* Применяет плавное центрирование viewport при приближении к defaultZoom.
|
|
@@ -3996,9 +3996,9 @@ const Et = 0.01;
|
|
|
3996
3996
|
class k {
|
|
3997
3997
|
constructor({ editor: t }) {
|
|
3998
3998
|
var e;
|
|
3999
|
-
this.
|
|
3999
|
+
this._handleTextEditingEntered = () => {
|
|
4000
4000
|
this.isTextEditingActive = !0;
|
|
4001
|
-
}, this.
|
|
4001
|
+
}, this._handleTextChanged = (s) => {
|
|
4002
4002
|
var r, c;
|
|
4003
4003
|
const { target: n } = s;
|
|
4004
4004
|
if (!k._isTextbox(n)) return;
|
|
@@ -4013,7 +4013,7 @@ class k {
|
|
|
4013
4013
|
} else u < l ? n.textCaseRaw = i.slice(0, u) : n.textCaseRaw = o.toLocaleLowerCase();
|
|
4014
4014
|
} else
|
|
4015
4015
|
n.textCaseRaw = o;
|
|
4016
|
-
}, this.
|
|
4016
|
+
}, this._handleTextEditingExited = (s) => {
|
|
4017
4017
|
var i, r;
|
|
4018
4018
|
const { target: n } = s;
|
|
4019
4019
|
if (!k._isTextbox(n)) return;
|
|
@@ -4029,7 +4029,7 @@ class k {
|
|
|
4029
4029
|
}), setTimeout(() => {
|
|
4030
4030
|
this.isTextEditingActive = !1, this.editor.historyManager.saveState();
|
|
4031
4031
|
}, hs);
|
|
4032
|
-
}, this.
|
|
4032
|
+
}, this._handleObjectScaling = (s) => {
|
|
4033
4033
|
var Z, G, W, tt, et, st, nt, ot, at, it, rt, ct, dt, lt;
|
|
4034
4034
|
const { target: n, transform: o } = s;
|
|
4035
4035
|
if (!k._isTextbox(n) || !o) return;
|
|
@@ -4046,27 +4046,21 @@ class k {
|
|
|
4046
4046
|
scaleX: 1,
|
|
4047
4047
|
scaleY: 1
|
|
4048
4048
|
});
|
|
4049
|
-
const
|
|
4050
|
-
let
|
|
4051
|
-
Y && (b || M) && (A === "right" ?
|
|
4049
|
+
const _ = (dt = n.width) != null ? dt : T, Y = Math.abs(_ - v) > Et;
|
|
4050
|
+
let B = g;
|
|
4051
|
+
Y && (b || M) && (A === "right" ? B = N - _ : A === "center" && (B = I - _ / 2)), n.set({ left: B }), a.baseLeft = B, o.scaleX = 1, o.scaleY = 1;
|
|
4052
4052
|
const { original: R } = o;
|
|
4053
|
-
R && (R.scaleX = 1, R.scaleY = 1, R.width =
|
|
4054
|
-
}, this.
|
|
4053
|
+
R && (R.scaleX = 1, R.scaleY = 1, R.width = _, R.height = n.height, R.left = B), n.setCoords(), this.canvas.requestRenderAll(), a.baseWidth = _, a.baseFontSize = (lt = n.fontSize) != null ? lt : y, a.hasWidthChange = Y || L;
|
|
4054
|
+
}, this._handleObjectModified = (s) => {
|
|
4055
4055
|
var r, c, d;
|
|
4056
4056
|
const { target: n } = s;
|
|
4057
4057
|
if (!k._isTextbox(n)) return;
|
|
4058
4058
|
const o = this.scalingState.get(n);
|
|
4059
4059
|
if (this.scalingState.delete(n), !(o != null && o.hasWidthChange)) return;
|
|
4060
4060
|
const a = (r = n.width) != null ? r : n.calcTextWidth(), i = (d = (c = n.fontSize) != null ? c : o == null ? void 0 : o.baseFontSize) != null ? d : 16;
|
|
4061
|
-
this.updateText(n, { width: a, fontSize: i }), n.set({ scaleX: 1, scaleY: 1 }), n.setCoords();
|
|
4061
|
+
this.updateText({ target: n, style: { width: a, fontSize: i } }), n.set({ scaleX: 1, scaleY: 1 }), n.setCoords();
|
|
4062
4062
|
}, this.editor = t, this.canvas = t.canvas, this.fonts = (e = t.options.fonts) != null ? e : [], this.scalingState = /* @__PURE__ */ new WeakMap(), this.isTextEditingActive = !1, this._bindEvents();
|
|
4063
4063
|
}
|
|
4064
|
-
/**
|
|
4065
|
-
* Уничтожает менеджер и снимает слушатели.
|
|
4066
|
-
*/
|
|
4067
|
-
destroy() {
|
|
4068
|
-
this.canvas.off("object:scaling", this.handleObjectScaling), this.canvas.off("object:modified", this.handleObjectModified), this.canvas.off("text:editing:exited", this.handleTextEditingExited), this.canvas.off("text:editing:entered", this.handleTextEditingEntered), this.canvas.off("text:changed", this.handleTextChanged);
|
|
4069
|
-
}
|
|
4070
4064
|
/**
|
|
4071
4065
|
* Добавляет новый текстовый объект на канвас.
|
|
4072
4066
|
* @param options — настройки текста
|
|
@@ -4159,12 +4153,14 @@ class k {
|
|
|
4159
4153
|
}
|
|
4160
4154
|
/**
|
|
4161
4155
|
* Обновляет текстовый объект.
|
|
4162
|
-
* @param target — объект, его id или активный объект (если не передан)
|
|
4163
|
-
* @param style — стиль, который нужно применить
|
|
4164
4156
|
* @param options — настройки обновления
|
|
4157
|
+
* @param options.target — объект, его id или активный объект (если не передан)
|
|
4158
|
+
* @param options.style — стиль, который нужно применить
|
|
4159
|
+
* @param options.withoutSave — не сохранять состояние в историю
|
|
4160
|
+
* @param options.skipRender — не вызывать перерисовку канваса
|
|
4165
4161
|
*/
|
|
4166
|
-
updateText(t, e = {},
|
|
4167
|
-
var Y,
|
|
4162
|
+
updateText({ target: t, style: e = {}, withoutSave: s, skipRender: n } = {}) {
|
|
4163
|
+
var Y, B, R, Z, G, W, tt, et, st, nt, ot, at, it, rt, ct, dt, lt, zt, Yt, Ht, Zt, Wt, Pt, Vt, Gt, Xt, Kt, $t, Qt, Jt, qt, te, ee, se, ne, oe, ae, ie, re, ce, de, le;
|
|
4168
4164
|
const o = this._resolveTextObject(t);
|
|
4169
4165
|
if (!o) return null;
|
|
4170
4166
|
const { historyManager: a } = this.editor;
|
|
@@ -4172,7 +4168,7 @@ class k {
|
|
|
4172
4168
|
const i = {
|
|
4173
4169
|
id: o.id,
|
|
4174
4170
|
text: (Y = o.text) != null ? Y : void 0,
|
|
4175
|
-
textCaseRaw: (
|
|
4171
|
+
textCaseRaw: (B = o.textCaseRaw) != null ? B : void 0,
|
|
4176
4172
|
uppercase: !!o.uppercase,
|
|
4177
4173
|
fontFamily: (R = o.fontFamily) != null ? R : void 0,
|
|
4178
4174
|
fontSize: (Z = o.fontSize) != null ? Z : void 0,
|
|
@@ -4232,7 +4228,7 @@ class k {
|
|
|
4232
4228
|
y.text = wt, o.textCaseRaw = v;
|
|
4233
4229
|
} else o.textCaseRaw === void 0 && (o.textCaseRaw = A);
|
|
4234
4230
|
o.uppercase = w, o.set(y), o.setCoords(), n || this.canvas.requestRenderAll(), a.resumeHistory(), s || a.saveState();
|
|
4235
|
-
const
|
|
4231
|
+
const _ = {
|
|
4236
4232
|
id: o.id,
|
|
4237
4233
|
text: (Vt = o.text) != null ? Vt : void 0,
|
|
4238
4234
|
textCaseRaw: (Gt = o.textCaseRaw) != null ? Gt : void 0,
|
|
@@ -4266,9 +4262,15 @@ class k {
|
|
|
4266
4262
|
},
|
|
4267
4263
|
updates: y,
|
|
4268
4264
|
before: i,
|
|
4269
|
-
after:
|
|
4265
|
+
after: _
|
|
4270
4266
|
}), o;
|
|
4271
4267
|
}
|
|
4268
|
+
/**
|
|
4269
|
+
* Уничтожает менеджер и снимает слушатели.
|
|
4270
|
+
*/
|
|
4271
|
+
destroy() {
|
|
4272
|
+
this.canvas.off("object:scaling", this._handleObjectScaling), this.canvas.off("object:modified", this._handleObjectModified), this.canvas.off("text:editing:exited", this._handleTextEditingExited), this.canvas.off("text:editing:entered", this._handleTextEditingEntered), this.canvas.off("text:changed", this._handleTextChanged);
|
|
4273
|
+
}
|
|
4272
4274
|
/**
|
|
4273
4275
|
* Возвращает активный текст или ищет по id.
|
|
4274
4276
|
*/
|
|
@@ -4288,7 +4290,7 @@ class k {
|
|
|
4288
4290
|
return !!t && t instanceof gt;
|
|
4289
4291
|
}
|
|
4290
4292
|
_bindEvents() {
|
|
4291
|
-
this.canvas.on("object:scaling", this.
|
|
4293
|
+
this.canvas.on("object:scaling", this._handleObjectScaling), this.canvas.on("object:modified", this._handleObjectModified), this.canvas.on("text:editing:entered", this._handleTextEditingEntered), this.canvas.on("text:editing:exited", this._handleTextEditingExited), this.canvas.on("text:changed", this._handleTextChanged);
|
|
4292
4294
|
}
|
|
4293
4295
|
_ensureScalingState(t) {
|
|
4294
4296
|
var s, n, o;
|
|
@@ -4349,7 +4351,7 @@ class Ut {
|
|
|
4349
4351
|
showRotationAngle: d,
|
|
4350
4352
|
_onReadyCallback: l
|
|
4351
4353
|
} = this.options;
|
|
4352
|
-
if (jt.apply(), this.canvas = new
|
|
4354
|
+
if (jt.apply(), this.canvas = new _e(this.containerId, this.options), this.moduleLoader = new Ye(), this.workerManager = new He(), this.errorManager = new St({ editor: this }), this.historyManager = new It({ editor: this }), this.toolbar = new os({ editor: this }), this.transformManager = new ms({ editor: this }), this.zoomManager = new ps({ editor: this }), this.canvasManager = new fs({ editor: this }), this.imageManager = new H({ editor: this }), this.layerManager = new At({ editor: this }), this.shapeManager = new ys({ editor: this }), this.interactionBlocker = new Ms({ editor: this }), this.backgroundManager = new Q({ editor: this }), this.clipboardManager = new bs({ editor: this }), this.objectLockManager = new Ct({ editor: this }), this.groupingManager = new vs({ editor: this }), this.selectionManager = new js({ editor: this }), this.deletionManager = new Rt({ editor: this }), this.panConstraintManager = new As({ editor: this }), this.fontManager = new Lt((u = this.options.fonts) != null ? u : []), this.textManager = new k({ editor: this }), d && (this.angleIndicator = new Bt({ editor: this })), this._createMontageArea(), this._createClippingArea(), this.listeners = new ft({ editor: this, options: this.options }), this.canvasManager.setEditorContainerWidth(t), this.canvasManager.setEditorContainerHeight(e), this.canvasManager.setCanvasWrapperWidth(s), this.canvasManager.setCanvasWrapperHeight(n), this.canvasManager.setCanvasCSSWidth(o), this.canvasManager.setCanvasCSSHeight(a), this.canvasManager.updateCanvas(), this.zoomManager.calculateAndApplyDefaultZoom(), yield this.fontManager.loadFonts(), i != null && i.source) {
|
|
4353
4355
|
const {
|
|
4354
4356
|
source: g,
|
|
4355
4357
|
scale: f = `image-${c}`,
|
|
@@ -4422,7 +4424,7 @@ class Ut {
|
|
|
4422
4424
|
const t = document.createElement("canvas");
|
|
4423
4425
|
t.width = 20, t.height = 20;
|
|
4424
4426
|
const e = t.getContext("2d");
|
|
4425
|
-
return e.fillStyle = "#ddd", e.fillRect(0, 0, 40, 40), e.fillStyle = "#ccc", e.fillRect(0, 0, 10, 10), e.fillRect(10, 10, 10, 10), new
|
|
4427
|
+
return e.fillStyle = "#ddd", e.fillRect(0, 0, 40, 40), e.fillStyle = "#ccc", e.fillRect(0, 0, 10, 10), e.fillRect(10, 10, 10, 10), new Be({
|
|
4426
4428
|
source: t,
|
|
4427
4429
|
repeat: "repeat"
|
|
4428
4430
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anu3ev/fabric-image-editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "JavaScript image editor built on FabricJS, allowing you to create instances with an integrated montage area and providing an API to modify and manage state.",
|
|
5
5
|
"module": "dist/main.js",
|
|
6
6
|
"files": [
|
package/readme.md
CHANGED
|
@@ -129,17 +129,20 @@ const textbox = editor.textManager.addText({
|
|
|
129
129
|
})
|
|
130
130
|
|
|
131
131
|
// Update existing text
|
|
132
|
-
editor.textManager.updateText(
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
132
|
+
editor.textManager.updateText({
|
|
133
|
+
target: textbox,
|
|
134
|
+
style: {
|
|
135
|
+
text: 'HELLO FABRIC',
|
|
136
|
+
uppercase: true,
|
|
137
|
+
strokeColor: '#2563eb',
|
|
138
|
+
strokeWidth: 2
|
|
139
|
+
}
|
|
137
140
|
})
|
|
138
141
|
```
|
|
139
142
|
|
|
140
143
|
### Configuring Fonts
|
|
141
144
|
|
|
142
|
-
By default the editor ships with a curated Google Fonts collection (Latin + Cyrillic coverage).
|
|
145
|
+
By default the editor ships with a curated Google Fonts collection (Latin + Cyrillic coverage).
|
|
143
146
|
If you want to use your own fonts, supply a `fonts` array – the provided list will replace the defaults.
|
|
144
147
|
|
|
145
148
|
```typescript
|