@gedit/editor-2d 0.3.14 → 0.3.17
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/lib/browser/editor2d-contribution.d.ts.map +1 -1
- package/lib/browser/editor2d-contribution.js +19 -18
- package/lib/browser/editor2d-contribution.js.map +1 -1
- package/lib/browser/playground/canvas-layer.d.ts +2 -1
- package/lib/browser/playground/canvas-layer.d.ts.map +1 -1
- package/lib/browser/playground/canvas-layer.js +8 -1
- package/lib/browser/playground/canvas-layer.js.map +1 -1
- package/lib/browser/playground/path-edit/path-edit-layer-move-point.d.ts.map +1 -1
- package/lib/browser/playground/path-edit/path-edit-layer-move-point.js +38 -4
- package/lib/browser/playground/path-edit/path-edit-layer-move-point.js.map +1 -1
- package/lib/browser/playground/path-edit/path-edit-layer-svg-path.d.ts +9 -2
- package/lib/browser/playground/path-edit/path-edit-layer-svg-path.d.ts.map +1 -1
- package/lib/browser/playground/path-edit/path-edit-layer-svg-path.js +232 -13
- package/lib/browser/playground/path-edit/path-edit-layer-svg-path.js.map +1 -1
- package/lib/browser/playground/path-edit/utils.d.ts +16 -3
- package/lib/browser/playground/path-edit/utils.d.ts.map +1 -1
- package/lib/browser/playground/path-edit/utils.js +63 -13
- package/lib/browser/playground/path-edit/utils.js.map +1 -1
- package/lib/browser/playground/path-edit-layer.d.ts +46 -3
- package/lib/browser/playground/path-edit-layer.d.ts.map +1 -1
- package/lib/browser/playground/path-edit-layer.js +533 -171
- package/lib/browser/playground/path-edit-layer.js.map +1 -1
- package/lib/browser/playground/playground-contribution.d.ts.map +1 -1
- package/lib/browser/playground/playground-contribution.js +2 -0
- package/lib/browser/playground/playground-contribution.js.map +1 -1
- package/lib/browser/utils/bezier.path.utils.d.ts.map +1 -1
- package/lib/browser/utils/bezier.path.utils.js +3 -0
- package/lib/browser/utils/bezier.path.utils.js.map +1 -1
- package/package.json +7 -7
- package/src/browser/editor2d-contribution.ts +19 -18
- package/src/browser/playground/canvas-layer.ts +6 -1
- package/src/browser/playground/path-edit/path-edit-layer-move-point.tsx +50 -5
- package/src/browser/playground/path-edit/path-edit-layer-svg-path.tsx +303 -26
- package/src/browser/playground/path-edit/utils.tsx +82 -17
- package/src/browser/playground/path-edit-layer.tsx +585 -216
- package/src/browser/playground/playground-contribution.ts +2 -0
- package/src/browser/style/path-edit-layer.less +17 -5
- package/src/browser/svg/drag_path.svg +17 -0
- package/src/browser/utils/bezier.path.utils.ts +3 -0
|
@@ -17,6 +17,7 @@ import type { Editor2dDocument, Editor2dPathNode } from '../model';
|
|
|
17
17
|
import { PlaygroundContext2d } from './playground-context';
|
|
18
18
|
import { SelectableTreeNode, TreeSelection } from '@gedit/tree';
|
|
19
19
|
import {
|
|
20
|
+
asVec,
|
|
20
21
|
PathChild,
|
|
21
22
|
PathSchema,
|
|
22
23
|
PATH_FUNC_TYPE,
|
|
@@ -37,8 +38,13 @@ import {
|
|
|
37
38
|
updatePathNodeData,
|
|
38
39
|
inverseTransformToData,
|
|
39
40
|
transformToData,
|
|
41
|
+
shiftAngleArray,
|
|
40
42
|
} from './path-edit';
|
|
41
43
|
|
|
44
|
+
import { Command } from '@gedit/command';
|
|
45
|
+
import { isOSX } from '@gedit/application-common';
|
|
46
|
+
import { getParallelPositionByPoint } from '../utils/bezier.path.utils';
|
|
47
|
+
|
|
42
48
|
export interface PathEditLayerEventContextProps {
|
|
43
49
|
onPointMouseDown: (e: React.MouseEvent, p: PathChild) => void;
|
|
44
50
|
onClosePath: () => void;
|
|
@@ -53,11 +59,52 @@ export interface PathEditLayerEventContextProps {
|
|
|
53
59
|
key: string
|
|
54
60
|
) => void;
|
|
55
61
|
onPathAddPoint: (index: number, e: React.MouseEvent) => void;
|
|
62
|
+
isShiftKey?: boolean;
|
|
63
|
+
isCtrlKey?: boolean;
|
|
56
64
|
}
|
|
57
65
|
export const PathEditLayerEventContext = React.createContext<PathEditLayerEventContextProps>(
|
|
58
66
|
{} as PathEditLayerEventContextProps
|
|
59
67
|
);
|
|
60
68
|
|
|
69
|
+
export namespace Editor2dPathKeyCommands {
|
|
70
|
+
const EDITOR2D_PATH_CATEGORY = 'Editor2dPath';
|
|
71
|
+
export const TAB_PATH: Command = {
|
|
72
|
+
id: 'editor2d.path.tab',
|
|
73
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
74
|
+
label: '下一个点',
|
|
75
|
+
};
|
|
76
|
+
// export const SHOW_ALL_BEZIER: Command = {
|
|
77
|
+
// id: 'editor2d.path.showAllBezier',
|
|
78
|
+
// category: EDITOR2D_PATH_CATEGORY,
|
|
79
|
+
// label: '显示全部贝塞尔点',
|
|
80
|
+
// };
|
|
81
|
+
export const SELECT_All: Command = {
|
|
82
|
+
id: 'editor2d.path.selectAll',
|
|
83
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
84
|
+
label: '选择全部',
|
|
85
|
+
};
|
|
86
|
+
export const BEZIER_STRAIGHT: Command = {
|
|
87
|
+
id: 'editor2d.path.bezierStraight',
|
|
88
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
89
|
+
label: '无贝塞尔',
|
|
90
|
+
};
|
|
91
|
+
export const BEZIER_EQUAL: Command = {
|
|
92
|
+
id: 'editor2d.path.bezierEqual',
|
|
93
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
94
|
+
label: '左右相等',
|
|
95
|
+
};
|
|
96
|
+
export const BEZIER_BREAK: Command = {
|
|
97
|
+
id: 'editor2d.path.bezierBreak',
|
|
98
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
99
|
+
label: '左右断开',
|
|
100
|
+
};
|
|
101
|
+
export const BEZIER_UNEQUAL: Command = {
|
|
102
|
+
id: 'editor2d.path.bezierUnequal',
|
|
103
|
+
category: EDITOR2D_PATH_CATEGORY,
|
|
104
|
+
label: '左右不相等',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
61
108
|
/**
|
|
62
109
|
* 动态绘制层
|
|
63
110
|
*/
|
|
@@ -75,6 +122,34 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
75
122
|
currentPathNode?: Editor2dPathNode;
|
|
76
123
|
startPos?: PathChild;
|
|
77
124
|
|
|
125
|
+
// 显示全部贝塞尔点
|
|
126
|
+
protected altKey = false;
|
|
127
|
+
|
|
128
|
+
// 按住 shit 键
|
|
129
|
+
protected shiftKey = false;
|
|
130
|
+
|
|
131
|
+
// 按住 ctrl 或 ⌘ 键;
|
|
132
|
+
protected ctrlKey = false;
|
|
133
|
+
|
|
134
|
+
// 历史记录
|
|
135
|
+
// protected history:
|
|
136
|
+
|
|
137
|
+
protected historyUri?: string;
|
|
138
|
+
|
|
139
|
+
protected _historyIndex = 0;
|
|
140
|
+
|
|
141
|
+
protected noHistory = false;
|
|
142
|
+
|
|
143
|
+
get historyIndex(): number {
|
|
144
|
+
const h = this._historyIndex;
|
|
145
|
+
this._historyIndex++;
|
|
146
|
+
return h;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
set historyIndex(h: number) {
|
|
150
|
+
this._historyIndex = h;
|
|
151
|
+
}
|
|
152
|
+
|
|
78
153
|
// 访录当前图层在 timeline 里的监听事件
|
|
79
154
|
layerDisposeMap = new Map<string, Disposable>();
|
|
80
155
|
protected bezierStartPos?: {
|
|
@@ -105,13 +180,14 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
105
180
|
}
|
|
106
181
|
|
|
107
182
|
reNodeData(): void {
|
|
183
|
+
this.clearHistory();
|
|
108
184
|
this.currentPathNode = undefined;
|
|
109
185
|
this.startPos = undefined;
|
|
110
186
|
this.pathPointSelection!.clearSelection();
|
|
111
187
|
this.pathPointSelection!.selectMode = PathSelectMode.ADD_PATH;
|
|
112
188
|
this.docDispose?.dispose();
|
|
113
189
|
}
|
|
114
|
-
updateNodeData(): void {
|
|
190
|
+
updateNodeData(noHistory?: boolean): void {
|
|
115
191
|
if (!this.currentPathNode) {
|
|
116
192
|
return;
|
|
117
193
|
}
|
|
@@ -119,7 +195,69 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
119
195
|
// console.log('updateNodeData', nodeData);
|
|
120
196
|
// 直接更新数据,,动画 updateAnimationNode 里会把数据删了;
|
|
121
197
|
this.currentPathNode.path = nodeData.path;
|
|
198
|
+
this.currentPathNode.selected = true;
|
|
122
199
|
this.document?.updateNode(this.currentPathNode, nodeData, true);
|
|
200
|
+
this.addHistoryData(noHistory);
|
|
201
|
+
}
|
|
202
|
+
reloadNodeData(content: string): void {
|
|
203
|
+
if (!this.currentPathNode || !this.pathPointSelection) {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const path = JSON.parse(content) as PathSchema;
|
|
207
|
+
this.currentPathNode.path = path;
|
|
208
|
+
this.document?.updateNode(this.currentPathNode, { path }, true);
|
|
209
|
+
this.pathPointSelection.selection = path.paths[path.paths.length - 1]
|
|
210
|
+
? [{ pointId: path.paths[path.paths.length - 1].id }]
|
|
211
|
+
: [];
|
|
212
|
+
if (!path.paths.length) {
|
|
213
|
+
this.pathPointSelection.enterPathMode([]);
|
|
214
|
+
}
|
|
215
|
+
this.draw();
|
|
216
|
+
}
|
|
217
|
+
clearHistory(): void {
|
|
218
|
+
if (this.historyUri) {
|
|
219
|
+
this.context.historyService.clearHistory(this.historyUri);
|
|
220
|
+
this.historyUri = undefined;
|
|
221
|
+
this.context.historyService.switchHistory(this.context.document.uri);
|
|
222
|
+
}
|
|
223
|
+
this.historyIndex = 0;
|
|
224
|
+
}
|
|
225
|
+
addHistoryData(noHistory?: boolean): void {
|
|
226
|
+
const nodePath = this.currentPathNode?.path;
|
|
227
|
+
if (!nodePath || noHistory || !this.historyUri) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const index = this.historyIndex;
|
|
232
|
+
this.context.historyService.add(this.historyUri, {
|
|
233
|
+
key: index,
|
|
234
|
+
data: {
|
|
235
|
+
content: JSON.stringify(nodePath),
|
|
236
|
+
resource: {
|
|
237
|
+
reload: (content: string) => {
|
|
238
|
+
this.reloadNodeData(content);
|
|
239
|
+
},
|
|
240
|
+
resource: {
|
|
241
|
+
uri: this.historyUri,
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
createHistory(): void {
|
|
248
|
+
if (!this.currentPathNode) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
this.historyUri = `${this.context.document.uri}?${this.currentPathNode?.id}`;
|
|
252
|
+
if (this.context.historyService.currentUri !== this.historyUri) {
|
|
253
|
+
this.context.historyService.switchHistory(this.historyUri);
|
|
254
|
+
if (
|
|
255
|
+
!this.context.historyService.getHistoryNavigator(this.historyUri)
|
|
256
|
+
?.length
|
|
257
|
+
) {
|
|
258
|
+
this.addHistoryData();
|
|
259
|
+
}
|
|
260
|
+
}
|
|
123
261
|
}
|
|
124
262
|
// updateNodePathData(): void {
|
|
125
263
|
// if (!this.currentPathNode) {
|
|
@@ -237,14 +375,199 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
237
375
|
}
|
|
238
376
|
}
|
|
239
377
|
|
|
378
|
+
protected updateCurrentPointBezierType(type: PATH_FUNC_TYPE): void {
|
|
379
|
+
if (!this.currentPathNode || !this.pathPointSelection) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
const { selection = [] } = this.pathPointSelection;
|
|
383
|
+
selection.forEach(item => {
|
|
384
|
+
const path = this.currentPathNode!.path;
|
|
385
|
+
const point = path.paths.find(c => c.id === item.pointId);
|
|
386
|
+
if (point) {
|
|
387
|
+
point.type = type;
|
|
388
|
+
switch (type) {
|
|
389
|
+
case PATH_FUNC_TYPE.STRAIGHT:
|
|
390
|
+
delete point.x1;
|
|
391
|
+
delete point.y1;
|
|
392
|
+
delete point.x2;
|
|
393
|
+
delete point.y2;
|
|
394
|
+
break;
|
|
395
|
+
case PATH_FUNC_TYPE.EQUAL:
|
|
396
|
+
case PATH_FUNC_TYPE.UNEQUAL:
|
|
397
|
+
case PATH_FUNC_TYPE.BREAK: {
|
|
398
|
+
const inP1 = 'x1' in point && 'y1' in point;
|
|
399
|
+
const inP2 = 'x2' in point && 'y2' in point;
|
|
400
|
+
if (type === PATH_FUNC_TYPE.BREAK && inP1 && inP2) {
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
const index = path.paths.findIndex(c => c.id === point.id);
|
|
404
|
+
const prevPoint =
|
|
405
|
+
path.paths[index - 1] || path.paths[path.paths.length - 1];
|
|
406
|
+
const nextPoint = path.paths[index + 1] || path.paths[0];
|
|
407
|
+
// 计算平衡线;
|
|
408
|
+
// 点线长度计算两个点的长的距一半;
|
|
409
|
+
const { p1, p2 /* isReverse */ } = getParallelPositionByPoint(
|
|
410
|
+
prevPoint,
|
|
411
|
+
nextPoint,
|
|
412
|
+
point
|
|
413
|
+
);
|
|
414
|
+
if (type === PATH_FUNC_TYPE.BREAK) {
|
|
415
|
+
if (inP1 && !inP2) {
|
|
416
|
+
point.x2 = p2.x;
|
|
417
|
+
point.y2 = p2.y;
|
|
418
|
+
} else if (inP2 && !inP1) {
|
|
419
|
+
point.x1 = p1.x;
|
|
420
|
+
point.y1 = p1.y;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
point.x1 = p1.x;
|
|
424
|
+
point.y1 = p1.y;
|
|
425
|
+
point.x2 = p2.x;
|
|
426
|
+
point.y2 = p2.y;
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
default:
|
|
431
|
+
break;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
this.updateNodeData();
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
protected registerKeybindings(): Disposable[] {
|
|
439
|
+
const ctrlKey = !isOSX ? 'control' : 'meta';
|
|
440
|
+
return [
|
|
441
|
+
// alt shift 之类在 keybindings 里面不能单个做快捷键
|
|
442
|
+
this.listenGlobalEvent('keydown', e => {
|
|
443
|
+
// alt 显示全部贝赛尔点
|
|
444
|
+
if (this.isEnabled && e.key.toLowerCase() === 'alt') {
|
|
445
|
+
this.altKey = true;
|
|
446
|
+
this.draw();
|
|
447
|
+
}
|
|
448
|
+
if (this.isEnabled && e.key.toLowerCase() === 'shift') {
|
|
449
|
+
this.shiftKey = true;
|
|
450
|
+
this.draw();
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (this.isEnabled && e.key.toLowerCase() === ctrlKey) {
|
|
454
|
+
this.ctrlKey = true;
|
|
455
|
+
this.draw();
|
|
456
|
+
}
|
|
457
|
+
}),
|
|
458
|
+
this.listenGlobalEvent('keyup', (e: KeyboardEvent) => {
|
|
459
|
+
if (this.isEnabled && e.key.toLowerCase() === 'alt') {
|
|
460
|
+
this.altKey = false;
|
|
461
|
+
this.draw();
|
|
462
|
+
}
|
|
463
|
+
if (this.isEnabled && e.key.toLowerCase() === 'shift') {
|
|
464
|
+
this.shiftKey = false;
|
|
465
|
+
this.draw();
|
|
466
|
+
}
|
|
467
|
+
if (this.isEnabled && e.key.toLowerCase() === ctrlKey) {
|
|
468
|
+
this.ctrlKey = false;
|
|
469
|
+
this.draw();
|
|
470
|
+
}
|
|
471
|
+
}),
|
|
472
|
+
// tab 切换点
|
|
473
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.TAB_PATH, {
|
|
474
|
+
execute: () => {
|
|
475
|
+
const currentPoint = this.pathPointSelection.selection?.[0]?.pointId;
|
|
476
|
+
const { paths = [] } = this.currentPathNode?.path || {};
|
|
477
|
+
const index = currentPoint
|
|
478
|
+
? paths.findIndex(c => c.id === currentPoint)
|
|
479
|
+
: -1;
|
|
480
|
+
let nextPoint;
|
|
481
|
+
if (index === -1) {
|
|
482
|
+
nextPoint = paths[0];
|
|
483
|
+
} else {
|
|
484
|
+
nextPoint = paths[index + 1] || paths[0];
|
|
485
|
+
}
|
|
486
|
+
this.selectionChange(nextPoint);
|
|
487
|
+
},
|
|
488
|
+
isEnabled: () => !!this.isEnabled,
|
|
489
|
+
}),
|
|
490
|
+
this.keybindings.registerKeybindings({
|
|
491
|
+
command: Editor2dPathKeyCommands.TAB_PATH.id,
|
|
492
|
+
keybinding: 'tab',
|
|
493
|
+
when: 'editor2dWidgetFocus',
|
|
494
|
+
}),
|
|
495
|
+
// all 全选
|
|
496
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.SELECT_All, {
|
|
497
|
+
execute: () => {
|
|
498
|
+
if (!this.currentPathNode || !this.pathPointSelection) {
|
|
499
|
+
return;
|
|
500
|
+
}
|
|
501
|
+
const { paths = [] } = this.currentPathNode.path;
|
|
502
|
+
const selection = paths.map(c => ({
|
|
503
|
+
pointId: c.id,
|
|
504
|
+
}));
|
|
505
|
+
this.pathPointSelection.enterSelectBezierMode(selection);
|
|
506
|
+
},
|
|
507
|
+
isEnabled: () => !!this.isEnabled,
|
|
508
|
+
}),
|
|
509
|
+
this.keybindings.registerKeybindings({
|
|
510
|
+
command: Editor2dPathKeyCommands.SELECT_All.id,
|
|
511
|
+
keybinding: isOSX ? 'cmd+a' : 'ctrl+a',
|
|
512
|
+
when: 'editor2dWidgetFocus',
|
|
513
|
+
}),
|
|
514
|
+
// 贝赛尔点
|
|
515
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.BEZIER_STRAIGHT, {
|
|
516
|
+
execute: () => {
|
|
517
|
+
this.updateCurrentPointBezierType(PATH_FUNC_TYPE.STRAIGHT);
|
|
518
|
+
},
|
|
519
|
+
isEnabled: () => !!this.isEnabled,
|
|
520
|
+
}),
|
|
521
|
+
this.keybindings.registerKeybindings({
|
|
522
|
+
command: Editor2dPathKeyCommands.BEZIER_STRAIGHT.id,
|
|
523
|
+
keybinding: '1',
|
|
524
|
+
when: 'editor2dWidgetFocus',
|
|
525
|
+
}),
|
|
526
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.BEZIER_EQUAL, {
|
|
527
|
+
execute: () => {
|
|
528
|
+
this.updateCurrentPointBezierType(PATH_FUNC_TYPE.EQUAL);
|
|
529
|
+
},
|
|
530
|
+
isEnabled: () => !!this.isEnabled,
|
|
531
|
+
}),
|
|
532
|
+
this.keybindings.registerKeybindings({
|
|
533
|
+
command: Editor2dPathKeyCommands.BEZIER_EQUAL.id,
|
|
534
|
+
keybinding: '2',
|
|
535
|
+
when: 'editor2dWidgetFocus',
|
|
536
|
+
}),
|
|
537
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.BEZIER_BREAK, {
|
|
538
|
+
execute: () => {
|
|
539
|
+
this.updateCurrentPointBezierType(PATH_FUNC_TYPE.BREAK);
|
|
540
|
+
},
|
|
541
|
+
isEnabled: () => !!this.isEnabled,
|
|
542
|
+
}),
|
|
543
|
+
this.keybindings.registerKeybindings({
|
|
544
|
+
command: Editor2dPathKeyCommands.BEZIER_BREAK.id,
|
|
545
|
+
keybinding: '3',
|
|
546
|
+
when: 'editor2dWidgetFocus',
|
|
547
|
+
}),
|
|
548
|
+
this.commands.registerCommand(Editor2dPathKeyCommands.BEZIER_UNEQUAL, {
|
|
549
|
+
execute: () => {
|
|
550
|
+
this.updateCurrentPointBezierType(PATH_FUNC_TYPE.UNEQUAL);
|
|
551
|
+
},
|
|
552
|
+
isEnabled: () => !!this.isEnabled,
|
|
553
|
+
}),
|
|
554
|
+
this.keybindings.registerKeybindings({
|
|
555
|
+
command: Editor2dPathKeyCommands.BEZIER_UNEQUAL.id,
|
|
556
|
+
keybinding: '4',
|
|
557
|
+
when: 'editor2dWidgetFocus',
|
|
558
|
+
}),
|
|
559
|
+
];
|
|
560
|
+
}
|
|
561
|
+
|
|
240
562
|
onReady(): void {
|
|
241
563
|
this.addDispose([
|
|
242
|
-
this.
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
564
|
+
...this.registerKeybindings(),
|
|
565
|
+
// this.context.historyService.onHistoryBack(e => {
|
|
566
|
+
// this.reNodeData();
|
|
567
|
+
// this.pathPointSelection!.selectMode = PathSelectMode.ADD_PATH;
|
|
568
|
+
// this.pathPointSelection!.clearSelection();
|
|
569
|
+
// this.editorState.toDefaultState();
|
|
570
|
+
// }),
|
|
248
571
|
this.editorState.onStateChange(e => {
|
|
249
572
|
/**
|
|
250
573
|
* 1. 不是路径编辑状态时,清空数据
|
|
@@ -262,7 +585,6 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
262
585
|
return;
|
|
263
586
|
}
|
|
264
587
|
const selectNodes = this.document?.getSelectedNodes() || [];
|
|
265
|
-
|
|
266
588
|
const pathSelectsNodes = selectNodes.filter(
|
|
267
589
|
c => c.displayType === GameObjectBaseType.PATH
|
|
268
590
|
);
|
|
@@ -272,6 +594,7 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
272
594
|
this.currentPathNode = deepClone(
|
|
273
595
|
pathSelectsNodes[0]
|
|
274
596
|
) as Editor2dPathNode;
|
|
597
|
+
this.createHistory();
|
|
275
598
|
if (
|
|
276
599
|
this.currentPathNode.useAnimationId &&
|
|
277
600
|
this.document?.timelineService?.currentTimelineData &&
|
|
@@ -282,13 +605,17 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
282
605
|
this.onRegisterTimelineEvent();
|
|
283
606
|
}
|
|
284
607
|
|
|
285
|
-
const selectionNode = [
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
608
|
+
const selectionNode = this.currentPathNode.path.paths[
|
|
609
|
+
this.currentPathNode.path.paths.length - 1
|
|
610
|
+
]?.id
|
|
611
|
+
? [
|
|
612
|
+
{
|
|
613
|
+
pointId: this.currentPathNode.path.paths[
|
|
614
|
+
this.currentPathNode.path.paths.length - 1
|
|
615
|
+
].id,
|
|
616
|
+
},
|
|
617
|
+
]
|
|
618
|
+
: [];
|
|
292
619
|
this.currentPathNode.path.closed
|
|
293
620
|
? this.pathPointSelection.enterSelectBezierMode(selectionNode)
|
|
294
621
|
: this.pathPointSelection.enterPathMode(selectionNode);
|
|
@@ -360,28 +687,14 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
360
687
|
);
|
|
361
688
|
const { paths = [], closed } = this.currentPathNode?.path || {};
|
|
362
689
|
const pathSelects: PathPointSelection[] = [];
|
|
363
|
-
const {
|
|
364
|
-
position = { x: 0, y: 1 },
|
|
365
|
-
scale = { x: 1, y: 1 },
|
|
366
|
-
rotation = 0,
|
|
367
|
-
} = this.currentPathNode!;
|
|
368
|
-
const offset = this.getBoundsOffset();
|
|
369
|
-
const center = {
|
|
370
|
-
x: -offset.x,
|
|
371
|
-
y: -offset.y,
|
|
372
|
-
};
|
|
373
690
|
paths.forEach(p => {
|
|
374
|
-
const { x
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const r = transformToData({ x, y }, { scale, rotation }, center);
|
|
378
|
-
x = r.x + position.x;
|
|
379
|
-
y = r.y + position.y;
|
|
380
|
-
const wh = (4 / this.config.finalScale) * 2;
|
|
691
|
+
const { x, y } = this.pathPosToCanvasPos(p);
|
|
692
|
+
// 半径
|
|
693
|
+
const wh = 4 * this.config.finalScale;
|
|
381
694
|
if (
|
|
382
|
-
x >= selectBound.x && // 左
|
|
695
|
+
x - wh >= selectBound.x && // 左
|
|
383
696
|
x + wh <= selectBound.x + selectBound.width && // 右
|
|
384
|
-
y >= selectBound.y && // 上
|
|
697
|
+
y - wh >= selectBound.y && // 上
|
|
385
698
|
y + wh <= selectBound.y + selectBound.height // 下
|
|
386
699
|
) {
|
|
387
700
|
pathSelects.push({
|
|
@@ -413,102 +726,110 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
413
726
|
}
|
|
414
727
|
this.reNodeData();
|
|
415
728
|
}), */
|
|
729
|
+
// 拦掉画布点击事件,失焦再次点击时会触发 widget 的点击事件, 会聚焦到 widget 上
|
|
730
|
+
this.listenPlaygroundEvent('click', (event: MouseEvent) => {
|
|
731
|
+
if (this.isEnabled) {
|
|
732
|
+
event.preventDefault();
|
|
733
|
+
event.stopPropagation();
|
|
734
|
+
this.createHistory();
|
|
735
|
+
}
|
|
736
|
+
}),
|
|
416
737
|
// 画布新增点点击事件;
|
|
417
738
|
this.listenPlaygroundEvent('mousedown', (event: MouseEvent) => {
|
|
418
739
|
// 只在左键点击时绘制
|
|
419
|
-
if (event.buttons !== 1) {
|
|
740
|
+
if (event.buttons !== 1 || !this.isEnabled) {
|
|
420
741
|
return;
|
|
421
742
|
}
|
|
743
|
+
event.preventDefault();
|
|
744
|
+
event.stopPropagation();
|
|
422
745
|
this.startDrag(event.clientX, event.clientY, {
|
|
423
746
|
onDragStart: e => {
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
747
|
+
const { selectMode, selection } = this.pathPointSelection || {};
|
|
748
|
+
/**
|
|
749
|
+
* 拦截画布点击事件,不处理绘制;
|
|
750
|
+
* 1. 闭合路径时;
|
|
751
|
+
* 2. 带区域选择模式时;
|
|
752
|
+
* 3. 多点选择时;
|
|
753
|
+
*/
|
|
754
|
+
if (
|
|
755
|
+
// 判断当前 select 是否 path 路径
|
|
756
|
+
(this.currentPathNode && this.currentPathNode.path.closed) ||
|
|
757
|
+
selectMode !== PathSelectMode.ADD_PATH ||
|
|
758
|
+
(selection && selection.length > 1)
|
|
759
|
+
) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
let { x, y } = this.canvasPosToPathPos({
|
|
763
|
+
x: e.endPos.x / (this.config?.finalScale || 1),
|
|
764
|
+
y: e.endPos.y / (this.config?.finalScale || 1),
|
|
765
|
+
});
|
|
766
|
+
|
|
767
|
+
if (selection) {
|
|
768
|
+
const selectionPoint = selection[0];
|
|
769
|
+
const index =
|
|
770
|
+
this.currentPathNode?.path.paths.findIndex(
|
|
771
|
+
c => c.id === selectionPoint.pointId
|
|
772
|
+
) ?? -1;
|
|
773
|
+
const node = this.currentPathNode?.path.paths[index];
|
|
774
|
+
if (node) {
|
|
775
|
+
// 按住 ctrl 加点时;
|
|
776
|
+
if (this.ctrlKey && node.type !== PATH_FUNC_TYPE.STRAIGHT) {
|
|
777
|
+
const isReverse = index === 0;
|
|
778
|
+
if (isReverse) {
|
|
779
|
+
node.x1 = node.x;
|
|
780
|
+
node.y1 = node.y;
|
|
781
|
+
} else {
|
|
782
|
+
node.x2 = node.x;
|
|
783
|
+
node.y2 = node.y;
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
// 按住 shift 时,生成固定角度的点;
|
|
787
|
+
if (this.shiftKey) {
|
|
788
|
+
const arc = asVec(node, { x, y });
|
|
789
|
+
let angle = (arc.ang / Math.PI) * 180;
|
|
790
|
+
angle = angle < 0 ? 360 + angle : angle;
|
|
791
|
+
const angleIndex = shiftAngleArray.findIndex(
|
|
792
|
+
a => a > angle
|
|
793
|
+
);
|
|
794
|
+
const prevAngle =
|
|
795
|
+
shiftAngleArray[angleIndex - 1] ??
|
|
796
|
+
shiftAngleArray[shiftAngleArray.length - 1];
|
|
797
|
+
const nextAngle = shiftAngleArray[angleIndex];
|
|
798
|
+
const convertAngle =
|
|
799
|
+
Math.abs(angle - prevAngle) > Math.abs(nextAngle - angle)
|
|
800
|
+
? nextAngle
|
|
801
|
+
: prevAngle;
|
|
802
|
+
// 取转换角度后的坐标值
|
|
803
|
+
const rad = (convertAngle / 180) * Math.PI;
|
|
804
|
+
x = Math.cos(rad) * arc.len + node.x;
|
|
805
|
+
y = Math.sin(rad) * arc.len + node.y;
|
|
806
|
+
}
|
|
441
807
|
}
|
|
442
|
-
const {
|
|
443
|
-
position = { x: 0, y: 0 },
|
|
444
|
-
scale = { x: 1, y: 1 },
|
|
445
|
-
rotation = 0,
|
|
446
|
-
} = this.currentPathNode || {};
|
|
447
|
-
const offset = this.getBoundsOffset();
|
|
448
|
-
let x =
|
|
449
|
-
e.endPos.x / (this.config?.finalScale || 1) -
|
|
450
|
-
position.x -
|
|
451
|
-
offset.x;
|
|
452
|
-
let y =
|
|
453
|
-
e.endPos.y / (this.config?.finalScale || 1) -
|
|
454
|
-
position.y -
|
|
455
|
-
offset.y;
|
|
456
|
-
const center = {
|
|
457
|
-
x: -offset.x,
|
|
458
|
-
y: -offset.y,
|
|
459
|
-
};
|
|
460
|
-
const { x: rx, y: ry } = inverseTransformToData(
|
|
461
|
-
{ x, y },
|
|
462
|
-
{ scale, rotation },
|
|
463
|
-
center
|
|
464
|
-
);
|
|
465
|
-
x = rx;
|
|
466
|
-
y = ry;
|
|
467
|
-
this.startPos = {
|
|
468
|
-
x,
|
|
469
|
-
y,
|
|
470
|
-
};
|
|
471
|
-
this.startPos.id = generateUuid();
|
|
472
|
-
this.startPos.type = PATH_FUNC_TYPE.STRAIGHT;
|
|
473
|
-
this.addPath(this.startPos);
|
|
474
|
-
this.pathPointSelection!.enterPathMode([
|
|
475
|
-
{
|
|
476
|
-
pointId: this.startPos.id,
|
|
477
|
-
},
|
|
478
|
-
]);
|
|
479
808
|
}
|
|
809
|
+
|
|
810
|
+
this.startPos = {
|
|
811
|
+
x,
|
|
812
|
+
y,
|
|
813
|
+
};
|
|
814
|
+
this.startPos.id = generateUuid();
|
|
815
|
+
this.startPos.type = PATH_FUNC_TYPE.STRAIGHT;
|
|
816
|
+
this.addPath(this.startPos);
|
|
817
|
+
this.pathPointSelection!.enterPathMode([
|
|
818
|
+
{
|
|
819
|
+
pointId: this.startPos.id,
|
|
820
|
+
},
|
|
821
|
+
]);
|
|
822
|
+
this.updateNodeData(true);
|
|
480
823
|
},
|
|
481
824
|
onDrag: e => {
|
|
482
825
|
if (!this.startPos) {
|
|
483
826
|
return;
|
|
484
827
|
}
|
|
485
828
|
// const pos = this.getPosFromMouseEvent(e);
|
|
486
|
-
const {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
rotation = 0,
|
|
491
|
-
} = this.currentPathNode || {};
|
|
492
|
-
const offset = this.getBoundsOffset();
|
|
493
|
-
let x =
|
|
494
|
-
e.endPos.x / (this.config?.finalScale || 1) -
|
|
495
|
-
position.x -
|
|
496
|
-
offset.x;
|
|
497
|
-
let y =
|
|
498
|
-
e.endPos.y / (this.config?.finalScale || 1) -
|
|
499
|
-
position.y -
|
|
500
|
-
offset.y;
|
|
501
|
-
const center = {
|
|
502
|
-
x: -offset.x,
|
|
503
|
-
y: -offset.y,
|
|
504
|
-
};
|
|
505
|
-
const { x: rx, y: ry } = inverseTransformToData(
|
|
506
|
-
{ x, y },
|
|
507
|
-
{ scale, rotation },
|
|
508
|
-
center
|
|
509
|
-
);
|
|
510
|
-
x = rx;
|
|
511
|
-
y = ry;
|
|
829
|
+
const { path } = this.currentPathNode || {};
|
|
830
|
+
const eX = e.endPos.x / (this.config?.finalScale || 1);
|
|
831
|
+
const eY = e.endPos.y / (this.config?.finalScale || 1);
|
|
832
|
+
let { x, y } = this.canvasPosToPathPos({ x: eX, y: eY });
|
|
512
833
|
|
|
513
834
|
const pathNode = path?.paths.find(
|
|
514
835
|
c => c.id === this.startPos?.id
|
|
@@ -521,24 +842,43 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
521
842
|
Math.abs(y - this.startPos.y)
|
|
522
843
|
) >= 5
|
|
523
844
|
) {
|
|
524
|
-
|
|
525
|
-
|
|
845
|
+
let x1 = pathNode.x * 2 - x;
|
|
846
|
+
let y1 = pathNode.y * 2 - y;
|
|
526
847
|
const reverse = this.isOnePoint();
|
|
848
|
+
if (this.shiftKey) {
|
|
849
|
+
// 计算原点到当前点的角度
|
|
850
|
+
const a = Math.abs(x - this.startPos.x);
|
|
851
|
+
const b = Math.abs(y - this.startPos.y);
|
|
852
|
+
const max = Math.max(a, b);
|
|
853
|
+
if (max === a) {
|
|
854
|
+
y = this.startPos.y;
|
|
855
|
+
y1 = this.startPos.y;
|
|
856
|
+
} else {
|
|
857
|
+
x = this.startPos.x;
|
|
858
|
+
x1 = this.startPos.x;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
527
861
|
pathNode.x2 = toFixedValue(reverse ? x1 : x, 2);
|
|
528
862
|
pathNode.y2 = toFixedValue(reverse ? y1 : y, 2);
|
|
529
863
|
pathNode.x1 = toFixedValue(reverse ? x : x1, 2);
|
|
530
864
|
pathNode.y1 = toFixedValue(reverse ? y : y1, 2);
|
|
531
865
|
pathNode.type = PATH_FUNC_TYPE.EQUAL;
|
|
532
866
|
// console.log(this.startPos, path?.paths);
|
|
533
|
-
this.updateNodeData();
|
|
867
|
+
this.updateNodeData(true);
|
|
534
868
|
}
|
|
535
869
|
},
|
|
536
870
|
onDragEnd: () => {
|
|
537
871
|
this.startPos = undefined;
|
|
872
|
+
this.updateNodeData();
|
|
538
873
|
},
|
|
539
874
|
});
|
|
540
875
|
}),
|
|
541
876
|
this.listenPlaygroundEvent('dblclick', (e: MouseEvent) => {
|
|
877
|
+
if (!this.isEnabled) {
|
|
878
|
+
return;
|
|
879
|
+
}
|
|
880
|
+
e.preventDefault();
|
|
881
|
+
e.stopPropagation();
|
|
542
882
|
// 双击画布时,关闭路径
|
|
543
883
|
// 1. 在路径编辑状态时,不处理;
|
|
544
884
|
// 2. 选中的是 path 路径时,不处理,新增点;
|
|
@@ -546,7 +886,7 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
546
886
|
// 4. 右键时,不处理;
|
|
547
887
|
// 5. 不是路径编辑状态时,不处理;
|
|
548
888
|
const isExit =
|
|
549
|
-
this.
|
|
889
|
+
this.isEnabled &&
|
|
550
890
|
this.pathPointSelection.selectMode === PathSelectMode.SELECT_BEZIER;
|
|
551
891
|
if (isExit) {
|
|
552
892
|
const playgroundLayer = this.pipelineLayers.find(
|
|
@@ -574,6 +914,8 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
574
914
|
!this.currentPathNode ||
|
|
575
915
|
selectNodes[0].id !== this.currentPathNode.id
|
|
576
916
|
) {
|
|
917
|
+
// 清空上个 path 的 history
|
|
918
|
+
this.clearHistory();
|
|
577
919
|
// 选中的不是当前的 path 路径, 切换 currentPathNode;
|
|
578
920
|
this.currentPathNode = selectNodes[0] as Editor2dPathNode;
|
|
579
921
|
if (
|
|
@@ -596,6 +938,7 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
596
938
|
this.currentPathNode.path.closed
|
|
597
939
|
? pathPointSelection.enterSelectBezierMode(selectionNode)
|
|
598
940
|
: pathPointSelection.enterPathMode(selectionNode);
|
|
941
|
+
this.createHistory();
|
|
599
942
|
// this.updateNodePathData();
|
|
600
943
|
}
|
|
601
944
|
return;
|
|
@@ -663,13 +1006,18 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
663
1006
|
{ x: 0, y: 0 }
|
|
664
1007
|
);
|
|
665
1008
|
this.currentPathNode.selected = true;
|
|
1009
|
+
this.currentPathNode.path.paths = [];
|
|
666
1010
|
this.context.selection.clearSelection();
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
1011
|
+
setTimeout(() => {
|
|
1012
|
+
this.context.selection.addSelection({
|
|
1013
|
+
node: this.currentPathNode as Readonly<SelectableTreeNode>,
|
|
1014
|
+
type: TreeSelection.SelectionType.TOGGLE,
|
|
1015
|
+
});
|
|
670
1016
|
});
|
|
671
1017
|
}
|
|
672
|
-
|
|
1018
|
+
// 把空数组先插入历史;
|
|
1019
|
+
this.createHistory();
|
|
1020
|
+
// this.currentPathNode.path.paths = this.currentPathNode.path.paths || []; // array 会被复用,复制一个,保证不会被修改
|
|
673
1021
|
if (this.isOnePoint() && this.currentPathNode.path.paths.length > 1) {
|
|
674
1022
|
// 第一帧
|
|
675
1023
|
this.currentPathNode.path.paths.unshift(pos);
|
|
@@ -683,16 +1031,6 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
683
1031
|
// });
|
|
684
1032
|
}
|
|
685
1033
|
|
|
686
|
-
protected onBezierPointMove(pos: PointSchema): void {
|
|
687
|
-
const { key, path: p } = this.bezierStartPos!;
|
|
688
|
-
const { path = { paths: [] } } = this.currentPathNode || {};
|
|
689
|
-
const pathNode = path.paths.find(c => c.id === p.id);
|
|
690
|
-
if (!pathNode || !this.currentPathNode) {
|
|
691
|
-
return;
|
|
692
|
-
}
|
|
693
|
-
setBezierMovePoint(pathNode, key, pos);
|
|
694
|
-
this.updateNodeData();
|
|
695
|
-
}
|
|
696
1034
|
protected onBezierPointMouseDown(
|
|
697
1035
|
e: React.MouseEvent,
|
|
698
1036
|
p: PathChild,
|
|
@@ -704,9 +1042,10 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
704
1042
|
e.preventDefault();
|
|
705
1043
|
e.stopPropagation();
|
|
706
1044
|
const pos = this.getPosFromMouseEvent(e);
|
|
1045
|
+
const { x: startX, y: startY } = this.canvasPosToPathPos(pos);
|
|
707
1046
|
this.bezierStartPos = {
|
|
708
|
-
x:
|
|
709
|
-
y:
|
|
1047
|
+
x: startX,
|
|
1048
|
+
y: startY,
|
|
710
1049
|
key,
|
|
711
1050
|
path: p,
|
|
712
1051
|
};
|
|
@@ -719,28 +1058,20 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
719
1058
|
this.startDrag(e.clientX, e.clientY, {
|
|
720
1059
|
onDrag: e => {
|
|
721
1060
|
if (this.bezierStartPos) {
|
|
722
|
-
const {
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
}
|
|
727
|
-
const
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
const { x: currentX, y: currentY } = inverseTransformToData(
|
|
737
|
-
{ x, y },
|
|
738
|
-
{ scale, rotation },
|
|
739
|
-
center
|
|
740
|
-
);
|
|
741
|
-
x = currentX;
|
|
742
|
-
y = currentY;
|
|
743
|
-
this.onBezierPointMove({ x, y });
|
|
1061
|
+
const { path = { paths: [] } } = this.currentPathNode || {};
|
|
1062
|
+
const { x, y } = this.canvasPosToPathPos({
|
|
1063
|
+
x: e.endPos.x / (this.config?.finalScale || 1),
|
|
1064
|
+
y: e.endPos.y / (this.config?.finalScale || 1),
|
|
1065
|
+
});
|
|
1066
|
+
const pathNode = path.paths.find(c => c.id === p.id);
|
|
1067
|
+
if (!pathNode) {
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
setBezierMovePoint(pathNode, key, { x, y }, this.bezierStartPos, {
|
|
1071
|
+
shiftKey: this.shiftKey,
|
|
1072
|
+
ctrlKey: this.ctrlKey,
|
|
1073
|
+
});
|
|
1074
|
+
this.updateNodeData(true);
|
|
744
1075
|
}
|
|
745
1076
|
},
|
|
746
1077
|
onDragEnd: () => {
|
|
@@ -756,6 +1087,7 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
756
1087
|
]);
|
|
757
1088
|
}
|
|
758
1089
|
}
|
|
1090
|
+
this.updateNodeData();
|
|
759
1091
|
},
|
|
760
1092
|
});
|
|
761
1093
|
this.draw();
|
|
@@ -774,19 +1106,13 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
774
1106
|
return event;
|
|
775
1107
|
}
|
|
776
1108
|
|
|
777
|
-
protected
|
|
778
|
-
e: React.MouseEvent,
|
|
779
|
-
currentPoint: PathChild
|
|
780
|
-
): void {
|
|
781
|
-
if (e.buttons !== 1) {
|
|
782
|
-
return;
|
|
783
|
-
}
|
|
1109
|
+
protected selectionChange(currentPoint: PathChild): void {
|
|
784
1110
|
// 如果在 selection 里拖动所有点, 没有则切换当前 selection 里的点
|
|
785
1111
|
const { pathPointSelection } = this;
|
|
786
1112
|
if (!pathPointSelection) {
|
|
787
1113
|
return;
|
|
788
1114
|
}
|
|
789
|
-
|
|
1115
|
+
const selection = pathPointSelection?.selection || [];
|
|
790
1116
|
const node = this.currentPathNode as Editor2dPathNode;
|
|
791
1117
|
const selectionNode = [
|
|
792
1118
|
{
|
|
@@ -825,12 +1151,26 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
825
1151
|
}
|
|
826
1152
|
}
|
|
827
1153
|
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
protected onPointMouseDown(
|
|
1157
|
+
e: React.MouseEvent,
|
|
1158
|
+
currentPoint: PathChild
|
|
1159
|
+
): void {
|
|
1160
|
+
if (e.buttons !== 1) {
|
|
1161
|
+
return;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
this.selectionChange(currentPoint);
|
|
1165
|
+
|
|
1166
|
+
const node = this.currentPathNode as Editor2dPathNode;
|
|
828
1167
|
const startNodeClone = deepClone(node.path.paths);
|
|
829
1168
|
|
|
830
1169
|
this.startDrag(e.clientX, e.clientY, {
|
|
831
1170
|
// 拖动
|
|
832
1171
|
onDrag: dragEvent => {
|
|
833
|
-
|
|
1172
|
+
const { pathPointSelection } = this;
|
|
1173
|
+
const selection = pathPointSelection?.selection || [];
|
|
834
1174
|
const selectionNodes = selection
|
|
835
1175
|
.map(s => node.path.paths.find(p => p.id === s.pointId))
|
|
836
1176
|
.filter(c => c) as PathChild[];
|
|
@@ -850,77 +1190,62 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
850
1190
|
const startNode = selectionNodes.map((s: PathChild) =>
|
|
851
1191
|
startNodeClone.find((c: PathChild) => c.id === s.id)
|
|
852
1192
|
);
|
|
853
|
-
const {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
} = this.currentPathNode || {};
|
|
858
|
-
const offset = this.getBoundsOffset();
|
|
859
|
-
let x =
|
|
860
|
-
dragEvent.endPos.x / (this.config?.finalScale || 1) -
|
|
861
|
-
position.x -
|
|
862
|
-
offset.x;
|
|
863
|
-
let y =
|
|
864
|
-
dragEvent.endPos.y / (this.config?.finalScale || 1) -
|
|
865
|
-
position.y -
|
|
866
|
-
offset.y;
|
|
867
|
-
const center = {
|
|
868
|
-
x: -offset.x,
|
|
869
|
-
y: -offset.y,
|
|
870
|
-
};
|
|
871
|
-
const { x: currentX, y: currentY } = inverseTransformToData(
|
|
872
|
-
{ x, y },
|
|
873
|
-
{ scale, rotation },
|
|
874
|
-
center
|
|
875
|
-
);
|
|
876
|
-
x = currentX;
|
|
877
|
-
y = currentY;
|
|
1193
|
+
const { x, y } = this.canvasPosToPathPos({
|
|
1194
|
+
x: dragEvent.endPos.x / (this.config?.finalScale || 1),
|
|
1195
|
+
y: dragEvent.endPos.y / (this.config?.finalScale || 1),
|
|
1196
|
+
});
|
|
878
1197
|
selectionNodes.forEach((p: PathChild, i) => {
|
|
879
1198
|
const start = startNode[i];
|
|
880
1199
|
const d = delta[i];
|
|
881
1200
|
const deltaX = x - start.x + d.x;
|
|
882
1201
|
const deltaY = y - start.y + d.y;
|
|
1202
|
+
const max = Math.max(Math.abs(deltaX), Math.abs(deltaY));
|
|
1203
|
+
|
|
1204
|
+
const isX = max === Math.abs(deltaX);
|
|
1205
|
+
const isY = max === Math.abs(deltaY);
|
|
1206
|
+
const noX = this.shiftKey && !isX;
|
|
1207
|
+
const noY = this.shiftKey && !isY;
|
|
883
1208
|
if (typeof p.x1 === 'number') {
|
|
884
|
-
p.x1 = toFixedValue(start.x1 + deltaX, 2);
|
|
1209
|
+
p.x1 = noX ? start.x1 : toFixedValue(start.x1 + deltaX, 2);
|
|
885
1210
|
}
|
|
886
1211
|
if (typeof p.x2 === 'number') {
|
|
887
|
-
p.x2 = toFixedValue(start.x2 + deltaX, 2);
|
|
1212
|
+
p.x2 = noX ? start.x2 : toFixedValue(start.x2 + deltaX, 2);
|
|
888
1213
|
}
|
|
889
1214
|
if (typeof p.y1 === 'number') {
|
|
890
|
-
p.y1 = toFixedValue(start.y1 + deltaY, 2);
|
|
1215
|
+
p.y1 = noY ? start.y1 : toFixedValue(start.y1 + deltaY, 2);
|
|
891
1216
|
}
|
|
892
1217
|
if (typeof p.y2 === 'number') {
|
|
893
|
-
p.y2 = toFixedValue(start.y2 + deltaY, 2);
|
|
1218
|
+
p.y2 = noY ? start.y2 : toFixedValue(start.y2 + deltaY, 2);
|
|
894
1219
|
}
|
|
895
|
-
p.x = toFixedValue(x + d.x, 2);
|
|
896
|
-
p.y = toFixedValue(y + d.y, 2);
|
|
1220
|
+
p.x = noX ? start.x : toFixedValue(x + d.x, 2);
|
|
1221
|
+
p.y = noY ? start.y : toFixedValue(y + d.y, 2);
|
|
897
1222
|
});
|
|
898
1223
|
|
|
1224
|
+
this.updateNodeData(true);
|
|
1225
|
+
},
|
|
1226
|
+
onDragEnd: () => {
|
|
899
1227
|
this.updateNodeData();
|
|
900
1228
|
},
|
|
901
1229
|
});
|
|
902
1230
|
this.draw();
|
|
903
1231
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
const { paths = [] } = path;
|
|
915
|
-
const p = this.getPosFromMouseEvent(e);
|
|
1232
|
+
// 画布坐标转换成 path 坐标;
|
|
1233
|
+
protected canvasPosToPathPos(p: {
|
|
1234
|
+
x: number;
|
|
1235
|
+
y: number;
|
|
1236
|
+
}): {
|
|
1237
|
+
x: number;
|
|
1238
|
+
y: number;
|
|
1239
|
+
} {
|
|
1240
|
+
const { position = { x: 0, y: 0 }, scale = { x: 1, y: 1 }, rotation = 0 } =
|
|
1241
|
+
this.currentPathNode || {};
|
|
916
1242
|
const offset = this.getBoundsOffset();
|
|
917
|
-
let x = p.x - position.x - offset.x;
|
|
918
|
-
let y = p.y - position.y - offset.y;
|
|
919
|
-
|
|
920
1243
|
const center = {
|
|
921
1244
|
x: -offset.x,
|
|
922
1245
|
y: -offset.y,
|
|
923
1246
|
};
|
|
1247
|
+
let x = p.x - position.x - offset.x;
|
|
1248
|
+
let y = p.y - position.y - offset.y;
|
|
924
1249
|
const { x: currentX, y: currentY } = inverseTransformToData(
|
|
925
1250
|
{ x, y },
|
|
926
1251
|
{ scale, rotation },
|
|
@@ -928,13 +1253,53 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
928
1253
|
);
|
|
929
1254
|
x = currentX;
|
|
930
1255
|
y = currentY;
|
|
931
|
-
|
|
1256
|
+
return {
|
|
932
1257
|
x,
|
|
933
1258
|
y,
|
|
934
1259
|
};
|
|
1260
|
+
}
|
|
1261
|
+
protected pathPosToCanvasPos(c: {
|
|
1262
|
+
x: number;
|
|
1263
|
+
y: number;
|
|
1264
|
+
}): {
|
|
1265
|
+
x: number;
|
|
1266
|
+
y: number;
|
|
1267
|
+
} {
|
|
1268
|
+
const { position = { x: 0, y: 0 }, scale = { x: 1, y: 1 }, rotation = 0 } =
|
|
1269
|
+
this.currentPathNode || {};
|
|
1270
|
+
const offset = this.getBoundsOffset();
|
|
1271
|
+
const center = {
|
|
1272
|
+
x: -offset.x,
|
|
1273
|
+
y: -offset.y,
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
const { x, y } = transformToData(
|
|
1277
|
+
{ x: c.x, y: c.y },
|
|
1278
|
+
{ scale, rotation },
|
|
1279
|
+
center
|
|
1280
|
+
);
|
|
1281
|
+
return {
|
|
1282
|
+
x: x + position.x + offset.x,
|
|
1283
|
+
y: y + position.y + offset.y,
|
|
1284
|
+
};
|
|
1285
|
+
}
|
|
1286
|
+
protected getPathMousePos(e: React.MouseEvent): { x: number; y: number } {
|
|
1287
|
+
const p = this.getPosFromMouseEvent({
|
|
1288
|
+
clientX: e.clientX ?? 0,
|
|
1289
|
+
clientY: e.clientY ?? 0,
|
|
1290
|
+
});
|
|
1291
|
+
return this.canvasPosToPathPos(p);
|
|
1292
|
+
}
|
|
1293
|
+
protected onPathAddPoint(i: number, e: React.MouseEvent): void {
|
|
1294
|
+
if (!this.currentPathNode || !this.document) {
|
|
1295
|
+
return;
|
|
1296
|
+
}
|
|
1297
|
+
const { path } = this.currentPathNode || {};
|
|
1298
|
+
const { paths = [] } = path;
|
|
1299
|
+
const pos = this.getPathMousePos(e);
|
|
935
1300
|
const point = paths[i];
|
|
936
1301
|
const nextPoint = paths[i + 1] ? paths[i + 1] : paths[0];
|
|
937
|
-
const newPoint = getNewPoint(point, nextPoint, pos);
|
|
1302
|
+
const newPoint = getNewPoint(point, nextPoint, pos, this.shiftKey);
|
|
938
1303
|
paths.splice(i + 1, 0, newPoint);
|
|
939
1304
|
this.pathPointSelection!.enterPathMode([
|
|
940
1305
|
{
|
|
@@ -987,8 +1352,6 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
987
1352
|
const paths = [...p].map(c => {
|
|
988
1353
|
const item = {
|
|
989
1354
|
...c,
|
|
990
|
-
x: c.x,
|
|
991
|
-
y: c.y,
|
|
992
1355
|
};
|
|
993
1356
|
|
|
994
1357
|
const { x, y } = transformToData(
|
|
@@ -1028,6 +1391,8 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
1028
1391
|
onBezierPointMouseDown: this.onBezierPointMouseDown.bind(this),
|
|
1029
1392
|
onClosePath: this.onClosePath.bind(this),
|
|
1030
1393
|
onPathAddPoint: this.onPathAddPoint.bind(this),
|
|
1394
|
+
isShiftKey: this.shiftKey,
|
|
1395
|
+
isCtrlKey: this.ctrlKey,
|
|
1031
1396
|
}}
|
|
1032
1397
|
>
|
|
1033
1398
|
<SvgPath
|
|
@@ -1035,11 +1400,15 @@ export class PathEditLayer extends Layer<PlaygroundContext2d> {
|
|
|
1035
1400
|
height={this.config.config.pageBounds?.height || 300}
|
|
1036
1401
|
getPosFromMouseEvent={this.getPosFromMouseEvent.bind(this)}
|
|
1037
1402
|
node={this.currentPathNode}
|
|
1403
|
+
showAllBezier={this.altKey}
|
|
1038
1404
|
paths={paths}
|
|
1039
1405
|
selection={this.pathPointSelection?.selection as PathPointSelection[]}
|
|
1040
1406
|
selectMode={this.pathPointSelection?.selectMode}
|
|
1041
1407
|
getPointIsStartOrEnd={this.getPointIsStartOrEnd.bind(this)}
|
|
1408
|
+
onUpdateNodeData={this.updateNodeData.bind(this)}
|
|
1042
1409
|
scale={this.config.finalScale}
|
|
1410
|
+
getPathMousePos={this.getPathMousePos.bind(this)}
|
|
1411
|
+
pathPosToCanvasPos={this.pathPosToCanvasPos.bind(this)}
|
|
1043
1412
|
/>
|
|
1044
1413
|
</PathEditLayerEventContext.Provider>
|
|
1045
1414
|
);
|