Skip to content

Commit a7d487c

Browse files
qcjiaminqc
andauthored
feat: 完善锁定插件,画布内增加锁定控制图标 (#550)
Co-authored-by: qc <qiuchen610714354@gmail.com>
1 parent 4715a98 commit a7d487c

File tree

5 files changed

+110
-11
lines changed

5 files changed

+110
-11
lines changed

.eslintrc-auto-import.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,4 @@
7171
"watchPostEffect": true,
7272
"watchSyncEffect": true
7373
}
74-
}
74+
}

packages/core/assets/lock.svg

Lines changed: 7 additions & 0 deletions
Loading

packages/core/plugin/LockPlugin.ts

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
* @Description: 锁定文件
77
*/
88
import { fabric } from 'fabric';
9-
import { SelectMode } from '../eventType';
9+
import { SelectEvent, SelectMode } from '../eventType';
1010
import type { IEditor, IPluginTempl } from '@kuaitu/core';
11+
import lockImg from '../assets/lock.svg?url';
12+
// import lockImg from '../assets/rotateicon.svg?url';
13+
// import unlockImg from '../assets/unlock.svg?url'
1114

1215
type IPlugin = Pick<LockPlugin, 'lock' | 'unLock'>;
1316

@@ -24,13 +27,100 @@ enum ItypeKey {
2427
lockScalingY = 'lockScalingY',
2528
}
2629

30+
enum IControlKey {
31+
bl = 'bl',
32+
br = 'br',
33+
mb = 'mb',
34+
ml = 'ml',
35+
mr = 'mr',
36+
mt = 'mt',
37+
tl = 'tl',
38+
tr = 'tr',
39+
mtr = 'mtr',
40+
lock = 'lock',
41+
}
42+
2743
export default class LockPlugin implements IPluginTempl {
2844
static pluginName = 'LockPlugin';
2945
static apis = ['lock', 'unLock'];
30-
constructor(public canvas: fabric.Canvas, public editor: IEditor) {}
46+
constructor(public canvas: fabric.Canvas, public editor: IEditor) {
47+
this.init();
48+
}
49+
50+
init() {
51+
const imgEl = document.createElement('img');
52+
imgEl.src = lockImg;
53+
const that = this;
54+
function renderIcon(
55+
ctx: CanvasRenderingContext2D,
56+
left: number,
57+
top: number,
58+
styleOverride: any,
59+
fabricObject: fabric.Object
60+
) {
61+
const iconWith = 25;
62+
ctx.save();
63+
ctx.translate(left, top);
64+
const angle = fabricObject.angle as number;
65+
ctx.rotate(fabric.util.degreesToRadians(angle));
66+
ctx.drawImage(imgEl, -iconWith / 2, -iconWith / 2, iconWith, iconWith);
67+
ctx.restore();
68+
}
69+
70+
function unLockObject(eventData: any, transform: any): boolean {
71+
that.unLock();
72+
return true;
73+
}
74+
75+
fabric.Object.prototype.controls.lock = new fabric.Control({
76+
x: 0.5,
77+
y: 0.5,
78+
offsetY: 0,
79+
cursorStyle: 'pointer',
80+
mouseUpHandler: unLockObject,
81+
render: renderIcon,
82+
});
83+
84+
fabric.Textbox.prototype.controls.lock = new fabric.Control({
85+
x: 0.5,
86+
y: 0.5,
87+
offsetY: 0,
88+
cursorStyle: 'pointer',
89+
mouseUpHandler: unLockObject,
90+
render: renderIcon,
91+
});
92+
this.canvas.on('selection:created', () => this.renderCornerByActiveObj());
93+
this.canvas.on('selection:updated', () => this.renderCornerByActiveObj());
94+
}
95+
96+
controlCornersVisible(obj: fabric.Object) {
97+
const isLocked = obj.lockMovementX;
98+
Object.values(IControlKey).forEach((key: IControlKey) => {
99+
if (key === IControlKey.lock) {
100+
obj.setControlVisible(key, isLocked);
101+
} else {
102+
obj.setControlVisible(key, !isLocked);
103+
}
104+
});
105+
}
106+
107+
renderCornerByActiveObj() {
108+
const actives = this.canvas
109+
.getActiveObjects()
110+
.filter((item) => !(item instanceof fabric.GuideLine));
111+
if (actives && actives.length === 1) {
112+
const active = actives[0];
113+
this.controlCornersVisible(active);
114+
} else if (actives && actives.length > 1) {
115+
const active = this.canvas.getActiveObject();
116+
if (active) {
117+
this.controlCornersVisible(active);
118+
}
119+
}
120+
}
31121

32122
hookImportAfter() {
33-
this.canvas.forEachObject((obj) => {
123+
this.canvas.forEachObject((obj: fabric.Object) => {
34124
if (obj.hasControls === false && obj.selectable === false) {
35125
this.canvas.setActiveObject(obj);
36126
this.lock();
@@ -42,14 +132,13 @@ export default class LockPlugin implements IPluginTempl {
42132
lock() {
43133
const activeObject = this.canvas.getActiveObject() as fabric.Object;
44134
if (activeObject) {
45-
activeObject.hasControls = false;
46-
activeObject.selectable = false;
47-
activeObject.evented = false;
48135
// 修改默认属性
49136
Object.values(ItypeKey).forEach((key: ItypeKey) => {
50137
activeObject[key] = true;
51138
});
52-
this.canvas.discardActiveObject().renderAll();
139+
this.controlCornersVisible(activeObject);
140+
this.canvas.renderAll();
141+
this.editor.emit(SelectEvent.ONE, [activeObject]);
53142
}
54143
}
55144

@@ -63,7 +152,9 @@ export default class LockPlugin implements IPluginTempl {
63152
Object.values(ItypeKey).forEach((key: ItypeKey) => {
64153
activeObject[key] = false;
65154
});
66-
this.canvas.discardActiveObject().renderAll();
155+
this.controlCornersVisible(activeObject);
156+
this.canvas.renderAll();
157+
this.editor.emit(SelectEvent.ONE, [activeObject]);
67158
}
68159
}
69160

src/components/lock.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
-->
88

99
<template>
10-
<Tooltip :content="$t('quick.lock')" v-if="isOne">
10+
<Tooltip :content="isLock ? $t('quick.unlock') : $t('quick.lock')" v-if="isOne">
1111
<Button long v-if="isLock" @click="doLock(false)" icon="md-lock" type="text"></Button>
1212
<Button long v-else @click="doLock(true)" icon="md-unlock" type="text"></Button>
1313
</Tooltip>
@@ -24,7 +24,7 @@ const doLock = (isLock) => {
2424
};
2525
2626
const handleSelected = (items) => {
27-
isLock.value = !items[0].selectable;
27+
isLock.value = items[0].lockMovementX;
2828
};
2929
3030
onMounted(() => {

src/language/zh.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
"del": "删除",
156156
"copy": "复制",
157157
"lock": "锁定",
158+
"unlock": "解锁",
158159
"hide": "隐藏",
159160
"editPoly": "编辑多边形"
160161
},

0 commit comments

Comments
 (0)