@hprint/plugins 0.0.1-alpha.2 → 0.0.1-alpha.3
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/index.js +17 -17
- package/dist/index.mjs +1071 -1057
- package/dist/src/plugins/AlignGuidLinePlugin.d.ts +7 -2
- package/dist/src/plugins/AlignGuidLinePlugin.d.ts.map +1 -1
- package/dist/src/plugins/GroupAlignPlugin.d.ts.map +1 -1
- package/dist/src/plugins/LockPlugin.d.ts.map +1 -1
- package/dist/src/plugins/QrCodePlugin.d.ts +5 -0
- package/dist/src/plugins/QrCodePlugin.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/assets/style/resizePlugin.css +27 -27
- package/src/objects/Arrow.js +47 -47
- package/src/objects/ThinTailArrow.js +50 -50
- package/src/plugins/AlignGuidLinePlugin.ts +1152 -1141
- package/src/plugins/BarCodePlugin.ts +2 -2
- package/src/plugins/ControlsPlugin.ts +251 -251
- package/src/plugins/ControlsRotatePlugin.ts +111 -111
- package/src/plugins/CopyPlugin.ts +255 -255
- package/src/plugins/DeleteHotKeyPlugin.ts +57 -57
- package/src/plugins/DrawLinePlugin.ts +162 -162
- package/src/plugins/DrawPolygonPlugin.ts +205 -205
- package/src/plugins/DringPlugin.ts +125 -125
- package/src/plugins/FlipPlugin.ts +59 -59
- package/src/plugins/FontPlugin.ts +165 -165
- package/src/plugins/FreeDrawPlugin.ts +49 -49
- package/src/plugins/GroupAlignPlugin.ts +365 -365
- package/src/plugins/GroupPlugin.ts +82 -82
- package/src/plugins/GroupTextEditorPlugin.ts +198 -198
- package/src/plugins/HistoryPlugin.ts +181 -181
- package/src/plugins/ImageStroke.ts +121 -121
- package/src/plugins/LayerPlugin.ts +108 -108
- package/src/plugins/LockPlugin.ts +242 -240
- package/src/plugins/MaskPlugin.ts +155 -155
- package/src/plugins/MaterialPlugin.ts +224 -224
- package/src/plugins/MiddleMousePlugin.ts +45 -45
- package/src/plugins/MoveHotKeyPlugin.ts +46 -46
- package/src/plugins/PathTextPlugin.ts +89 -89
- package/src/plugins/PolygonModifyPlugin.ts +224 -224
- package/src/plugins/PrintPlugin.ts +81 -81
- package/src/plugins/PsdPlugin.ts +52 -52
- package/src/plugins/QrCodePlugin.ts +322 -329
- package/src/plugins/ResizePlugin.ts +278 -278
- package/src/plugins/RulerPlugin.ts +78 -78
- package/src/plugins/SimpleClipImagePlugin.ts +244 -244
- package/src/plugins/UnitPlugin.ts +326 -326
- package/src/plugins/WaterMarkPlugin.ts +257 -257
- package/src/types/eventType.ts +11 -11
- package/src/utils/psd.js +432 -432
- package/src/utils/ruler/guideline.ts +145 -145
- package/src/utils/ruler/index.ts +91 -91
- package/src/utils/ruler/ruler.ts +924 -924
- package/src/utils/ruler/utils.ts +162 -162
- package/tsconfig.json +10 -10
- package/vite.config.ts +29 -29
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
import { fabric } from '@hprint/core';
|
|
2
|
-
import { utils } from '@hprint/shared';
|
|
3
|
-
import { v4 as uuid } from 'uuid';
|
|
4
|
-
import type { IEditor, IPluginTempl } from '@hprint/core';
|
|
5
|
-
|
|
6
|
-
type IPlugin = Pick<GroupPlugin, 'unGroup' | 'group'>;
|
|
7
|
-
|
|
8
|
-
declare module '@hprint/core' {
|
|
9
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
10
|
-
interface IEditor extends IPlugin {}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
class GroupPlugin implements IPluginTempl {
|
|
14
|
-
static pluginName = 'GroupPlugin';
|
|
15
|
-
static apis = ['unGroup', 'group'];
|
|
16
|
-
constructor(
|
|
17
|
-
public canvas: fabric.Canvas,
|
|
18
|
-
public editor: IEditor
|
|
19
|
-
) {}
|
|
20
|
-
|
|
21
|
-
// 拆分组
|
|
22
|
-
unGroup() {
|
|
23
|
-
const activeObject = this.canvas.getActiveObject() as fabric.Group;
|
|
24
|
-
if (!activeObject) return;
|
|
25
|
-
// 先获取当前选中的对象,然后打散
|
|
26
|
-
const activeObjectList = activeObject.getObjects();
|
|
27
|
-
activeObject.toActiveSelection();
|
|
28
|
-
for (const item of activeObjectList) {
|
|
29
|
-
item.set('id', uuid());
|
|
30
|
-
}
|
|
31
|
-
this.canvas.discardActiveObject().renderAll();
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
group() {
|
|
35
|
-
// 组合元素
|
|
36
|
-
const activeObj =
|
|
37
|
-
this.canvas.getActiveObject() as fabric.ActiveSelection;
|
|
38
|
-
if (!activeObj) return;
|
|
39
|
-
const activegroup = activeObj.toGroup();
|
|
40
|
-
const objectsInGroup = activegroup.getObjects();
|
|
41
|
-
activegroup.clone((newgroup: fabric.Group) => {
|
|
42
|
-
newgroup.set('id', uuid());
|
|
43
|
-
this.canvas.remove(activegroup);
|
|
44
|
-
objectsInGroup.forEach((object) => {
|
|
45
|
-
this.canvas.remove(object);
|
|
46
|
-
});
|
|
47
|
-
this.canvas.add(newgroup);
|
|
48
|
-
this.canvas.setActiveObject(newgroup);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
contextMenu() {
|
|
53
|
-
const activeObject = this.canvas.getActiveObject();
|
|
54
|
-
|
|
55
|
-
if (utils.isActiveSelection(activeObject)) {
|
|
56
|
-
return [
|
|
57
|
-
{
|
|
58
|
-
text: '组合',
|
|
59
|
-
hotkey: 'Ctrl+V',
|
|
60
|
-
disabled: false,
|
|
61
|
-
onclick: () => this.group(),
|
|
62
|
-
},
|
|
63
|
-
];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (utils.isGroup(activeObject)) {
|
|
67
|
-
return [
|
|
68
|
-
{
|
|
69
|
-
text: '拆分组合',
|
|
70
|
-
hotkey: 'Ctrl+V',
|
|
71
|
-
disabled: false,
|
|
72
|
-
onclick: () => this.unGroup(),
|
|
73
|
-
},
|
|
74
|
-
];
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
destroy() {
|
|
78
|
-
console.log('pluginDestroy');
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export default GroupPlugin;
|
|
1
|
+
import { fabric } from '@hprint/core';
|
|
2
|
+
import { utils } from '@hprint/shared';
|
|
3
|
+
import { v4 as uuid } from 'uuid';
|
|
4
|
+
import type { IEditor, IPluginTempl } from '@hprint/core';
|
|
5
|
+
|
|
6
|
+
type IPlugin = Pick<GroupPlugin, 'unGroup' | 'group'>;
|
|
7
|
+
|
|
8
|
+
declare module '@hprint/core' {
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
10
|
+
interface IEditor extends IPlugin {}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class GroupPlugin implements IPluginTempl {
|
|
14
|
+
static pluginName = 'GroupPlugin';
|
|
15
|
+
static apis = ['unGroup', 'group'];
|
|
16
|
+
constructor(
|
|
17
|
+
public canvas: fabric.Canvas,
|
|
18
|
+
public editor: IEditor
|
|
19
|
+
) {}
|
|
20
|
+
|
|
21
|
+
// 拆分组
|
|
22
|
+
unGroup() {
|
|
23
|
+
const activeObject = this.canvas.getActiveObject() as fabric.Group;
|
|
24
|
+
if (!activeObject) return;
|
|
25
|
+
// 先获取当前选中的对象,然后打散
|
|
26
|
+
const activeObjectList = activeObject.getObjects();
|
|
27
|
+
activeObject.toActiveSelection();
|
|
28
|
+
for (const item of activeObjectList) {
|
|
29
|
+
item.set('id', uuid());
|
|
30
|
+
}
|
|
31
|
+
this.canvas.discardActiveObject().renderAll();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
group() {
|
|
35
|
+
// 组合元素
|
|
36
|
+
const activeObj =
|
|
37
|
+
this.canvas.getActiveObject() as fabric.ActiveSelection;
|
|
38
|
+
if (!activeObj) return;
|
|
39
|
+
const activegroup = activeObj.toGroup();
|
|
40
|
+
const objectsInGroup = activegroup.getObjects();
|
|
41
|
+
activegroup.clone((newgroup: fabric.Group) => {
|
|
42
|
+
newgroup.set('id', uuid());
|
|
43
|
+
this.canvas.remove(activegroup);
|
|
44
|
+
objectsInGroup.forEach((object) => {
|
|
45
|
+
this.canvas.remove(object);
|
|
46
|
+
});
|
|
47
|
+
this.canvas.add(newgroup);
|
|
48
|
+
this.canvas.setActiveObject(newgroup);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
contextMenu() {
|
|
53
|
+
const activeObject = this.canvas.getActiveObject();
|
|
54
|
+
|
|
55
|
+
if (utils.isActiveSelection(activeObject)) {
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
text: '组合',
|
|
59
|
+
hotkey: 'Ctrl+V',
|
|
60
|
+
disabled: false,
|
|
61
|
+
onclick: () => this.group(),
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (utils.isGroup(activeObject)) {
|
|
67
|
+
return [
|
|
68
|
+
{
|
|
69
|
+
text: '拆分组合',
|
|
70
|
+
hotkey: 'Ctrl+V',
|
|
71
|
+
disabled: false,
|
|
72
|
+
onclick: () => this.unGroup(),
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
destroy() {
|
|
78
|
+
console.log('pluginDestroy');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export default GroupPlugin;
|
|
@@ -1,198 +1,198 @@
|
|
|
1
|
-
import { fabric } from '@hprint/core';
|
|
2
|
-
import { utils } from '@hprint/shared';
|
|
3
|
-
import { v4 as uuid } from 'uuid';
|
|
4
|
-
import { pick } from 'lodash-es';
|
|
5
|
-
import type { IEditor, IPluginTempl } from '@hprint/core';
|
|
6
|
-
|
|
7
|
-
class GroupTextEditorPlugin implements IPluginTempl {
|
|
8
|
-
static pluginName = 'GroupTextEditorPlugin';
|
|
9
|
-
isDown = false;
|
|
10
|
-
constructor(
|
|
11
|
-
public canvas: fabric.Canvas,
|
|
12
|
-
public editor: IEditor
|
|
13
|
-
) {
|
|
14
|
-
this._init();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// 组内文本输入
|
|
18
|
-
_init() {
|
|
19
|
-
this.canvas.on('mouse:down', (opt) => {
|
|
20
|
-
this.isDown = true;
|
|
21
|
-
// 重置选中controls
|
|
22
|
-
if (
|
|
23
|
-
opt.target &&
|
|
24
|
-
!opt.target.lockMovementX &&
|
|
25
|
-
!opt.target.lockMovementY &&
|
|
26
|
-
!opt.target.lockRotation &&
|
|
27
|
-
!opt.target.lockScalingX &&
|
|
28
|
-
!opt.target.lockScalingY
|
|
29
|
-
) {
|
|
30
|
-
opt.target.hasControls = true;
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
this.canvas.on('mouse:up', () => {
|
|
35
|
-
this.isDown = false;
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
this.canvas.on('mouse:dblclick', (opt) => {
|
|
39
|
-
if (utils.isGroup(opt.target)) {
|
|
40
|
-
const selectedObject = this._getGroupObj(opt) as fabric.IText;
|
|
41
|
-
if (!selectedObject) return;
|
|
42
|
-
selectedObject.selectable = true;
|
|
43
|
-
// 由于组内的元素,双击以后会导致controls偏移,因此隐藏他
|
|
44
|
-
if (selectedObject.hasControls) {
|
|
45
|
-
selectedObject.hasControls = false;
|
|
46
|
-
}
|
|
47
|
-
if (this.isText(selectedObject)) {
|
|
48
|
-
this._bedingTextEditingEvent(selectedObject, opt.target);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
this.canvas.setActiveObject(selectedObject);
|
|
52
|
-
this.canvas.renderAll();
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// 获取点击区域内的组内文字元素
|
|
58
|
-
_getGroupTextObj(opt: fabric.IEvent<MouseEvent>) {
|
|
59
|
-
const pointer = this.canvas.getPointer(opt.e, true);
|
|
60
|
-
if (!utils.isGroup(opt.target)) return false;
|
|
61
|
-
const clickObj = this.canvas._searchPossibleTargets(
|
|
62
|
-
opt.target._objects,
|
|
63
|
-
pointer
|
|
64
|
-
);
|
|
65
|
-
if (clickObj && this.isText(clickObj)) {
|
|
66
|
-
return clickObj;
|
|
67
|
-
}
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
_getGroupObj(opt: fabric.IEvent<MouseEvent>) {
|
|
72
|
-
const pointer = this.canvas.getPointer(opt.e, true);
|
|
73
|
-
if (!utils.isGroup(opt.target)) return false;
|
|
74
|
-
const clickObj = this.canvas._searchPossibleTargets(
|
|
75
|
-
opt.target._objects,
|
|
76
|
-
pointer
|
|
77
|
-
);
|
|
78
|
-
return clickObj;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// 通过组合重新组装来编辑文字,可能会耗性能。
|
|
82
|
-
_bedingTextEditingEvent(textObject: fabric.IText, groupObj: fabric.Group) {
|
|
83
|
-
const textObjectJSON = textObject.toObject();
|
|
84
|
-
|
|
85
|
-
const groupMatrix: number[] = groupObj.calcTransformMatrix();
|
|
86
|
-
|
|
87
|
-
const a: number = groupMatrix[0];
|
|
88
|
-
const b: number = groupMatrix[1];
|
|
89
|
-
const c: number = groupMatrix[2];
|
|
90
|
-
const d: number = groupMatrix[3];
|
|
91
|
-
const e: number = groupMatrix[4];
|
|
92
|
-
const f: number = groupMatrix[5];
|
|
93
|
-
|
|
94
|
-
const newX = a * (textObject.left ?? 0) + c * (textObject.top ?? 0) + e;
|
|
95
|
-
const newY = b * (textObject.left ?? 0) + d * (textObject.top ?? 0) + f;
|
|
96
|
-
|
|
97
|
-
const tempText = new (textObject.constructor as typeof fabric.IText)(
|
|
98
|
-
textObject.text ?? '',
|
|
99
|
-
{
|
|
100
|
-
...textObjectJSON,
|
|
101
|
-
scaleX: textObjectJSON.scaleX * a,
|
|
102
|
-
scaleY: textObjectJSON.scaleY * a,
|
|
103
|
-
textAlign: textObject.textAlign,
|
|
104
|
-
left: newX,
|
|
105
|
-
top: newY,
|
|
106
|
-
styles: textObject.styles,
|
|
107
|
-
groupCopyed: textObject.group,
|
|
108
|
-
}
|
|
109
|
-
);
|
|
110
|
-
tempText.id = uuid();
|
|
111
|
-
textObject.visible = false;
|
|
112
|
-
groupObj.addWithUpdate();
|
|
113
|
-
tempText.visible = true;
|
|
114
|
-
tempText.selectable = true;
|
|
115
|
-
tempText.hasControls = false;
|
|
116
|
-
tempText.editable = true;
|
|
117
|
-
this.canvas.add(tempText);
|
|
118
|
-
this.canvas.setActiveObject(tempText);
|
|
119
|
-
tempText.enterEditing();
|
|
120
|
-
tempText.selectAll();
|
|
121
|
-
|
|
122
|
-
tempText.on('editing:exited', () => {
|
|
123
|
-
const attrs = tempText.toObject();
|
|
124
|
-
|
|
125
|
-
// 进入编辑模式时触发
|
|
126
|
-
textObject.set({
|
|
127
|
-
...pick(attrs, [
|
|
128
|
-
'fill',
|
|
129
|
-
'fontSize',
|
|
130
|
-
'fontStyle',
|
|
131
|
-
'fontFamily',
|
|
132
|
-
'lineHeight',
|
|
133
|
-
'backgroundColor',
|
|
134
|
-
]),
|
|
135
|
-
text: tempText.text,
|
|
136
|
-
visible: true,
|
|
137
|
-
});
|
|
138
|
-
groupObj.addWithUpdate();
|
|
139
|
-
tempText.visible = false;
|
|
140
|
-
this.canvas.remove(tempText);
|
|
141
|
-
this.canvas.setActiveObject(groupObj);
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// 绑定编辑取消事件
|
|
146
|
-
_bedingEditingEvent(
|
|
147
|
-
textObject: fabric.IText,
|
|
148
|
-
opt: fabric.IEvent<MouseEvent>
|
|
149
|
-
) {
|
|
150
|
-
if (!opt.target) return;
|
|
151
|
-
const left = opt.target.left;
|
|
152
|
-
const top = opt.target.top;
|
|
153
|
-
const ids = this._unGroup() || [];
|
|
154
|
-
|
|
155
|
-
const resetGroup = () => {
|
|
156
|
-
const groupArr = this.canvas
|
|
157
|
-
.getObjects()
|
|
158
|
-
.filter((item) => item.id && ids.includes(item.id));
|
|
159
|
-
// 删除元素
|
|
160
|
-
groupArr.forEach((item) => this.canvas.remove(item));
|
|
161
|
-
|
|
162
|
-
// 生成新组
|
|
163
|
-
const group = new fabric.Group([...groupArr]);
|
|
164
|
-
group.set('left', left);
|
|
165
|
-
group.set('top', top);
|
|
166
|
-
group.set('id', uuid());
|
|
167
|
-
textObject.off('editing:exited', resetGroup);
|
|
168
|
-
this.canvas.add(group);
|
|
169
|
-
this.canvas.discardActiveObject().renderAll();
|
|
170
|
-
};
|
|
171
|
-
// 绑定取消事件
|
|
172
|
-
textObject.on('editing:exited', resetGroup);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// 拆分组合并返回ID
|
|
176
|
-
_unGroup() {
|
|
177
|
-
const ids: string[] = [];
|
|
178
|
-
const activeObj = this.canvas.getActiveObject() as fabric.Group;
|
|
179
|
-
if (!activeObj) return;
|
|
180
|
-
activeObj.getObjects().forEach((item) => {
|
|
181
|
-
const id = uuid();
|
|
182
|
-
ids.push(id);
|
|
183
|
-
item.set('id', id);
|
|
184
|
-
});
|
|
185
|
-
activeObj.toActiveSelection();
|
|
186
|
-
return ids;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
isText(obj: fabric.Object) {
|
|
190
|
-
return obj.type && ['i-text', 'text', 'textbox'].includes(obj.type);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
destroy() {
|
|
194
|
-
console.log('pluginDestroy');
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export default GroupTextEditorPlugin;
|
|
1
|
+
import { fabric } from '@hprint/core';
|
|
2
|
+
import { utils } from '@hprint/shared';
|
|
3
|
+
import { v4 as uuid } from 'uuid';
|
|
4
|
+
import { pick } from 'lodash-es';
|
|
5
|
+
import type { IEditor, IPluginTempl } from '@hprint/core';
|
|
6
|
+
|
|
7
|
+
class GroupTextEditorPlugin implements IPluginTempl {
|
|
8
|
+
static pluginName = 'GroupTextEditorPlugin';
|
|
9
|
+
isDown = false;
|
|
10
|
+
constructor(
|
|
11
|
+
public canvas: fabric.Canvas,
|
|
12
|
+
public editor: IEditor
|
|
13
|
+
) {
|
|
14
|
+
this._init();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// 组内文本输入
|
|
18
|
+
_init() {
|
|
19
|
+
this.canvas.on('mouse:down', (opt) => {
|
|
20
|
+
this.isDown = true;
|
|
21
|
+
// 重置选中controls
|
|
22
|
+
if (
|
|
23
|
+
opt.target &&
|
|
24
|
+
!opt.target.lockMovementX &&
|
|
25
|
+
!opt.target.lockMovementY &&
|
|
26
|
+
!opt.target.lockRotation &&
|
|
27
|
+
!opt.target.lockScalingX &&
|
|
28
|
+
!opt.target.lockScalingY
|
|
29
|
+
) {
|
|
30
|
+
opt.target.hasControls = true;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
this.canvas.on('mouse:up', () => {
|
|
35
|
+
this.isDown = false;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
this.canvas.on('mouse:dblclick', (opt) => {
|
|
39
|
+
if (utils.isGroup(opt.target)) {
|
|
40
|
+
const selectedObject = this._getGroupObj(opt) as fabric.IText;
|
|
41
|
+
if (!selectedObject) return;
|
|
42
|
+
selectedObject.selectable = true;
|
|
43
|
+
// 由于组内的元素,双击以后会导致controls偏移,因此隐藏他
|
|
44
|
+
if (selectedObject.hasControls) {
|
|
45
|
+
selectedObject.hasControls = false;
|
|
46
|
+
}
|
|
47
|
+
if (this.isText(selectedObject)) {
|
|
48
|
+
this._bedingTextEditingEvent(selectedObject, opt.target);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
this.canvas.setActiveObject(selectedObject);
|
|
52
|
+
this.canvas.renderAll();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 获取点击区域内的组内文字元素
|
|
58
|
+
_getGroupTextObj(opt: fabric.IEvent<MouseEvent>) {
|
|
59
|
+
const pointer = this.canvas.getPointer(opt.e, true);
|
|
60
|
+
if (!utils.isGroup(opt.target)) return false;
|
|
61
|
+
const clickObj = this.canvas._searchPossibleTargets(
|
|
62
|
+
opt.target._objects,
|
|
63
|
+
pointer
|
|
64
|
+
);
|
|
65
|
+
if (clickObj && this.isText(clickObj)) {
|
|
66
|
+
return clickObj;
|
|
67
|
+
}
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_getGroupObj(opt: fabric.IEvent<MouseEvent>) {
|
|
72
|
+
const pointer = this.canvas.getPointer(opt.e, true);
|
|
73
|
+
if (!utils.isGroup(opt.target)) return false;
|
|
74
|
+
const clickObj = this.canvas._searchPossibleTargets(
|
|
75
|
+
opt.target._objects,
|
|
76
|
+
pointer
|
|
77
|
+
);
|
|
78
|
+
return clickObj;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// 通过组合重新组装来编辑文字,可能会耗性能。
|
|
82
|
+
_bedingTextEditingEvent(textObject: fabric.IText, groupObj: fabric.Group) {
|
|
83
|
+
const textObjectJSON = textObject.toObject();
|
|
84
|
+
|
|
85
|
+
const groupMatrix: number[] = groupObj.calcTransformMatrix();
|
|
86
|
+
|
|
87
|
+
const a: number = groupMatrix[0];
|
|
88
|
+
const b: number = groupMatrix[1];
|
|
89
|
+
const c: number = groupMatrix[2];
|
|
90
|
+
const d: number = groupMatrix[3];
|
|
91
|
+
const e: number = groupMatrix[4];
|
|
92
|
+
const f: number = groupMatrix[5];
|
|
93
|
+
|
|
94
|
+
const newX = a * (textObject.left ?? 0) + c * (textObject.top ?? 0) + e;
|
|
95
|
+
const newY = b * (textObject.left ?? 0) + d * (textObject.top ?? 0) + f;
|
|
96
|
+
|
|
97
|
+
const tempText = new (textObject.constructor as typeof fabric.IText)(
|
|
98
|
+
textObject.text ?? '',
|
|
99
|
+
{
|
|
100
|
+
...textObjectJSON,
|
|
101
|
+
scaleX: textObjectJSON.scaleX * a,
|
|
102
|
+
scaleY: textObjectJSON.scaleY * a,
|
|
103
|
+
textAlign: textObject.textAlign,
|
|
104
|
+
left: newX,
|
|
105
|
+
top: newY,
|
|
106
|
+
styles: textObject.styles,
|
|
107
|
+
groupCopyed: textObject.group,
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
tempText.id = uuid();
|
|
111
|
+
textObject.visible = false;
|
|
112
|
+
groupObj.addWithUpdate();
|
|
113
|
+
tempText.visible = true;
|
|
114
|
+
tempText.selectable = true;
|
|
115
|
+
tempText.hasControls = false;
|
|
116
|
+
tempText.editable = true;
|
|
117
|
+
this.canvas.add(tempText);
|
|
118
|
+
this.canvas.setActiveObject(tempText);
|
|
119
|
+
tempText.enterEditing();
|
|
120
|
+
tempText.selectAll();
|
|
121
|
+
|
|
122
|
+
tempText.on('editing:exited', () => {
|
|
123
|
+
const attrs = tempText.toObject();
|
|
124
|
+
|
|
125
|
+
// 进入编辑模式时触发
|
|
126
|
+
textObject.set({
|
|
127
|
+
...pick(attrs, [
|
|
128
|
+
'fill',
|
|
129
|
+
'fontSize',
|
|
130
|
+
'fontStyle',
|
|
131
|
+
'fontFamily',
|
|
132
|
+
'lineHeight',
|
|
133
|
+
'backgroundColor',
|
|
134
|
+
]),
|
|
135
|
+
text: tempText.text,
|
|
136
|
+
visible: true,
|
|
137
|
+
});
|
|
138
|
+
groupObj.addWithUpdate();
|
|
139
|
+
tempText.visible = false;
|
|
140
|
+
this.canvas.remove(tempText);
|
|
141
|
+
this.canvas.setActiveObject(groupObj);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 绑定编辑取消事件
|
|
146
|
+
_bedingEditingEvent(
|
|
147
|
+
textObject: fabric.IText,
|
|
148
|
+
opt: fabric.IEvent<MouseEvent>
|
|
149
|
+
) {
|
|
150
|
+
if (!opt.target) return;
|
|
151
|
+
const left = opt.target.left;
|
|
152
|
+
const top = opt.target.top;
|
|
153
|
+
const ids = this._unGroup() || [];
|
|
154
|
+
|
|
155
|
+
const resetGroup = () => {
|
|
156
|
+
const groupArr = this.canvas
|
|
157
|
+
.getObjects()
|
|
158
|
+
.filter((item) => item.id && ids.includes(item.id));
|
|
159
|
+
// 删除元素
|
|
160
|
+
groupArr.forEach((item) => this.canvas.remove(item));
|
|
161
|
+
|
|
162
|
+
// 生成新组
|
|
163
|
+
const group = new fabric.Group([...groupArr]);
|
|
164
|
+
group.set('left', left);
|
|
165
|
+
group.set('top', top);
|
|
166
|
+
group.set('id', uuid());
|
|
167
|
+
textObject.off('editing:exited', resetGroup);
|
|
168
|
+
this.canvas.add(group);
|
|
169
|
+
this.canvas.discardActiveObject().renderAll();
|
|
170
|
+
};
|
|
171
|
+
// 绑定取消事件
|
|
172
|
+
textObject.on('editing:exited', resetGroup);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 拆分组合并返回ID
|
|
176
|
+
_unGroup() {
|
|
177
|
+
const ids: string[] = [];
|
|
178
|
+
const activeObj = this.canvas.getActiveObject() as fabric.Group;
|
|
179
|
+
if (!activeObj) return;
|
|
180
|
+
activeObj.getObjects().forEach((item) => {
|
|
181
|
+
const id = uuid();
|
|
182
|
+
ids.push(id);
|
|
183
|
+
item.set('id', id);
|
|
184
|
+
});
|
|
185
|
+
activeObj.toActiveSelection();
|
|
186
|
+
return ids;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
isText(obj: fabric.Object) {
|
|
190
|
+
return obj.type && ['i-text', 'text', 'textbox'].includes(obj.type);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
destroy() {
|
|
194
|
+
console.log('pluginDestroy');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export default GroupTextEditorPlugin;
|