@antv/infographic 0.2.13 → 0.2.15
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/README.md +12 -5
- package/README.zh-CN.md +12 -5
- package/dist/infographic.min.js +180 -171
- package/dist/infographic.min.js.map +1 -1
- package/esm/designs/structures/index.d.ts +1 -0
- package/esm/designs/structures/index.js +1 -0
- package/esm/designs/structures/relation-dagre-flow.js +4 -139
- package/esm/designs/structures/sequence-interaction.d.ts +54 -0
- package/esm/designs/structures/sequence-interaction.js +440 -0
- package/esm/designs/utils/geometry.d.ts +44 -0
- package/esm/designs/utils/geometry.js +244 -0
- package/esm/designs/utils/index.d.ts +1 -0
- package/esm/designs/utils/index.js +1 -0
- package/esm/editor/commands/UpdateOptions.d.ts +4 -4
- package/esm/editor/commands/UpdateOptions.js +6 -3
- package/esm/editor/editor.d.ts +5 -1
- package/esm/editor/editor.js +16 -5
- package/esm/editor/index.d.ts +1 -0
- package/esm/editor/index.js +1 -0
- package/esm/editor/interactions/brush-select.d.ts +0 -1
- package/esm/editor/interactions/brush-select.js +2 -10
- package/esm/editor/interactions/drag-canvas.d.ts +35 -0
- package/esm/editor/interactions/drag-canvas.js +161 -0
- package/esm/editor/interactions/drag-element.js +4 -3
- package/esm/editor/interactions/index.d.ts +1 -0
- package/esm/editor/interactions/index.js +1 -0
- package/esm/editor/interactions/zoom-wheel.d.ts +9 -0
- package/esm/editor/interactions/zoom-wheel.js +32 -15
- package/esm/editor/managers/index.d.ts +1 -0
- package/esm/editor/managers/index.js +1 -0
- package/esm/editor/managers/state.d.ts +4 -2
- package/esm/editor/managers/state.js +14 -13
- package/esm/editor/managers/sync-registry.d.ts +16 -0
- package/esm/editor/managers/sync-registry.js +51 -0
- package/esm/editor/plugins/{edit-bar/components → components}/button.js +1 -1
- package/esm/editor/plugins/{edit-bar/components → components}/color-picker.js +1 -1
- package/esm/editor/plugins/{edit-bar/components → components}/icons.d.ts +1 -0
- package/esm/editor/plugins/{edit-bar/components → components}/icons.js +1 -0
- package/esm/editor/plugins/{edit-bar/components → components}/popover.js +2 -2
- package/esm/editor/plugins/{edit-bar/components → components}/select.js +1 -1
- package/esm/editor/plugins/core-sync.d.ts +8 -0
- package/esm/editor/plugins/core-sync.js +30 -0
- package/esm/editor/plugins/edit-bar/edit-items/align-elements.js +1 -1
- package/esm/editor/plugins/edit-bar/edit-items/font-align.js +1 -1
- package/esm/editor/plugins/edit-bar/edit-items/font-color.js +1 -1
- package/esm/editor/plugins/edit-bar/edit-items/font-family.js +1 -1
- package/esm/editor/plugins/edit-bar/edit-items/font-size.js +1 -1
- package/esm/editor/plugins/edit-bar/edit-items/icon-color.js +1 -1
- package/esm/editor/plugins/edit-bar/index.d.ts +2 -2
- package/esm/editor/plugins/edit-bar/index.js +1 -1
- package/esm/editor/plugins/index.d.ts +2 -0
- package/esm/editor/plugins/index.js +2 -0
- package/esm/editor/plugins/reset-viewbox.d.ts +33 -0
- package/esm/editor/plugins/reset-viewbox.js +186 -0
- package/esm/editor/types/editor.d.ts +14 -0
- package/esm/editor/types/index.d.ts +1 -0
- package/esm/editor/types/interaction.d.ts +9 -0
- package/esm/editor/types/state.d.ts +4 -2
- package/esm/editor/types/sync.d.ts +27 -0
- package/esm/editor/types/sync.js +1 -0
- package/esm/editor/utils/data.js +3 -1
- package/esm/editor/utils/event.d.ts +1 -0
- package/esm/editor/utils/event.js +8 -0
- package/esm/editor/utils/index.d.ts +1 -0
- package/esm/editor/utils/index.js +1 -0
- package/esm/editor/utils/object.d.ts +15 -0
- package/esm/editor/utils/object.js +77 -0
- package/esm/index.d.ts +4 -3
- package/esm/index.js +3 -2
- package/esm/options/types.d.ts +7 -0
- package/esm/runtime/Infographic.js +20 -7
- package/esm/runtime/options.js +7 -2
- package/esm/syntax/index.js +40 -20
- package/esm/syntax/relations.js +26 -2
- package/esm/syntax/schema.js +1 -0
- package/esm/templates/built-in.js +27 -2
- package/esm/templates/sequence-interaction.d.ts +2 -0
- package/esm/templates/sequence-interaction.js +76 -0
- package/esm/types/data.d.ts +1 -0
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/measure-text.js +40 -9
- package/esm/utils/padding.d.ts +1 -0
- package/esm/utils/padding.js +6 -2
- package/esm/utils/types.d.ts +16 -0
- package/esm/utils/types.js +12 -0
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/lib/designs/structures/index.d.ts +1 -0
- package/lib/designs/structures/index.js +1 -0
- package/lib/designs/structures/relation-dagre-flow.js +5 -140
- package/lib/designs/structures/sequence-interaction.d.ts +54 -0
- package/lib/designs/structures/sequence-interaction.js +444 -0
- package/lib/designs/utils/geometry.d.ts +44 -0
- package/lib/designs/utils/geometry.js +256 -0
- package/lib/designs/utils/index.d.ts +1 -0
- package/lib/designs/utils/index.js +1 -0
- package/lib/editor/commands/UpdateOptions.d.ts +4 -4
- package/lib/editor/commands/UpdateOptions.js +6 -3
- package/lib/editor/editor.d.ts +5 -1
- package/lib/editor/editor.js +16 -5
- package/lib/editor/index.d.ts +1 -0
- package/lib/editor/index.js +1 -0
- package/lib/editor/interactions/brush-select.d.ts +0 -1
- package/lib/editor/interactions/brush-select.js +1 -9
- package/lib/editor/interactions/drag-canvas.d.ts +35 -0
- package/lib/editor/interactions/drag-canvas.js +165 -0
- package/lib/editor/interactions/drag-element.js +4 -3
- package/lib/editor/interactions/index.d.ts +1 -0
- package/lib/editor/interactions/index.js +3 -1
- package/lib/editor/interactions/zoom-wheel.d.ts +9 -0
- package/lib/editor/interactions/zoom-wheel.js +32 -15
- package/lib/editor/managers/index.d.ts +1 -0
- package/lib/editor/managers/index.js +1 -0
- package/lib/editor/managers/state.d.ts +4 -2
- package/lib/editor/managers/state.js +12 -11
- package/lib/editor/managers/sync-registry.d.ts +16 -0
- package/lib/editor/managers/sync-registry.js +55 -0
- package/lib/editor/plugins/{edit-bar/components → components}/button.js +1 -1
- package/lib/editor/plugins/{edit-bar/components → components}/color-picker.js +1 -1
- package/lib/editor/plugins/{edit-bar/components → components}/icons.d.ts +1 -0
- package/lib/editor/plugins/{edit-bar/components → components}/icons.js +2 -1
- package/lib/editor/plugins/{edit-bar/components → components}/popover.js +2 -2
- package/lib/editor/plugins/{edit-bar/components → components}/select.js +1 -1
- package/lib/editor/plugins/core-sync.d.ts +8 -0
- package/lib/editor/plugins/core-sync.js +34 -0
- package/lib/editor/plugins/edit-bar/edit-items/align-elements.js +1 -1
- package/lib/editor/plugins/edit-bar/edit-items/font-align.js +1 -1
- package/lib/editor/plugins/edit-bar/edit-items/font-color.js +1 -1
- package/lib/editor/plugins/edit-bar/edit-items/font-family.js +1 -1
- package/lib/editor/plugins/edit-bar/edit-items/font-size.js +1 -1
- package/lib/editor/plugins/edit-bar/edit-items/icon-color.js +1 -1
- package/lib/editor/plugins/edit-bar/index.d.ts +2 -2
- package/lib/editor/plugins/edit-bar/index.js +1 -1
- package/lib/editor/plugins/index.d.ts +2 -0
- package/lib/editor/plugins/index.js +5 -1
- package/lib/editor/plugins/reset-viewbox.d.ts +33 -0
- package/lib/editor/plugins/reset-viewbox.js +190 -0
- package/lib/editor/types/editor.d.ts +14 -0
- package/lib/editor/types/index.d.ts +1 -0
- package/lib/editor/types/interaction.d.ts +9 -0
- package/lib/editor/types/state.d.ts +4 -2
- package/lib/editor/types/sync.d.ts +27 -0
- package/lib/editor/types/sync.js +2 -0
- package/lib/editor/utils/data.js +3 -1
- package/lib/editor/utils/event.d.ts +1 -0
- package/lib/editor/utils/event.js +9 -0
- package/lib/editor/utils/index.d.ts +1 -0
- package/lib/editor/utils/index.js +1 -0
- package/lib/editor/utils/object.d.ts +15 -0
- package/lib/editor/utils/object.js +80 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.js +9 -2
- package/lib/options/types.d.ts +7 -0
- package/lib/runtime/Infographic.js +19 -6
- package/lib/runtime/options.js +6 -1
- package/lib/syntax/index.js +40 -20
- package/lib/syntax/relations.js +26 -2
- package/lib/syntax/schema.js +1 -0
- package/lib/templates/built-in.js +27 -2
- package/lib/templates/sequence-interaction.d.ts +2 -0
- package/lib/templates/sequence-interaction.js +79 -0
- package/lib/types/data.d.ts +1 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.js +1 -0
- package/lib/utils/measure-text.js +39 -8
- package/lib/utils/padding.d.ts +1 -0
- package/lib/utils/padding.js +7 -2
- package/lib/utils/types.d.ts +16 -0
- package/lib/utils/types.js +13 -0
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/designs/structures/index.ts +1 -0
- package/src/designs/structures/relation-dagre-flow.tsx +14 -178
- package/src/designs/structures/sequence-interaction.tsx +885 -0
- package/src/designs/utils/geometry.tsx +315 -0
- package/src/designs/utils/index.ts +1 -0
- package/src/editor/commands/UpdateOptions.ts +11 -6
- package/src/editor/editor.ts +26 -5
- package/src/editor/index.ts +1 -0
- package/src/editor/interactions/brush-select.ts +2 -8
- package/src/editor/interactions/drag-canvas.ts +203 -0
- package/src/editor/interactions/drag-element.ts +5 -4
- package/src/editor/interactions/index.ts +1 -0
- package/src/editor/interactions/zoom-wheel.ts +49 -13
- package/src/editor/managers/index.ts +1 -0
- package/src/editor/managers/state.ts +21 -21
- package/src/editor/managers/sync-registry.ts +66 -0
- package/src/editor/plugins/{edit-bar/components → components}/button.ts +1 -1
- package/src/editor/plugins/{edit-bar/components → components}/color-picker.ts +1 -1
- package/src/editor/plugins/{edit-bar/components → components}/icons.ts +4 -0
- package/src/editor/plugins/{edit-bar/components → components}/popover.ts +2 -2
- package/src/editor/plugins/{edit-bar/components → components}/select.ts +1 -1
- package/src/editor/plugins/core-sync.ts +44 -0
- package/src/editor/plugins/edit-bar/edit-items/align-elements.ts +2 -2
- package/src/editor/plugins/edit-bar/edit-items/font-align.ts +1 -1
- package/src/editor/plugins/edit-bar/edit-items/font-color.ts +1 -1
- package/src/editor/plugins/edit-bar/edit-items/font-family.ts +1 -1
- package/src/editor/plugins/edit-bar/edit-items/font-size.ts +3 -3
- package/src/editor/plugins/edit-bar/edit-items/icon-color.ts +1 -1
- package/src/editor/plugins/edit-bar/index.ts +2 -2
- package/src/editor/plugins/index.ts +2 -0
- package/src/editor/plugins/reset-viewbox.ts +258 -0
- package/src/editor/types/editor.ts +18 -0
- package/src/editor/types/index.ts +1 -0
- package/src/editor/types/interaction.ts +31 -0
- package/src/editor/types/state.ts +14 -2
- package/src/editor/types/sync.ts +33 -0
- package/src/editor/utils/data.ts +2 -1
- package/src/editor/utils/event.ts +7 -0
- package/src/editor/utils/index.ts +1 -0
- package/src/editor/utils/object.ts +116 -0
- package/src/index.ts +26 -2
- package/src/options/types.ts +11 -0
- package/src/runtime/Infographic.tsx +27 -17
- package/src/runtime/options.ts +8 -1
- package/src/syntax/index.ts +51 -18
- package/src/syntax/relations.ts +29 -2
- package/src/syntax/schema.ts +1 -0
- package/src/templates/built-in.ts +30 -0
- package/src/templates/sequence-interaction.ts +101 -0
- package/src/types/data.ts +1 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/measure-text.ts +41 -9
- package/src/utils/padding.ts +10 -2
- package/src/utils/types.ts +61 -0
- package/src/version.ts +1 -1
- /package/esm/editor/plugins/{edit-bar/components → components}/button.d.ts +0 -0
- /package/esm/editor/plugins/{edit-bar/components → components}/color-picker.d.ts +0 -0
- /package/esm/editor/plugins/{edit-bar/components → components}/index.d.ts +0 -0
- /package/esm/editor/plugins/{edit-bar/components → components}/index.js +0 -0
- /package/esm/editor/plugins/{edit-bar/components → components}/popover.d.ts +0 -0
- /package/esm/editor/plugins/{edit-bar/components → components}/select.d.ts +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/button.d.ts +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/color-picker.d.ts +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/index.d.ts +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/index.js +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/popover.d.ts +0 -0
- /package/lib/editor/plugins/{edit-bar/components → components}/select.d.ts +0 -0
- /package/src/editor/plugins/{edit-bar/components → components}/index.ts +0 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import type { JSXElement } from '../../jsx';
|
|
2
|
+
import { Path, Polygon } from '../../jsx';
|
|
3
|
+
|
|
4
|
+
export const getMidPoint = (points: [number, number][]) => {
|
|
5
|
+
if (points.length === 0) return null;
|
|
6
|
+
if (points.length === 1) return points[0];
|
|
7
|
+
let total = 0;
|
|
8
|
+
const segments: {
|
|
9
|
+
length: number;
|
|
10
|
+
start: [number, number];
|
|
11
|
+
end: [number, number];
|
|
12
|
+
}[] = [];
|
|
13
|
+
for (let i = 0; i < points.length - 1; i += 1) {
|
|
14
|
+
const start = points[i];
|
|
15
|
+
const end = points[i + 1];
|
|
16
|
+
const length = Math.hypot(end[0] - start[0], end[1] - start[1]);
|
|
17
|
+
segments.push({ length, start, end });
|
|
18
|
+
total += length;
|
|
19
|
+
}
|
|
20
|
+
if (total === 0) return points[0];
|
|
21
|
+
let target = total / 2;
|
|
22
|
+
for (let i = 0; i < segments.length; i += 1) {
|
|
23
|
+
const segment = segments[i];
|
|
24
|
+
if (target <= segment.length || i === segments.length - 1) {
|
|
25
|
+
const ratio =
|
|
26
|
+
segment.length === 0
|
|
27
|
+
? 0
|
|
28
|
+
: Math.max(0, Math.min(1, target / segment.length));
|
|
29
|
+
return [
|
|
30
|
+
segment.start[0] + (segment.end[0] - segment.start[0]) * ratio,
|
|
31
|
+
segment.start[1] + (segment.end[1] - segment.start[1]) * ratio,
|
|
32
|
+
] as [number, number];
|
|
33
|
+
}
|
|
34
|
+
target -= segment.length;
|
|
35
|
+
}
|
|
36
|
+
return points[Math.floor(points.length / 2)];
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const createStraightPath = (
|
|
40
|
+
points: [number, number][],
|
|
41
|
+
dx: number,
|
|
42
|
+
dy: number,
|
|
43
|
+
) =>
|
|
44
|
+
points
|
|
45
|
+
.map(([x, y], index) => {
|
|
46
|
+
const prefix = index === 0 ? 'M' : 'L';
|
|
47
|
+
return `${prefix} ${x + dx} ${y + dy}`;
|
|
48
|
+
})
|
|
49
|
+
.join(' ');
|
|
50
|
+
|
|
51
|
+
export const createRoundedPath = (
|
|
52
|
+
points: [number, number][],
|
|
53
|
+
radius: number,
|
|
54
|
+
dx: number,
|
|
55
|
+
dy: number,
|
|
56
|
+
) => {
|
|
57
|
+
if (points.length < 2) return '';
|
|
58
|
+
const clamp = (value: number, min: number, max: number) =>
|
|
59
|
+
Math.min(max, Math.max(min, value));
|
|
60
|
+
const toPoint = ([x, y]: [number, number]) => ({
|
|
61
|
+
x: x + dx,
|
|
62
|
+
y: y + dy,
|
|
63
|
+
});
|
|
64
|
+
const output: string[] = [];
|
|
65
|
+
const first = toPoint(points[0]);
|
|
66
|
+
output.push(`M ${first.x} ${first.y}`);
|
|
67
|
+
|
|
68
|
+
if (points.length === 2) {
|
|
69
|
+
const last = toPoint(points[1]);
|
|
70
|
+
output.push(`L ${last.x} ${last.y}`);
|
|
71
|
+
return output.join(' ');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
for (let i = 1; i < points.length - 1; i += 1) {
|
|
75
|
+
const prev = points[i - 1];
|
|
76
|
+
const curr = points[i];
|
|
77
|
+
const next = points[i + 1];
|
|
78
|
+
const v0x = curr[0] - prev[0];
|
|
79
|
+
const v0y = curr[1] - prev[1];
|
|
80
|
+
const v1x = next[0] - curr[0];
|
|
81
|
+
const v1y = next[1] - curr[1];
|
|
82
|
+
const d0 = Math.hypot(v0x, v0y);
|
|
83
|
+
const d1 = Math.hypot(v1x, v1y);
|
|
84
|
+
if (d0 === 0 || d1 === 0) {
|
|
85
|
+
const currPoint = toPoint(curr);
|
|
86
|
+
output.push(`L ${currPoint.x} ${currPoint.y}`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const r = clamp(radius, 0, Math.min(d0, d1) / 2);
|
|
90
|
+
if (r === 0) {
|
|
91
|
+
const currPoint = toPoint(curr);
|
|
92
|
+
output.push(`L ${currPoint.x} ${currPoint.y}`);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const u0x = v0x / d0;
|
|
96
|
+
const u0y = v0y / d0;
|
|
97
|
+
const u1x = v1x / d1;
|
|
98
|
+
const u1y = v1y / d1;
|
|
99
|
+
const start = toPoint([curr[0] - u0x * r, curr[1] - u0y * r]);
|
|
100
|
+
const end = toPoint([curr[0] + u1x * r, curr[1] + u1y * r]);
|
|
101
|
+
output.push(`L ${start.x} ${start.y}`);
|
|
102
|
+
const currPoint = toPoint(curr);
|
|
103
|
+
output.push(`Q ${currPoint.x} ${currPoint.y} ${end.x} ${end.y}`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const last = toPoint(points[points.length - 1]);
|
|
107
|
+
output.push(`L ${last.x} ${last.y}`);
|
|
108
|
+
return output.join(' ');
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const createArrowElements = (
|
|
112
|
+
x: number,
|
|
113
|
+
y: number,
|
|
114
|
+
angle: number,
|
|
115
|
+
type: 'arrow' | 'triangle' | 'diamond',
|
|
116
|
+
fillColor: string,
|
|
117
|
+
edgeWidth: number,
|
|
118
|
+
arrowSize: number,
|
|
119
|
+
): JSXElement[] => {
|
|
120
|
+
const ux = Math.cos(angle);
|
|
121
|
+
const uy = Math.sin(angle);
|
|
122
|
+
const px = -uy;
|
|
123
|
+
const py = ux;
|
|
124
|
+
const length = arrowSize;
|
|
125
|
+
const halfWidth = arrowSize * 0.55;
|
|
126
|
+
|
|
127
|
+
if (type === 'arrow') {
|
|
128
|
+
const leftX = x - ux * length + px * halfWidth;
|
|
129
|
+
const leftY = y - uy * length + py * halfWidth;
|
|
130
|
+
const rightX = x - ux * length - px * halfWidth;
|
|
131
|
+
const rightY = y - uy * length - py * halfWidth;
|
|
132
|
+
return [
|
|
133
|
+
<Path
|
|
134
|
+
d={`M ${leftX} ${leftY} L ${x} ${y} L ${rightX} ${rightY}`}
|
|
135
|
+
stroke={fillColor}
|
|
136
|
+
strokeWidth={Math.max(1.5, edgeWidth)}
|
|
137
|
+
strokeLinecap="round"
|
|
138
|
+
strokeLinejoin="round"
|
|
139
|
+
fill="none"
|
|
140
|
+
/>,
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (type === 'diamond') {
|
|
145
|
+
const diamondLength = length * 1.25;
|
|
146
|
+
const diamondWidth = halfWidth * 0.75;
|
|
147
|
+
const midX = x - ux * diamondLength * 0.5;
|
|
148
|
+
const midY = y - uy * diamondLength * 0.5;
|
|
149
|
+
const diamondPoints = [
|
|
150
|
+
{ x, y },
|
|
151
|
+
{ x: midX + px * diamondWidth, y: midY + py * diamondWidth },
|
|
152
|
+
{ x: x - ux * diamondLength, y: y - uy * diamondLength },
|
|
153
|
+
{ x: midX - px * diamondWidth, y: midY - py * diamondWidth },
|
|
154
|
+
];
|
|
155
|
+
return [
|
|
156
|
+
<Polygon
|
|
157
|
+
points={diamondPoints}
|
|
158
|
+
fill={fillColor}
|
|
159
|
+
stroke={fillColor}
|
|
160
|
+
strokeWidth={Math.max(1, edgeWidth * 0.8)}
|
|
161
|
+
/>,
|
|
162
|
+
];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const trianglePoints = [
|
|
166
|
+
{ x, y },
|
|
167
|
+
{
|
|
168
|
+
x: x - ux * length + px * halfWidth,
|
|
169
|
+
y: y - uy * length + py * halfWidth,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
x: x - ux * length - px * halfWidth,
|
|
173
|
+
y: y - uy * length - py * halfWidth,
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
return [
|
|
177
|
+
<Polygon
|
|
178
|
+
points={trianglePoints}
|
|
179
|
+
fill={fillColor}
|
|
180
|
+
stroke={fillColor}
|
|
181
|
+
strokeWidth={Math.max(1, edgeWidth * 0.8)}
|
|
182
|
+
/>,
|
|
183
|
+
];
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// LT: Left Top (radio), LC: Left Center (1/2), LB: Left Bottom (1 - radio)
|
|
187
|
+
// RT: Right Top (radio), RC: Right Center (1/2), RB: Right Bottom (1 - radio)
|
|
188
|
+
export const getNodesAnchors = (node: {
|
|
189
|
+
x: number;
|
|
190
|
+
y: number;
|
|
191
|
+
width: number;
|
|
192
|
+
height: number;
|
|
193
|
+
radio?: number;
|
|
194
|
+
}) => {
|
|
195
|
+
const { x, y, width, height, radio = 0.25 } = node;
|
|
196
|
+
const q1H = height * radio;
|
|
197
|
+
const halfH = height * 0.5;
|
|
198
|
+
const q3H = height * (1 - radio);
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
LT: { x, y: y + q1H },
|
|
202
|
+
LC: { x, y: y + halfH },
|
|
203
|
+
LB: { x, y: y + q3H },
|
|
204
|
+
RT: { x: x + width, y: y + q1H },
|
|
205
|
+
RC: { x: x + width, y: y + halfH },
|
|
206
|
+
RB: { x: x + width, y: y + q3H },
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export const getTangentAngle = (points: [number, number][], t: 0 | 1) => {
|
|
211
|
+
const len = points.length;
|
|
212
|
+
// Cubic Bezier (Self loop)
|
|
213
|
+
if (len === 4) {
|
|
214
|
+
const p0 = points[0],
|
|
215
|
+
p1 = points[1],
|
|
216
|
+
p2 = points[2],
|
|
217
|
+
p3 = points[3];
|
|
218
|
+
if (t === 0) {
|
|
219
|
+
return Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
|
|
220
|
+
} else {
|
|
221
|
+
return Math.atan2(p3[1] - p2[1], p3[0] - p2[0]);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Quad Bezier (Curved)
|
|
225
|
+
if (len === 3) {
|
|
226
|
+
const p0 = points[0],
|
|
227
|
+
p1 = points[1],
|
|
228
|
+
p2 = points[2];
|
|
229
|
+
if (t === 0) {
|
|
230
|
+
return Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
|
|
231
|
+
} else {
|
|
232
|
+
return Math.atan2(p2[1] - p1[1], p2[0] - p1[0]);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Line
|
|
236
|
+
if (len === 2) {
|
|
237
|
+
const p0 = points[0],
|
|
238
|
+
p1 = points[1];
|
|
239
|
+
const angle = Math.atan2(p1[1] - p0[1], p1[0] - p0[0]);
|
|
240
|
+
return angle;
|
|
241
|
+
}
|
|
242
|
+
return 0;
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 计算贝塞尔曲线上任意 t (0-1) 位置的点
|
|
247
|
+
*/
|
|
248
|
+
export const getPointAtT = (
|
|
249
|
+
points: [number, number][],
|
|
250
|
+
t = 0.5,
|
|
251
|
+
): [number, number] => {
|
|
252
|
+
const len = points.length;
|
|
253
|
+
if (len === 4) {
|
|
254
|
+
const [p0, p1, p2, p3] = points;
|
|
255
|
+
const mt = 1 - t;
|
|
256
|
+
// B(t) = (1-t)^3*P0 + 3(1-t)^2*t*P1 + 3(1-t)*t^2*P2 + t^3*P3
|
|
257
|
+
return [
|
|
258
|
+
mt ** 3 * p0[0] +
|
|
259
|
+
3 * mt ** 2 * t * p1[0] +
|
|
260
|
+
3 * mt * t ** 2 * p2[0] +
|
|
261
|
+
t ** 3 * p3[0],
|
|
262
|
+
mt ** 3 * p0[1] +
|
|
263
|
+
3 * mt ** 2 * t * p1[1] +
|
|
264
|
+
3 * mt * t ** 2 * p2[1] +
|
|
265
|
+
t ** 3 * p3[1],
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
if (len === 3) {
|
|
269
|
+
const [p0, p1, p2] = points;
|
|
270
|
+
const mt = 1 - t;
|
|
271
|
+
// B(t) = (1-t)^2*P0 + 2(1-t)*t*P1 + t^2*P2
|
|
272
|
+
return [
|
|
273
|
+
mt ** 2 * p0[0] + 2 * mt * t * p1[0] + t ** 2 * p2[0],
|
|
274
|
+
mt ** 2 * p0[1] + 2 * mt * t * p1[1] + t ** 2 * p2[1],
|
|
275
|
+
];
|
|
276
|
+
}
|
|
277
|
+
if (len === 2) {
|
|
278
|
+
const [p0, p1] = points;
|
|
279
|
+
return [p0[0] + (p1[0] - p0[0]) * t, p0[1] + (p1[1] - p0[1]) * t];
|
|
280
|
+
}
|
|
281
|
+
return points[0] || [0, 0];
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export const getLabelPosition = (
|
|
285
|
+
points: [number, number][],
|
|
286
|
+
selfLoopOffset = 10,
|
|
287
|
+
) => {
|
|
288
|
+
const len = points.length;
|
|
289
|
+
// 默认取中点
|
|
290
|
+
const labelPoint = getPointAtT(points);
|
|
291
|
+
|
|
292
|
+
if (len === 4) {
|
|
293
|
+
// 针对自连接(len=4)的特殊偏移处理
|
|
294
|
+
labelPoint[0] += selfLoopOffset;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return labelPoint as [number, number];
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export const getEdgePathD = (points: [number, number][]) => {
|
|
301
|
+
const len = points.length;
|
|
302
|
+
if (len === 4) {
|
|
303
|
+
const [p0, p1, p2, p3] = points;
|
|
304
|
+
return `M ${p0[0]} ${p0[1]} C ${p1[0]} ${p1[1]} ${p2[0]} ${p2[1]} ${p3[0]} ${p3[1]}`;
|
|
305
|
+
}
|
|
306
|
+
if (len === 3) {
|
|
307
|
+
const [p0, p1, p2] = points;
|
|
308
|
+
return `M ${p0[0]} ${p0[1]} Q ${p1[0]} ${p1[1]} ${p2[0]} ${p2[1]}`;
|
|
309
|
+
}
|
|
310
|
+
if (len === 2) {
|
|
311
|
+
const [p0, p1] = points;
|
|
312
|
+
return `M ${p0[0]} ${p0[1]} L ${p1[0]} ${p1[1]}`;
|
|
313
|
+
}
|
|
314
|
+
return '';
|
|
315
|
+
};
|
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UpdatableInfographicOptions } from '../../options';
|
|
2
2
|
import type { ICommand, IStateManager } from '../types';
|
|
3
3
|
|
|
4
4
|
export class UpdateOptionsCommand implements ICommand {
|
|
5
5
|
constructor(
|
|
6
|
-
private options:
|
|
7
|
-
private original?:
|
|
6
|
+
private options: UpdatableInfographicOptions,
|
|
7
|
+
private original?: UpdatableInfographicOptions,
|
|
8
8
|
) {}
|
|
9
9
|
|
|
10
10
|
async apply(state: IStateManager) {
|
|
11
|
-
const prev = state.getOptions();
|
|
12
11
|
if (!this.original) {
|
|
13
|
-
|
|
12
|
+
const prev = state.getOptions();
|
|
13
|
+
this.original = {};
|
|
14
|
+
(
|
|
15
|
+
Object.keys(this.options) as Array<keyof UpdatableInfographicOptions>
|
|
16
|
+
).forEach((key) => {
|
|
17
|
+
(this.original as any)[key] = prev[key];
|
|
18
|
+
});
|
|
14
19
|
}
|
|
15
|
-
state.updateOptions(
|
|
20
|
+
state.updateOptions(this.options);
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
async undo(state: IStateManager) {
|
package/src/editor/editor.ts
CHANGED
|
@@ -6,11 +6,15 @@ import {
|
|
|
6
6
|
PluginManager,
|
|
7
7
|
StateManager,
|
|
8
8
|
} from './managers';
|
|
9
|
+
import { SyncRegistry } from './managers/sync-registry';
|
|
10
|
+
import { CoreSyncPlugin } from './plugins';
|
|
9
11
|
import type {
|
|
10
12
|
ICommandManager,
|
|
11
13
|
IEditor,
|
|
12
14
|
IPluginManager,
|
|
13
15
|
IStateManager,
|
|
16
|
+
ISyncRegistry,
|
|
17
|
+
SyncHandler,
|
|
14
18
|
} from './types';
|
|
15
19
|
|
|
16
20
|
export class Editor implements IEditor {
|
|
@@ -18,6 +22,7 @@ export class Editor implements IEditor {
|
|
|
18
22
|
commander: ICommandManager;
|
|
19
23
|
plugin: IPluginManager;
|
|
20
24
|
interaction: InteractionManager;
|
|
25
|
+
syncRegistry: ISyncRegistry;
|
|
21
26
|
|
|
22
27
|
constructor(
|
|
23
28
|
private emitter: IEventEmitter,
|
|
@@ -34,6 +39,14 @@ export class Editor implements IEditor {
|
|
|
34
39
|
const plugin = new PluginManager();
|
|
35
40
|
const interaction = new InteractionManager();
|
|
36
41
|
|
|
42
|
+
const syncRegistry = new SyncRegistry(() => state.getOptions());
|
|
43
|
+
|
|
44
|
+
this.commander = commander;
|
|
45
|
+
this.state = state;
|
|
46
|
+
this.plugin = plugin;
|
|
47
|
+
this.interaction = interaction;
|
|
48
|
+
this.syncRegistry = syncRegistry;
|
|
49
|
+
|
|
37
50
|
commander.init({ state, emitter });
|
|
38
51
|
state.init({
|
|
39
52
|
emitter,
|
|
@@ -41,6 +54,10 @@ export class Editor implements IEditor {
|
|
|
41
54
|
commander,
|
|
42
55
|
options,
|
|
43
56
|
});
|
|
57
|
+
// Load core plugin: CoreSyncPlugin (handles viewBox/padding sync)
|
|
58
|
+
const corePlugin = new CoreSyncPlugin();
|
|
59
|
+
const userPlugins = options.plugins || [];
|
|
60
|
+
|
|
44
61
|
plugin.init(
|
|
45
62
|
{
|
|
46
63
|
emitter,
|
|
@@ -48,7 +65,7 @@ export class Editor implements IEditor {
|
|
|
48
65
|
commander,
|
|
49
66
|
state,
|
|
50
67
|
},
|
|
51
|
-
|
|
68
|
+
[corePlugin, ...userPlugins],
|
|
52
69
|
);
|
|
53
70
|
interaction.init({
|
|
54
71
|
emitter,
|
|
@@ -57,11 +74,14 @@ export class Editor implements IEditor {
|
|
|
57
74
|
state,
|
|
58
75
|
interactions: options.interactions,
|
|
59
76
|
});
|
|
77
|
+
}
|
|
60
78
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
registerSync(
|
|
80
|
+
path: string,
|
|
81
|
+
handler: SyncHandler,
|
|
82
|
+
options?: { immediate?: boolean },
|
|
83
|
+
) {
|
|
84
|
+
return this.syncRegistry.register(path, handler, options);
|
|
65
85
|
}
|
|
66
86
|
|
|
67
87
|
getDocument() {
|
|
@@ -74,5 +94,6 @@ export class Editor implements IEditor {
|
|
|
74
94
|
this.plugin.destroy();
|
|
75
95
|
this.commander.destroy();
|
|
76
96
|
this.state.destroy();
|
|
97
|
+
this.syncRegistry.destroy();
|
|
77
98
|
}
|
|
78
99
|
}
|
package/src/editor/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
getElementViewportBounds,
|
|
6
6
|
getEventTarget,
|
|
7
7
|
getSelectableTarget,
|
|
8
|
+
isTextSelectionTarget,
|
|
8
9
|
} from '../utils';
|
|
9
10
|
import { Interaction } from './base';
|
|
10
11
|
|
|
@@ -38,7 +39,7 @@ export class BrushSelect extends Interaction implements IInteraction {
|
|
|
38
39
|
private handleStart = (event: PointerEvent) => {
|
|
39
40
|
if (!this.interaction.isActive()) return;
|
|
40
41
|
if (event.button !== 0) return;
|
|
41
|
-
if (
|
|
42
|
+
if (isTextSelectionTarget(event.target)) return;
|
|
42
43
|
if (this.hasElementAtStart(event.target)) return;
|
|
43
44
|
|
|
44
45
|
this.interaction.executeExclusiveInteraction(
|
|
@@ -194,11 +195,4 @@ export class BrushSelect extends Interaction implements IInteraction {
|
|
|
194
195
|
if (getEventTarget(target as unknown as SVGElement)) return true;
|
|
195
196
|
return Boolean(target.closest?.('[data-element-type]'));
|
|
196
197
|
}
|
|
197
|
-
|
|
198
|
-
private isTextSelectionTarget(target: EventTarget | null) {
|
|
199
|
-
if (!(target instanceof HTMLElement)) return false;
|
|
200
|
-
if (target.isContentEditable) return true;
|
|
201
|
-
const tag = target.tagName.toLowerCase();
|
|
202
|
-
return tag === 'input' || tag === 'textarea';
|
|
203
|
-
}
|
|
204
198
|
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { getViewBox, viewBoxToString } from '../../utils';
|
|
2
|
+
import { UpdateOptionsCommand } from '../commands';
|
|
3
|
+
import { IInteraction, InteractionInitOptions, KeyCode } from '../types';
|
|
4
|
+
import { clientToViewport, isTextSelectionTarget } from '../utils';
|
|
5
|
+
import { Interaction } from './base';
|
|
6
|
+
|
|
7
|
+
type CursorType = 'grab' | 'grabbing' | 'default';
|
|
8
|
+
export interface DragCanvasOptions {
|
|
9
|
+
trigger?: KeyCode[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class DragCanvas extends Interaction implements IInteraction {
|
|
13
|
+
name = 'drag-canvas';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 触发交互的按键代码。
|
|
17
|
+
* 参考标准的 KeyboardEvent.code 值:
|
|
18
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code/code_values
|
|
19
|
+
* @default ['Space']
|
|
20
|
+
*/
|
|
21
|
+
public trigger: KeyCode[] = ['Space'];
|
|
22
|
+
|
|
23
|
+
constructor(options?: DragCanvasOptions) {
|
|
24
|
+
super();
|
|
25
|
+
if (options?.trigger) {
|
|
26
|
+
this.trigger = options.trigger;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private isTriggerPressed = false;
|
|
31
|
+
|
|
32
|
+
private pointerId?: number;
|
|
33
|
+
private startPoint?: DOMPoint;
|
|
34
|
+
|
|
35
|
+
private document!: SVGSVGElement;
|
|
36
|
+
|
|
37
|
+
private startViewBoxString?: string;
|
|
38
|
+
|
|
39
|
+
private completeInteraction?: () => void;
|
|
40
|
+
|
|
41
|
+
// 防止组件快捷键侵入性过强
|
|
42
|
+
private isHovering = false;
|
|
43
|
+
|
|
44
|
+
init(options: InteractionInitOptions): void {
|
|
45
|
+
super.init(options);
|
|
46
|
+
this.document = this.editor.getDocument();
|
|
47
|
+
|
|
48
|
+
this.document.addEventListener('mouseenter', this.onMouseEnter);
|
|
49
|
+
this.document.addEventListener('mouseleave', this.onMouseLeave);
|
|
50
|
+
window.addEventListener('keydown', this.handleKeyDown);
|
|
51
|
+
window.addEventListener('blur', this.handleBlur);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
destroy(): void {
|
|
55
|
+
window.removeEventListener('keydown', this.handleKeyDown);
|
|
56
|
+
window.removeEventListener('keyup', this.handleKeyUp);
|
|
57
|
+
|
|
58
|
+
this.document.removeEventListener('pointerdown', this.handlePointerDown);
|
|
59
|
+
window.removeEventListener('pointermove', this.handlePointerMove);
|
|
60
|
+
window.removeEventListener('pointerup', this.handlePointerUp);
|
|
61
|
+
window.removeEventListener('pointercancel', this.handlePointerUp);
|
|
62
|
+
|
|
63
|
+
window.removeEventListener('blur', this.handleBlur);
|
|
64
|
+
this.document.removeEventListener('mouseenter', this.onMouseEnter);
|
|
65
|
+
this.document.removeEventListener('mouseleave', this.onMouseLeave);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private handleKeyDown = (event: KeyboardEvent) => {
|
|
69
|
+
if (!this.interaction.isActive()) return;
|
|
70
|
+
if (isTextSelectionTarget(event.target)) return;
|
|
71
|
+
|
|
72
|
+
// 增加焦点的判断,防止对空格的preventDefault侵入性过强
|
|
73
|
+
const target = event.target as Element;
|
|
74
|
+
const isBody =
|
|
75
|
+
target === document.body || target === document.documentElement;
|
|
76
|
+
const isEditor = target === this.document || this.document.contains(target);
|
|
77
|
+
if (!isBody && !isEditor) return;
|
|
78
|
+
|
|
79
|
+
if (!this.trigger.includes(event.code)) return;
|
|
80
|
+
if (!this.isHovering && !this.isTriggerPressed) return;
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
event.stopPropagation();
|
|
83
|
+
this.interaction.executeExclusiveInteraction(
|
|
84
|
+
this,
|
|
85
|
+
async () =>
|
|
86
|
+
new Promise<void>((resolve) => {
|
|
87
|
+
this.completeInteraction = resolve;
|
|
88
|
+
|
|
89
|
+
this.isTriggerPressed = true;
|
|
90
|
+
const viewBox = getViewBox(this.document);
|
|
91
|
+
|
|
92
|
+
this.startViewBoxString = viewBoxToString(viewBox);
|
|
93
|
+
this.setCursor('grab');
|
|
94
|
+
|
|
95
|
+
this.document.addEventListener('pointerdown', this.handlePointerDown);
|
|
96
|
+
window.addEventListener('keyup', this.handleKeyUp);
|
|
97
|
+
}),
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
private handlePointerDown = (event: PointerEvent) => {
|
|
102
|
+
if (event.button !== 0) return;
|
|
103
|
+
event.preventDefault();
|
|
104
|
+
event.stopPropagation();
|
|
105
|
+
|
|
106
|
+
const svg = this.document;
|
|
107
|
+
this.startPoint = clientToViewport(svg, event.clientX, event.clientY);
|
|
108
|
+
this.pointerId = event.pointerId;
|
|
109
|
+
|
|
110
|
+
this.setCursor('grabbing');
|
|
111
|
+
|
|
112
|
+
window.addEventListener('pointermove', this.handlePointerMove);
|
|
113
|
+
window.addEventListener('pointerup', this.handlePointerUp);
|
|
114
|
+
window.addEventListener('pointercancel', this.handlePointerUp);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
private handlePointerMove = (event: PointerEvent) => {
|
|
118
|
+
if (event.pointerId !== this.pointerId || !this.startPoint) return;
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
event.stopPropagation();
|
|
121
|
+
|
|
122
|
+
const svg = this.document;
|
|
123
|
+
const current = clientToViewport(svg, event.clientX, event.clientY);
|
|
124
|
+
const dx = current.x - this.startPoint.x;
|
|
125
|
+
const dy = current.y - this.startPoint.y;
|
|
126
|
+
|
|
127
|
+
const viewBox = getViewBox(svg);
|
|
128
|
+
|
|
129
|
+
const { x, y, width, height } = viewBox;
|
|
130
|
+
|
|
131
|
+
const newX = x - dx;
|
|
132
|
+
const newY = y - dy;
|
|
133
|
+
|
|
134
|
+
this.state.updateOptions({
|
|
135
|
+
viewBox: viewBoxToString({ x: newX, y: newY, width, height }),
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
private handlePointerUp = (event: PointerEvent) => {
|
|
140
|
+
if (event.pointerId !== this.pointerId) return;
|
|
141
|
+
|
|
142
|
+
this.startPoint = undefined;
|
|
143
|
+
this.pointerId = undefined;
|
|
144
|
+
this.setCursor('grab');
|
|
145
|
+
window.removeEventListener('pointermove', this.handlePointerMove);
|
|
146
|
+
window.removeEventListener('pointerup', this.handlePointerUp);
|
|
147
|
+
window.removeEventListener('pointercancel', this.handlePointerUp);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
private handleKeyUp = (event: KeyboardEvent) => {
|
|
151
|
+
if (!this.trigger.includes(event.code)) return;
|
|
152
|
+
this.stopDrag();
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
private stopDrag = () => {
|
|
156
|
+
if (this.startViewBoxString) {
|
|
157
|
+
const svg = this.document;
|
|
158
|
+
const viewBox = getViewBox(svg);
|
|
159
|
+
const currentViewBoxString = viewBoxToString(viewBox);
|
|
160
|
+
|
|
161
|
+
if (this.startViewBoxString !== currentViewBoxString) {
|
|
162
|
+
const command = new UpdateOptionsCommand(
|
|
163
|
+
{ viewBox: currentViewBoxString },
|
|
164
|
+
{ viewBox: this.startViewBoxString },
|
|
165
|
+
);
|
|
166
|
+
void this.commander.execute(command);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
this.startViewBoxString = undefined;
|
|
170
|
+
|
|
171
|
+
this.isTriggerPressed = false;
|
|
172
|
+
|
|
173
|
+
this.setCursor('default');
|
|
174
|
+
|
|
175
|
+
this.startPoint = undefined;
|
|
176
|
+
this.pointerId = undefined;
|
|
177
|
+
|
|
178
|
+
window.removeEventListener('keyup', this.handleKeyUp);
|
|
179
|
+
|
|
180
|
+
this.document.removeEventListener('pointerdown', this.handlePointerDown);
|
|
181
|
+
window.removeEventListener('pointermove', this.handlePointerMove);
|
|
182
|
+
window.removeEventListener('pointerup', this.handlePointerUp);
|
|
183
|
+
window.removeEventListener('pointercancel', this.handlePointerUp);
|
|
184
|
+
|
|
185
|
+
this.completeInteraction?.();
|
|
186
|
+
this.completeInteraction = undefined;
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
private setCursor = (behavior: CursorType) => {
|
|
190
|
+
document.body.style.cursor = behavior;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
private handleBlur = () => {
|
|
194
|
+
this.stopDrag();
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
private onMouseEnter = () => {
|
|
198
|
+
this.isHovering = true;
|
|
199
|
+
};
|
|
200
|
+
private onMouseLeave = () => {
|
|
201
|
+
this.isHovering = false;
|
|
202
|
+
};
|
|
203
|
+
}
|
|
@@ -157,10 +157,6 @@ export class DragElement extends Interaction implements IInteraction {
|
|
|
157
157
|
if (this.exclusiveStarted) return true;
|
|
158
158
|
if (!this.startTarget) return false;
|
|
159
159
|
|
|
160
|
-
if (this.willReplaceSelection) {
|
|
161
|
-
this.interaction.select([this.startTarget], 'replace');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
160
|
this.dragItems = this.selectionForDrag
|
|
165
161
|
.filter((element) => isEditableText(element))
|
|
166
162
|
.map((element) => this.createDragItem(element))
|
|
@@ -173,6 +169,11 @@ export class DragElement extends Interaction implements IInteraction {
|
|
|
173
169
|
this,
|
|
174
170
|
async () =>
|
|
175
171
|
new Promise<void>((resolve) => {
|
|
172
|
+
// 只有拿到锁之后,才真正执行选中逻辑
|
|
173
|
+
if (this.willReplaceSelection && this.startTarget) {
|
|
174
|
+
this.interaction.select([this.startTarget], 'replace');
|
|
175
|
+
}
|
|
176
|
+
|
|
176
177
|
this.completeInteraction = resolve;
|
|
177
178
|
started = true;
|
|
178
179
|
}),
|
|
@@ -2,6 +2,7 @@ export { Interaction } from './base';
|
|
|
2
2
|
export { BrushSelect } from './brush-select';
|
|
3
3
|
export { ClickSelect } from './click-select';
|
|
4
4
|
export { DblClickEditText } from './dblclick-edit-text';
|
|
5
|
+
export { DragCanvas } from './drag-canvas';
|
|
5
6
|
export { DragElement } from './drag-element';
|
|
6
7
|
export { HotkeyHistory } from './hotkey-history';
|
|
7
8
|
export { SelectHighlight } from './select-highlight';
|