kritzel-react 0.1.30 → 0.1.32
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/kritzel-react/lib/components/stencil-generated/components.js +122 -0
- package/dist/kritzel-react/lib/index.js +2 -0
- package/dist/kritzel-stencil/src/classes/core/core.class.js +797 -0
- package/dist/kritzel-stencil/src/classes/core/reviver.class.js +97 -0
- package/dist/kritzel-stencil/src/classes/core/store.class.js +153 -0
- package/dist/kritzel-stencil/src/classes/core/viewport.class.js +311 -0
- package/dist/kritzel-stencil/src/classes/core/workspace.class.js +34 -0
- package/dist/kritzel-stencil/src/classes/handlers/base.handler.js +6 -0
- package/dist/kritzel-stencil/src/classes/handlers/context-menu.handler.js +63 -0
- package/dist/kritzel-stencil/src/classes/handlers/hover.handler.js +18 -0
- package/dist/kritzel-stencil/src/classes/handlers/key.handler.js +76 -0
- package/dist/kritzel-stencil/src/classes/handlers/line-handle.handler.js +382 -0
- package/dist/kritzel-stencil/src/classes/handlers/move.handler.js +213 -0
- package/dist/kritzel-stencil/src/classes/handlers/resize.handler.js +205 -0
- package/dist/kritzel-stencil/src/classes/handlers/rotation.handler.js +117 -0
- package/dist/kritzel-stencil/src/classes/handlers/selection.handler.js +313 -0
- package/dist/kritzel-stencil/src/classes/managers/anchor.manager.js +1056 -0
- package/dist/kritzel-stencil/src/classes/managers/cursor.manager.js +117 -0
- package/dist/kritzel-stencil/src/classes/managers/theme.manager.js +103 -0
- package/dist/kritzel-stencil/src/classes/objects/base-object.class.js +249 -0
- package/dist/kritzel-stencil/src/classes/objects/custom-element.class.js +60 -0
- package/dist/kritzel-stencil/src/classes/objects/group.class.js +407 -0
- package/dist/kritzel-stencil/src/classes/objects/image.class.js +55 -0
- package/dist/kritzel-stencil/src/classes/objects/line.class.js +608 -0
- package/dist/kritzel-stencil/src/classes/objects/path.class.js +401 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-box.class.js +21 -0
- package/dist/kritzel-stencil/src/classes/objects/selection-group.class.js +409 -0
- package/dist/kritzel-stencil/src/classes/objects/shape.class.js +412 -0
- package/dist/kritzel-stencil/src/classes/objects/text.class.js +292 -0
- package/dist/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.js +101 -0
- package/dist/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.js +241 -0
- package/dist/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.js +43 -0
- package/dist/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.js +98 -0
- package/dist/kritzel-stencil/src/classes/registries/icon-registry.class.js +66 -0
- package/dist/kritzel-stencil/src/classes/registries/tool.registry.js +21 -0
- package/dist/kritzel-stencil/src/classes/structures/app-state-map.structure.js +212 -0
- package/dist/kritzel-stencil/src/classes/structures/object-map.structure.js +414 -0
- package/dist/kritzel-stencil/src/classes/structures/quadtree.structure.js +151 -0
- package/dist/kritzel-stencil/src/classes/tools/base-tool.class.js +36 -0
- package/dist/kritzel-stencil/src/classes/tools/brush-tool.class.js +161 -0
- package/dist/kritzel-stencil/src/classes/tools/eraser-tool.class.js +85 -0
- package/dist/kritzel-stencil/src/classes/tools/image-tool.class.js +83 -0
- package/dist/kritzel-stencil/src/classes/tools/line-tool.class.js +187 -0
- package/dist/kritzel-stencil/src/classes/tools/selection-tool.class.js +429 -0
- package/dist/kritzel-stencil/src/classes/tools/shape-tool.class.js +196 -0
- package/dist/kritzel-stencil/src/classes/tools/text-tool.class.js +100 -0
- package/dist/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.js +1343 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.js +46 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.js +312 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.js +60 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.js +105 -0
- package/dist/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.js +53 -0
- package/dist/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.js +137 -0
- package/dist/kritzel-stencil/src/configs/default-brush-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-engine-config.js +63 -0
- package/dist/kritzel-stencil/src/configs/default-line-tool.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-sync.config.js +9 -0
- package/dist/kritzel-stencil/src/configs/default-text-tool.config.js +7 -0
- package/dist/kritzel-stencil/src/constants/color-palette.constants.js +37 -0
- package/dist/kritzel-stencil/src/constants/engine.constants.js +2 -0
- package/dist/kritzel-stencil/src/enums/event-button.enum.js +6 -0
- package/dist/kritzel-stencil/src/enums/handle-type.enum.js +7 -0
- package/dist/kritzel-stencil/src/enums/shape-type.enum.js +6 -0
- package/dist/kritzel-stencil/src/helpers/class.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/color.helper.js +106 -0
- package/dist/kritzel-stencil/src/helpers/cursor.helper.js +57 -0
- package/dist/kritzel-stencil/src/helpers/devices.helper.js +28 -0
- package/dist/kritzel-stencil/src/helpers/event.helper.js +58 -0
- package/dist/kritzel-stencil/src/helpers/geometry.helper.js +149 -0
- package/dist/kritzel-stencil/src/helpers/keyboard.helper.js +51 -0
- package/dist/kritzel-stencil/src/helpers/math.helper.js +5 -0
- package/dist/kritzel-stencil/src/helpers/object.helper.js +11 -0
- package/dist/kritzel-stencil/src/helpers/theme.helper.js +69 -0
- package/dist/kritzel-stencil/src/index.js +41 -0
- package/dist/kritzel-stencil/src/interfaces/anchor.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/arrow-head.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/bounding-box.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/clonable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/context-menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/debug-info.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/dialog.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/displayable-shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/engine-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/line-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/master-detail.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/menu-item.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/object.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/path-options.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/point.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/polygon.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/serializable.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/settings.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/shortcut.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/sync-provider.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/theme.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool-config.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/tool.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/toolbar-control.interface.js +1 -0
- package/dist/kritzel-stencil/src/interfaces/undo-state.interface.js +1 -0
- package/dist/kritzel-stencil/src/themes/dark-theme.js +198 -0
- package/dist/kritzel-stencil/src/themes/light-theme.js +199 -0
- package/dist/kritzel-stencil/src/types/shortcut.type.js +1 -0
- package/dist/kritzel-stencil/src/types/state.types.js +1 -0
- package/dist/types/kritzel-react/lib/components/stencil-generated/components.d.ts +74 -0
- package/dist/types/kritzel-react/lib/index.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/classes/core/core.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/core/reviver.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/core/store.class.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/classes/core/viewport.class.d.ts +48 -0
- package/dist/types/kritzel-stencil/src/classes/core/workspace.class.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/base.handler.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/context-menu.handler.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/hover.handler.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/key.handler.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/line-handle.handler.d.ts +34 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/move.handler.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/resize.handler.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/rotation.handler.d.ts +12 -0
- package/dist/types/kritzel-stencil/src/classes/handlers/selection.handler.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/classes/managers/anchor.manager.d.ts +180 -0
- package/dist/types/kritzel-stencil/src/classes/managers/cursor.manager.d.ts +43 -0
- package/dist/types/kritzel-stencil/src/classes/managers/theme.manager.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/objects/base-object.class.d.ts +76 -0
- package/dist/types/kritzel-stencil/src/classes/objects/custom-element.class.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/classes/objects/group.class.d.ts +97 -0
- package/dist/types/kritzel-stencil/src/classes/objects/image.class.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/classes/objects/line.class.d.ts +101 -0
- package/dist/types/kritzel-stencil/src/classes/objects/path.class.d.ts +62 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-box.class.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/classes/objects/selection-group.class.d.ts +67 -0
- package/dist/types/kritzel-stencil/src/classes/objects/shape.class.d.ts +124 -0
- package/dist/types/kritzel-stencil/src/classes/objects/text.class.d.ts +56 -0
- package/dist/types/kritzel-stencil/src/classes/providers/broadcast-sync-provider.class.d.ts +18 -0
- package/dist/types/kritzel-stencil/src/classes/providers/hocuspocus-sync-provider.class.d.ts +120 -0
- package/dist/types/kritzel-stencil/src/classes/providers/indexeddb-sync-provider.class.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/classes/providers/websocket-sync-provider.class.d.ts +52 -0
- package/dist/types/kritzel-stencil/src/classes/registries/icon-registry.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/registries/tool.registry.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/classes/structures/app-state-map.structure.d.ts +31 -0
- package/dist/types/kritzel-stencil/src/classes/structures/object-map.structure.d.ts +63 -0
- package/dist/types/kritzel-stencil/src/classes/structures/quadtree.structure.d.ts +36 -0
- package/dist/types/kritzel-stencil/src/classes/tools/base-tool.class.d.ts +20 -0
- package/dist/types/kritzel-stencil/src/classes/tools/brush-tool.class.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/classes/tools/eraser-tool.class.d.ts +9 -0
- package/dist/types/kritzel-stencil/src/classes/tools/image-tool.class.d.ts +15 -0
- package/dist/types/kritzel-stencil/src/classes/tools/line-tool.class.d.ts +19 -0
- package/dist/types/kritzel-stencil/src/classes/tools/selection-tool.class.d.ts +54 -0
- package/dist/types/kritzel-stencil/src/classes/tools/shape-tool.class.d.ts +39 -0
- package/dist/types/kritzel-stencil/src/classes/tools/text-tool.class.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/core/kritzel-engine/kritzel-engine.d.ts +111 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-brush-style/kritzel-brush-style.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-dropdown/kritzel-dropdown.d.ts +46 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-font-family/kritzel-font-family.d.ts +13 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-line-endings/kritzel-line-endings.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/components/shared/kritzel-shape-fill/kritzel-shape-fill.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/components/ui/kritzel-context-menu/kritzel-context-menu.d.ts +21 -0
- package/dist/types/kritzel-stencil/src/configs/default-brush-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-engine-config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-line-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/configs/default-sync.config.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/configs/default-text-tool.config.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/constants/color-palette.constants.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/constants/engine.constants.d.ts +2 -0
- package/dist/types/kritzel-stencil/src/enums/event-button.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/enums/handle-type.enum.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/enums/shape-type.enum.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/helpers/class.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/color.helper.d.ts +33 -0
- package/dist/types/kritzel-stencil/src/helpers/cursor.helper.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/helpers/devices.helper.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/helpers/event.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/geometry.helper.d.ts +38 -0
- package/dist/types/kritzel-stencil/src/helpers/keyboard.helper.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/helpers/math.helper.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/helpers/object.helper.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/helpers/theme.helper.d.ts +41 -0
- package/dist/types/kritzel-stencil/src/index.d.ts +42 -0
- package/dist/types/kritzel-stencil/src/interfaces/anchor.interface.d.ts +137 -0
- package/dist/types/kritzel-stencil/src/interfaces/arrow-head.interface.d.ts +27 -0
- package/dist/types/kritzel-stencil/src/interfaces/bounding-box.interface.d.ts +8 -0
- package/dist/types/kritzel-stencil/src/interfaces/clonable.interface.d.ts +3 -0
- package/dist/types/kritzel-stencil/src/interfaces/context-menu-item.interface.d.ts +17 -0
- package/dist/types/kritzel-stencil/src/interfaces/debug-info.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/dialog.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/displayable-shortcut.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/engine-state.interface.d.ts +73 -0
- package/dist/types/kritzel-stencil/src/interfaces/line-options.interface.d.ts +23 -0
- package/dist/types/kritzel-stencil/src/interfaces/master-detail.interface.d.ts +14 -0
- package/dist/types/kritzel-stencil/src/interfaces/menu-item.interface.d.ts +24 -0
- package/dist/types/kritzel-stencil/src/interfaces/object.interface.d.ts +53 -0
- package/dist/types/kritzel-stencil/src/interfaces/path-options.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/point.interface.d.ts +4 -0
- package/dist/types/kritzel-stencil/src/interfaces/polygon.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/serializable.interface.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/interfaces/settings.interface.d.ts +11 -0
- package/dist/types/kritzel-stencil/src/interfaces/shortcut.interface.d.ts +10 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-config.interface.d.ts +22 -0
- package/dist/types/kritzel-stencil/src/interfaces/sync-provider.interface.d.ts +29 -0
- package/dist/types/kritzel-stencil/src/interfaces/theme.interface.d.ts +330 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool-config.interface.d.ts +26 -0
- package/dist/types/kritzel-stencil/src/interfaces/tool.interface.d.ts +7 -0
- package/dist/types/kritzel-stencil/src/interfaces/toolbar-control.interface.d.ts +58 -0
- package/dist/types/kritzel-stencil/src/interfaces/undo-state.interface.d.ts +6 -0
- package/dist/types/kritzel-stencil/src/themes/dark-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/themes/light-theme.d.ts +5 -0
- package/dist/types/kritzel-stencil/src/types/shortcut.type.d.ts +1 -0
- package/dist/types/kritzel-stencil/src/types/state.types.d.ts +3 -0
- package/package.json +2 -2
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
import { KritzelBaseObject } from './base-object.class';
|
|
2
|
+
import { KritzelGeometryHelper } from '../../helpers/geometry.helper';
|
|
3
|
+
import { KritzelColorHelper } from '../../helpers/color.helper';
|
|
4
|
+
export class KritzelLine extends KritzelBaseObject {
|
|
5
|
+
get d() {
|
|
6
|
+
if (this.controlX !== undefined && this.controlY !== undefined) {
|
|
7
|
+
return `M ${this.startX} ${this.startY} Q ${this.controlX} ${this.controlY} ${this.endX} ${this.endY}`;
|
|
8
|
+
}
|
|
9
|
+
return `M ${this.startX} ${this.startY} L ${this.endX} ${this.endY}`;
|
|
10
|
+
}
|
|
11
|
+
get viewBox() {
|
|
12
|
+
return `${this.x} ${this.y} ${this.width} ${this.height}`;
|
|
13
|
+
}
|
|
14
|
+
constructor(config) {
|
|
15
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
16
|
+
super();
|
|
17
|
+
this.__class__ = 'KritzelLine';
|
|
18
|
+
this.scale = 1;
|
|
19
|
+
this.isVisible = true;
|
|
20
|
+
this.isDebugInfoVisible = true;
|
|
21
|
+
this.isCompleted = false;
|
|
22
|
+
this._adjustedPoints = null;
|
|
23
|
+
this._clipInfo = null;
|
|
24
|
+
this.options = config;
|
|
25
|
+
this.startX = (_a = config === null || config === void 0 ? void 0 : config.startX) !== null && _a !== void 0 ? _a : 0;
|
|
26
|
+
this.startY = (_b = config === null || config === void 0 ? void 0 : config.startY) !== null && _b !== void 0 ? _b : 0;
|
|
27
|
+
this.endX = (_c = config === null || config === void 0 ? void 0 : config.endX) !== null && _c !== void 0 ? _c : 0;
|
|
28
|
+
this.endY = (_d = config === null || config === void 0 ? void 0 : config.endY) !== null && _d !== void 0 ? _d : 0;
|
|
29
|
+
this.controlX = config === null || config === void 0 ? void 0 : config.controlX;
|
|
30
|
+
this.controlY = config === null || config === void 0 ? void 0 : config.controlY;
|
|
31
|
+
this.translateX = (_e = config === null || config === void 0 ? void 0 : config.translateX) !== null && _e !== void 0 ? _e : 0;
|
|
32
|
+
this.translateY = (_f = config === null || config === void 0 ? void 0 : config.translateY) !== null && _f !== void 0 ? _f : 0;
|
|
33
|
+
this.scale = (_g = config === null || config === void 0 ? void 0 : config.scale) !== null && _g !== void 0 ? _g : 1;
|
|
34
|
+
this.strokeWidth = (_h = config === null || config === void 0 ? void 0 : config.strokeWidth) !== null && _h !== void 0 ? _h : 4;
|
|
35
|
+
this.stroke = (_j = config === null || config === void 0 ? void 0 : config.stroke) !== null && _j !== void 0 ? _j : { light: '#000000', dark: '#ffffff' };
|
|
36
|
+
this.startAnchor = config === null || config === void 0 ? void 0 : config.startAnchor;
|
|
37
|
+
this.endAnchor = config === null || config === void 0 ? void 0 : config.endAnchor;
|
|
38
|
+
this.arrows = config === null || config === void 0 ? void 0 : config.arrows;
|
|
39
|
+
this.updateDimensions();
|
|
40
|
+
}
|
|
41
|
+
static create(core, options) {
|
|
42
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
43
|
+
const object = new KritzelLine();
|
|
44
|
+
object._core = core;
|
|
45
|
+
object.id = object.generateId();
|
|
46
|
+
object.workspaceId = core.store.state.activeWorkspace.id;
|
|
47
|
+
object.options = options;
|
|
48
|
+
object.startX = (_a = options === null || options === void 0 ? void 0 : options.startX) !== null && _a !== void 0 ? _a : 0;
|
|
49
|
+
object.startY = (_b = options === null || options === void 0 ? void 0 : options.startY) !== null && _b !== void 0 ? _b : 0;
|
|
50
|
+
object.endX = (_c = options === null || options === void 0 ? void 0 : options.endX) !== null && _c !== void 0 ? _c : 0;
|
|
51
|
+
object.endY = (_d = options === null || options === void 0 ? void 0 : options.endY) !== null && _d !== void 0 ? _d : 0;
|
|
52
|
+
object.controlX = options === null || options === void 0 ? void 0 : options.controlX;
|
|
53
|
+
object.controlY = options === null || options === void 0 ? void 0 : options.controlY;
|
|
54
|
+
object.translateX = (_e = options === null || options === void 0 ? void 0 : options.translateX) !== null && _e !== void 0 ? _e : 0;
|
|
55
|
+
object.translateY = (_f = options === null || options === void 0 ? void 0 : options.translateY) !== null && _f !== void 0 ? _f : 0;
|
|
56
|
+
object.scale = (_g = options === null || options === void 0 ? void 0 : options.scale) !== null && _g !== void 0 ? _g : 1;
|
|
57
|
+
object.strokeWidth = (_h = options === null || options === void 0 ? void 0 : options.strokeWidth) !== null && _h !== void 0 ? _h : 4;
|
|
58
|
+
object.stroke = (_j = options === null || options === void 0 ? void 0 : options.stroke) !== null && _j !== void 0 ? _j : { light: '#000000', dark: '#ffffff' };
|
|
59
|
+
object.opacity = (_k = options === null || options === void 0 ? void 0 : options.opacity) !== null && _k !== void 0 ? _k : 1;
|
|
60
|
+
object.startAnchor = options === null || options === void 0 ? void 0 : options.startAnchor;
|
|
61
|
+
object.endAnchor = options === null || options === void 0 ? void 0 : options.endAnchor;
|
|
62
|
+
object.arrows = options === null || options === void 0 ? void 0 : options.arrows;
|
|
63
|
+
object.zIndex = core.store.currentZIndex;
|
|
64
|
+
object.updateDimensions();
|
|
65
|
+
return object;
|
|
66
|
+
}
|
|
67
|
+
resize(x, y, width, height) {
|
|
68
|
+
if (width <= 1 || height <= 1) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const scaleX = width / this.width;
|
|
72
|
+
const scaleY = height / this.height;
|
|
73
|
+
// Scale the line endpoints
|
|
74
|
+
this.startX = this.startX * scaleX;
|
|
75
|
+
this.startY = this.startY * scaleY;
|
|
76
|
+
this.endX = this.endX * scaleX;
|
|
77
|
+
this.endY = this.endY * scaleY;
|
|
78
|
+
if (this.controlX !== undefined && this.controlY !== undefined) {
|
|
79
|
+
this.controlX = this.controlX * scaleX;
|
|
80
|
+
this.controlY = this.controlY * scaleY;
|
|
81
|
+
}
|
|
82
|
+
// Recalculate dimensions from scaled endpoints
|
|
83
|
+
const { minX, minY, maxX, maxY } = this.calculateBoundingBox();
|
|
84
|
+
this.width = maxX - minX;
|
|
85
|
+
this.height = maxY - minY;
|
|
86
|
+
this.x = minX;
|
|
87
|
+
this.y = minY;
|
|
88
|
+
// Set the new position
|
|
89
|
+
this.translateX = x;
|
|
90
|
+
this.translateY = y;
|
|
91
|
+
this._adjustedPoints = null;
|
|
92
|
+
this._clipInfo = null;
|
|
93
|
+
this._core.store.state.objects.update(this);
|
|
94
|
+
// Update anchors after the line is updated
|
|
95
|
+
this._core.anchorManager.updateAnchorsForObject(this.id);
|
|
96
|
+
if (this.startAnchor) {
|
|
97
|
+
this._core.anchorManager.updateAnchorsForObject(this.startAnchor.objectId);
|
|
98
|
+
}
|
|
99
|
+
if (this.endAnchor) {
|
|
100
|
+
this._core.anchorManager.updateAnchorsForObject(this.endAnchor.objectId);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
rotate(value) {
|
|
104
|
+
this.rotation = value;
|
|
105
|
+
this._adjustedPoints = null;
|
|
106
|
+
this._clipInfo = null;
|
|
107
|
+
this._core.store.state.objects.update(this);
|
|
108
|
+
}
|
|
109
|
+
move(startX, startY, endX, endY) {
|
|
110
|
+
const deltaX = (startX - endX) / this._core.store.state.scale;
|
|
111
|
+
const deltaY = (startY - endY) / this._core.store.state.scale;
|
|
112
|
+
this.translateX += deltaX;
|
|
113
|
+
this.translateY += deltaY;
|
|
114
|
+
// If the line is anchored, we need to ensure the anchored endpoints stay at the target
|
|
115
|
+
if (this.startAnchor) {
|
|
116
|
+
this._core.anchorManager.updateAnchorsForObject(this.startAnchor.objectId);
|
|
117
|
+
}
|
|
118
|
+
if (this.endAnchor) {
|
|
119
|
+
this._core.anchorManager.updateAnchorsForObject(this.endAnchor.objectId);
|
|
120
|
+
}
|
|
121
|
+
this._adjustedPoints = null;
|
|
122
|
+
this._clipInfo = null;
|
|
123
|
+
this._core.store.state.objects.update(this);
|
|
124
|
+
}
|
|
125
|
+
hitTest(x, y) {
|
|
126
|
+
var _a, _b, _c, _d;
|
|
127
|
+
const minHitThreshold = 20;
|
|
128
|
+
const strokeWidth = Math.max(this.strokeWidth, minHitThreshold);
|
|
129
|
+
const halfStroke = strokeWidth / this.scale / 2;
|
|
130
|
+
if (this._adjustedPoints === null) {
|
|
131
|
+
this._adjustedPoints = this.computeAdjustedPoints();
|
|
132
|
+
}
|
|
133
|
+
// For curved lines, use distance to the Bezier curve
|
|
134
|
+
if (this.controlX !== undefined && this.controlY !== undefined) {
|
|
135
|
+
const clip = this.getClipInfo();
|
|
136
|
+
const startT = (_b = (_a = clip.start) === null || _a === void 0 ? void 0 : _a.t) !== null && _b !== void 0 ? _b : 0;
|
|
137
|
+
const endT = (_d = (_c = clip.end) === null || _c === void 0 ? void 0 : _c.t) !== null && _d !== void 0 ? _d : 1;
|
|
138
|
+
const distance = this.pointToBezierDistance(x, y, startT, endT);
|
|
139
|
+
return distance <= halfStroke;
|
|
140
|
+
}
|
|
141
|
+
// For straight lines, use distance to line segment
|
|
142
|
+
const clip = this.getClipInfo();
|
|
143
|
+
const p1 = clip.start ? [clip.start.x, clip.start.y] : this._adjustedPoints[0];
|
|
144
|
+
const p2 = clip.end ? [clip.end.x, clip.end.y] : this._adjustedPoints[1];
|
|
145
|
+
const distance = this.pointToLineSegmentDistance(x, y, p1[0], p1[1], p2[0], p2[1]);
|
|
146
|
+
return distance <= halfStroke;
|
|
147
|
+
}
|
|
148
|
+
hitTestPolygon(polygon) {
|
|
149
|
+
var _a, _b, _c, _d;
|
|
150
|
+
const halfStroke = this.strokeWidth / this.scale / 2;
|
|
151
|
+
if (this._adjustedPoints === null) {
|
|
152
|
+
this._adjustedPoints = this.computeAdjustedPoints();
|
|
153
|
+
}
|
|
154
|
+
const clip = this.getClipInfo();
|
|
155
|
+
const polyPoints = [
|
|
156
|
+
{ x: polygon.bottomLeft.x, y: polygon.bottomLeft.y },
|
|
157
|
+
{ x: polygon.bottomRight.x, y: polygon.bottomRight.y },
|
|
158
|
+
{ x: polygon.topRight.x, y: polygon.topRight.y },
|
|
159
|
+
{ x: polygon.topLeft.x, y: polygon.topLeft.y },
|
|
160
|
+
];
|
|
161
|
+
// Check if any endpoint is inside the polygon
|
|
162
|
+
// Use clipped endpoints
|
|
163
|
+
const p1 = clip.start ? [clip.start.x, clip.start.y] : this._adjustedPoints[0];
|
|
164
|
+
const p2 = clip.end ? [clip.end.x, clip.end.y] : this._adjustedPoints[1];
|
|
165
|
+
const endpoints = [p1, p2];
|
|
166
|
+
for (const [px, py] of endpoints) {
|
|
167
|
+
if (KritzelGeometryHelper.isPointInPolygon({ x: px, y: py }, polyPoints)) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Check if any polygon vertex is on the line/curve
|
|
172
|
+
for (const pt of polyPoints) {
|
|
173
|
+
if (this.hitTest(pt.x, pt.y)) {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// For curved lines, sample points along the curve and check if any are inside the polygon
|
|
178
|
+
if (this.controlX !== undefined && this.controlY !== undefined) {
|
|
179
|
+
const p0 = this._adjustedPoints[0];
|
|
180
|
+
const p2 = this._adjustedPoints[1];
|
|
181
|
+
const controlAdjusted = this.computeAdjustedControlPoint();
|
|
182
|
+
const startT = (_b = (_a = clip.start) === null || _a === void 0 ? void 0 : _a.t) !== null && _b !== void 0 ? _b : 0;
|
|
183
|
+
const endT = (_d = (_c = clip.end) === null || _c === void 0 ? void 0 : _c.t) !== null && _d !== void 0 ? _d : 1;
|
|
184
|
+
const samples = 20;
|
|
185
|
+
for (let i = 0; i <= samples; i++) {
|
|
186
|
+
const fraction = i / samples;
|
|
187
|
+
const t = startT + fraction * (endT - startT);
|
|
188
|
+
const oneMinusT = 1 - t;
|
|
189
|
+
const bx = oneMinusT * oneMinusT * p0[0] + 2 * oneMinusT * t * controlAdjusted[0] + t * t * p2[0];
|
|
190
|
+
const by = oneMinusT * oneMinusT * p0[1] + 2 * oneMinusT * t * controlAdjusted[1] + t * t * p2[1];
|
|
191
|
+
if (KritzelGeometryHelper.isPointInPolygon({ x: bx, y: by }, polyPoints)) {
|
|
192
|
+
return true;
|
|
193
|
+
}
|
|
194
|
+
// Also check if curve point is within stroke distance of polygon edges
|
|
195
|
+
for (let j = 0; j < polyPoints.length; j++) {
|
|
196
|
+
const q1 = polyPoints[j];
|
|
197
|
+
const q2 = polyPoints[(j + 1) % polyPoints.length];
|
|
198
|
+
const d = this.pointToLineSegmentDistance(bx, by, q1.x, q1.y, q2.x, q2.y);
|
|
199
|
+
if (d <= halfStroke) {
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
// For straight lines, check if line intersects any polygon edge
|
|
207
|
+
const checkP1 = { x: p1[0], y: p1[1] };
|
|
208
|
+
const checkP2 = { x: p2[0], y: p2[1] };
|
|
209
|
+
for (let j = 0; j < polyPoints.length; j++) {
|
|
210
|
+
const q1 = polyPoints[j];
|
|
211
|
+
const q2 = polyPoints[(j + 1) % polyPoints.length];
|
|
212
|
+
if (KritzelGeometryHelper.intersectLines(checkP1, checkP2, q1, q2)) {
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
// Check distance from polygon edges to line segment
|
|
216
|
+
const d1 = this.pointToLineSegmentDistance(q1.x, q1.y, checkP1.x, checkP1.y, checkP2.x, checkP2.y);
|
|
217
|
+
const d2 = this.pointToLineSegmentDistance(q2.x, q2.y, checkP1.x, checkP1.y, checkP2.x, checkP2.y);
|
|
218
|
+
const d3 = this.pointToLineSegmentDistance(checkP1.x, checkP1.y, q1.x, q1.y, q2.x, q2.y);
|
|
219
|
+
const d4 = this.pointToLineSegmentDistance(checkP2.x, checkP2.y, q1.x, q1.y, q2.x, q2.y);
|
|
220
|
+
const minD = Math.min(d1, d2, d3, d4);
|
|
221
|
+
if (minD <= halfStroke) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
updatePosition(x, y) {
|
|
228
|
+
this.translateX = x;
|
|
229
|
+
this.translateY = y;
|
|
230
|
+
this._adjustedPoints = null;
|
|
231
|
+
this._clipInfo = null;
|
|
232
|
+
this._core.store.state.objects.update(this);
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Updates a specific endpoint of the line (start or end).
|
|
236
|
+
* The coordinates are in viewBox-local space (relative to x, y origin).
|
|
237
|
+
* This method recalculates the bounding box dimensions.
|
|
238
|
+
*
|
|
239
|
+
* @param handleType - Which endpoint to update: 'start' or 'end'
|
|
240
|
+
* @param newX - New X coordinate in viewBox-local space
|
|
241
|
+
* @param newY - New Y coordinate in viewBox-local space
|
|
242
|
+
*/
|
|
243
|
+
updateEndpoint(handleType, newX, newY) {
|
|
244
|
+
// Update the appropriate endpoint
|
|
245
|
+
if (handleType === 'start') {
|
|
246
|
+
this.startX = newX;
|
|
247
|
+
this.startY = newY;
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
this.endX = newX;
|
|
251
|
+
this.endY = newY;
|
|
252
|
+
}
|
|
253
|
+
const oldWidth = this.width;
|
|
254
|
+
const oldHeight = this.height;
|
|
255
|
+
// Recalculate the bounding box (viewBox dimensions)
|
|
256
|
+
const { minX, minY, maxX, maxY } = this.calculateBoundingBox();
|
|
257
|
+
// Calculate the change in origin (in local coordinates)
|
|
258
|
+
const deltaX = minX - this.x;
|
|
259
|
+
const deltaY = minY - this.y;
|
|
260
|
+
const newWidth = maxX - minX;
|
|
261
|
+
const newHeight = maxY - minY;
|
|
262
|
+
const deltaWidth = newWidth - oldWidth;
|
|
263
|
+
const deltaHeight = newHeight - oldHeight;
|
|
264
|
+
const deltaCx = deltaWidth / 2;
|
|
265
|
+
const deltaCy = deltaHeight / 2;
|
|
266
|
+
// Update viewBox dimensions
|
|
267
|
+
this.x = minX;
|
|
268
|
+
this.y = minY;
|
|
269
|
+
this.width = newWidth;
|
|
270
|
+
this.height = newHeight;
|
|
271
|
+
// Rotate the delta to world coordinates before applying to translate
|
|
272
|
+
const cos = Math.cos(this.rotation);
|
|
273
|
+
const sin = Math.sin(this.rotation);
|
|
274
|
+
// We need to compensate for:
|
|
275
|
+
// 1. The shift of the top-left corner (deltaX, deltaY)
|
|
276
|
+
// 2. The shift of the center point (deltaCx, deltaCy) which affects rotation pivot
|
|
277
|
+
// Formula: DeltaT = R(DeltaPos + DeltaCenter) - DeltaCenter
|
|
278
|
+
const vx = deltaX + deltaCx;
|
|
279
|
+
const vy = deltaY + deltaCy;
|
|
280
|
+
const rotatedVx = vx * cos - vy * sin;
|
|
281
|
+
const rotatedVy = vx * sin + vy * cos;
|
|
282
|
+
const correctionX = rotatedVx - deltaCx;
|
|
283
|
+
const correctionY = rotatedVy - deltaCy;
|
|
284
|
+
// Adjust translateX/Y to compensate for the origin shift
|
|
285
|
+
// so the line stays visually in the same position
|
|
286
|
+
this.translateX += correctionX / this.scale;
|
|
287
|
+
this.translateY += correctionY / this.scale;
|
|
288
|
+
// Clear cached adjusted points
|
|
289
|
+
this._adjustedPoints = null;
|
|
290
|
+
this._clipInfo = null;
|
|
291
|
+
this._core.store.state.objects.update(this);
|
|
292
|
+
}
|
|
293
|
+
updateControlPoint(newX, newY) {
|
|
294
|
+
this.controlX = newX;
|
|
295
|
+
this.controlY = newY;
|
|
296
|
+
const oldWidth = this.width;
|
|
297
|
+
const oldHeight = this.height;
|
|
298
|
+
// Recalculate the bounding box (viewBox dimensions)
|
|
299
|
+
const { minX, minY, maxX, maxY } = this.calculateBoundingBox();
|
|
300
|
+
// Calculate the change in origin (in local coordinates)
|
|
301
|
+
const deltaX = minX - this.x;
|
|
302
|
+
const deltaY = minY - this.y;
|
|
303
|
+
const newWidth = maxX - minX;
|
|
304
|
+
const newHeight = maxY - minY;
|
|
305
|
+
const deltaWidth = newWidth - oldWidth;
|
|
306
|
+
const deltaHeight = newHeight - oldHeight;
|
|
307
|
+
const deltaCx = deltaWidth / 2;
|
|
308
|
+
const deltaCy = deltaHeight / 2;
|
|
309
|
+
// Update viewBox dimensions
|
|
310
|
+
this.x = minX;
|
|
311
|
+
this.y = minY;
|
|
312
|
+
this.width = newWidth;
|
|
313
|
+
this.height = newHeight;
|
|
314
|
+
// Rotate the delta to world coordinates before applying to translate
|
|
315
|
+
const cos = Math.cos(this.rotation);
|
|
316
|
+
const sin = Math.sin(this.rotation);
|
|
317
|
+
// We need to compensate for:
|
|
318
|
+
// 1. The shift of the top-left corner (deltaX, deltaY)
|
|
319
|
+
// 2. The shift of the center point (deltaCx, deltaCy) which affects rotation pivot
|
|
320
|
+
// Formula: DeltaT = R(DeltaPos + DeltaCenter) - DeltaCenter
|
|
321
|
+
const vx = deltaX + deltaCx;
|
|
322
|
+
const vy = deltaY + deltaCy;
|
|
323
|
+
const rotatedVx = vx * cos - vy * sin;
|
|
324
|
+
const rotatedVy = vx * sin + vy * cos;
|
|
325
|
+
const correctionX = rotatedVx - deltaCx;
|
|
326
|
+
const correctionY = rotatedVy - deltaCy;
|
|
327
|
+
// Adjust translateX/Y to compensate for the origin shift
|
|
328
|
+
// so the line stays visually in the same position
|
|
329
|
+
this.translateX += correctionX / this.scale;
|
|
330
|
+
this.translateY += correctionY / this.scale;
|
|
331
|
+
// Clear cached adjusted points
|
|
332
|
+
this._adjustedPoints = null;
|
|
333
|
+
this._clipInfo = null;
|
|
334
|
+
this._core.store.state.objects.update(this);
|
|
335
|
+
}
|
|
336
|
+
computeAdjustedPoints() {
|
|
337
|
+
const points = [
|
|
338
|
+
[this.startX, this.startY],
|
|
339
|
+
[this.endX, this.endY],
|
|
340
|
+
];
|
|
341
|
+
const angle = this.rotation;
|
|
342
|
+
const cos = Math.cos(angle);
|
|
343
|
+
const sin = Math.sin(angle);
|
|
344
|
+
const xs = points.map(p => p[0]);
|
|
345
|
+
const ys = points.map(p => p[1]);
|
|
346
|
+
const pivot = {
|
|
347
|
+
x: (Math.min(...xs) + Math.max(...xs)) / 2,
|
|
348
|
+
y: (Math.min(...ys) + Math.max(...ys)) / 2,
|
|
349
|
+
};
|
|
350
|
+
const { x: cx, y: cy } = pivot;
|
|
351
|
+
const rotatedPoints = points.map(([x, y]) => {
|
|
352
|
+
const dx = x - cx;
|
|
353
|
+
const dy = y - cy;
|
|
354
|
+
return [cx + dx * cos - dy * sin, cy + dx * sin + dy * cos];
|
|
355
|
+
});
|
|
356
|
+
return rotatedPoints.map(([px, py]) => [(px - this.x) / this.scale + this.translateX, (py - this.y) / this.scale + this.translateY]);
|
|
357
|
+
}
|
|
358
|
+
pointToLineSegmentDistance(x, y, x1, y1, x2, y2) {
|
|
359
|
+
const A = x - x1;
|
|
360
|
+
const B = y - y1;
|
|
361
|
+
const C = x2 - x1;
|
|
362
|
+
const D = y2 - y1;
|
|
363
|
+
const dot = A * C + B * D;
|
|
364
|
+
const len_sq = C * C + D * D;
|
|
365
|
+
let param = -1;
|
|
366
|
+
if (len_sq !== 0) {
|
|
367
|
+
param = dot / len_sq;
|
|
368
|
+
}
|
|
369
|
+
let xx, yy;
|
|
370
|
+
if (param < 0) {
|
|
371
|
+
xx = x1;
|
|
372
|
+
yy = y1;
|
|
373
|
+
}
|
|
374
|
+
else if (param > 1) {
|
|
375
|
+
xx = x2;
|
|
376
|
+
yy = y2;
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
xx = x1 + param * C;
|
|
380
|
+
yy = y1 + param * D;
|
|
381
|
+
}
|
|
382
|
+
const dx = x - xx;
|
|
383
|
+
const dy = y - yy;
|
|
384
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Calculates the minimum distance from a point to a quadratic Bezier curve.
|
|
388
|
+
* Uses sampling along the curve to find the closest point.
|
|
389
|
+
*/
|
|
390
|
+
pointToBezierDistance(x, y, startT = 0, endT = 1) {
|
|
391
|
+
if (this._adjustedPoints === null) {
|
|
392
|
+
this._adjustedPoints = this.computeAdjustedPoints();
|
|
393
|
+
}
|
|
394
|
+
const p0 = this._adjustedPoints[0];
|
|
395
|
+
const p2 = this._adjustedPoints[1];
|
|
396
|
+
// Calculate the adjusted control point
|
|
397
|
+
const controlAdjusted = this.computeAdjustedControlPoint();
|
|
398
|
+
let minDistance = Infinity;
|
|
399
|
+
const samples = 20; // Number of samples along the curve
|
|
400
|
+
for (let i = 0; i <= samples; i++) {
|
|
401
|
+
const fraction = i / samples;
|
|
402
|
+
const t = startT + fraction * (endT - startT);
|
|
403
|
+
const oneMinusT = 1 - t;
|
|
404
|
+
// Quadratic Bezier: B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
|
|
405
|
+
const bx = oneMinusT * oneMinusT * p0[0] + 2 * oneMinusT * t * controlAdjusted[0] + t * t * p2[0];
|
|
406
|
+
const by = oneMinusT * oneMinusT * p0[1] + 2 * oneMinusT * t * controlAdjusted[1] + t * t * p2[1];
|
|
407
|
+
const dx = x - bx;
|
|
408
|
+
const dy = y - by;
|
|
409
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
410
|
+
if (distance < minDistance) {
|
|
411
|
+
minDistance = distance;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return minDistance;
|
|
415
|
+
}
|
|
416
|
+
getClipInfo() {
|
|
417
|
+
if (this._clipInfo)
|
|
418
|
+
return this._clipInfo;
|
|
419
|
+
const startAnchor = this.startAnchor;
|
|
420
|
+
const endAnchor = this.endAnchor;
|
|
421
|
+
const result = {};
|
|
422
|
+
if (startAnchor) {
|
|
423
|
+
const target = this._core.anchorManager.findAnchorTarget(this, 'start');
|
|
424
|
+
if (target) {
|
|
425
|
+
const clip = this._core.anchorManager.computeAnchorClipInfo(this, 'start', target);
|
|
426
|
+
if (clip) {
|
|
427
|
+
result.start = { x: clip.worldX, y: clip.worldY, t: clip.t };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (endAnchor) {
|
|
432
|
+
const target = this._core.anchorManager.findAnchorTarget(this, 'end');
|
|
433
|
+
if (target) {
|
|
434
|
+
const clip = this._core.anchorManager.computeAnchorClipInfo(this, 'end', target);
|
|
435
|
+
if (clip) {
|
|
436
|
+
result.end = { x: clip.worldX, y: clip.worldY, t: clip.t };
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
this._clipInfo = result;
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Computes the adjusted control point in world coordinates, accounting for rotation and translation.
|
|
445
|
+
*/
|
|
446
|
+
computeAdjustedControlPoint() {
|
|
447
|
+
if (this.controlX === undefined || this.controlY === undefined) {
|
|
448
|
+
// Return midpoint if no control point
|
|
449
|
+
return [(this.startX + this.endX) / 2, (this.startY + this.endY) / 2];
|
|
450
|
+
}
|
|
451
|
+
const angle = this.rotation;
|
|
452
|
+
const cos = Math.cos(angle);
|
|
453
|
+
const sin = Math.sin(angle);
|
|
454
|
+
// Calculate pivot (center of bounding box for endpoints)
|
|
455
|
+
const xs = [this.startX, this.endX];
|
|
456
|
+
const ys = [this.startY, this.endY];
|
|
457
|
+
const pivot = {
|
|
458
|
+
x: (Math.min(...xs) + Math.max(...xs)) / 2,
|
|
459
|
+
y: (Math.min(...ys) + Math.max(...ys)) / 2,
|
|
460
|
+
};
|
|
461
|
+
const { x: cx, y: cy } = pivot;
|
|
462
|
+
// Rotate control point around pivot
|
|
463
|
+
const dx = this.controlX - cx;
|
|
464
|
+
const dy = this.controlY - cy;
|
|
465
|
+
const rotatedX = cx + dx * cos - dy * sin;
|
|
466
|
+
const rotatedY = cy + dx * sin + dy * cos;
|
|
467
|
+
// Transform to world coordinates
|
|
468
|
+
return [(rotatedX - this.x) / this.scale + this.translateX, (rotatedY - this.y) / this.scale + this.translateY];
|
|
469
|
+
}
|
|
470
|
+
get rotatedPolygon() {
|
|
471
|
+
const padding = this.padding;
|
|
472
|
+
// Use the bounding box which accounts for curve extrema
|
|
473
|
+
const { minX, minY, maxX, maxY } = KritzelLine.calculateBoundingBox(this.startX, this.startY, this.endX, this.endY, this.controlX, this.controlY, this.strokeWidth);
|
|
474
|
+
// Convert to local coordinates (relative to this.x, this.y)
|
|
475
|
+
const localMinX = minX - this.x + padding;
|
|
476
|
+
const localMinY = minY - this.y + padding;
|
|
477
|
+
const localMaxX = maxX - this.x + padding;
|
|
478
|
+
const localMaxY = maxY - this.y + padding;
|
|
479
|
+
const c1 = { x: localMinX, y: localMinY }; // top-left
|
|
480
|
+
const c2 = { x: localMaxX, y: localMinY }; // top-right
|
|
481
|
+
const c3 = { x: localMaxX, y: localMaxY }; // bottom-right
|
|
482
|
+
const c4 = { x: localMinX, y: localMaxY }; // bottom-left
|
|
483
|
+
const cx = this.totalWidth / 2;
|
|
484
|
+
const cy = this.totalHeight / 2;
|
|
485
|
+
const angle = this.rotation;
|
|
486
|
+
const cos = Math.cos(angle);
|
|
487
|
+
const sin = Math.sin(angle);
|
|
488
|
+
const transform = (p) => {
|
|
489
|
+
const rx = (p.x - cx) * cos - (p.y - cy) * sin + cx;
|
|
490
|
+
const ry = (p.x - cx) * sin + (p.y - cy) * cos + cy;
|
|
491
|
+
return {
|
|
492
|
+
x: rx / this.scale + this.translateX,
|
|
493
|
+
y: ry / this.scale + this.translateY,
|
|
494
|
+
};
|
|
495
|
+
};
|
|
496
|
+
return {
|
|
497
|
+
topLeft: transform(c1),
|
|
498
|
+
topRight: transform(c2),
|
|
499
|
+
bottomRight: transform(c3),
|
|
500
|
+
bottomLeft: transform(c4),
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* Calculates the tight bounding box for a quadratic Bezier curve or straight line.
|
|
505
|
+
* For curves, it finds the extrema points where the derivative equals zero.
|
|
506
|
+
*/
|
|
507
|
+
static calculateBoundingBox(startX, startY, endX, endY, controlX, controlY, strokeWidth) {
|
|
508
|
+
let minX = Math.min(startX, endX);
|
|
509
|
+
let minY = Math.min(startY, endY);
|
|
510
|
+
let maxX = Math.max(startX, endX);
|
|
511
|
+
let maxY = Math.max(startY, endY);
|
|
512
|
+
if (controlX !== undefined && controlY !== undefined) {
|
|
513
|
+
// For a quadratic Bezier: B(t) = (1-t)²P₀ + 2(1-t)tP₁ + t²P₂
|
|
514
|
+
// Derivative: B'(t) = 2(1-t)(P₁-P₀) + 2t(P₂-P₁) = 0
|
|
515
|
+
// Solving for t: t = (P₀ - P₁) / (P₀ - 2P₁ + P₂)
|
|
516
|
+
// Find extrema for X
|
|
517
|
+
const aX = startX - 2 * controlX + endX;
|
|
518
|
+
if (aX !== 0) {
|
|
519
|
+
const tX = (startX - controlX) / aX;
|
|
520
|
+
if (tX > 0 && tX < 1) {
|
|
521
|
+
const extremaX = (1 - tX) * (1 - tX) * startX + 2 * (1 - tX) * tX * controlX + tX * tX * endX;
|
|
522
|
+
minX = Math.min(minX, extremaX);
|
|
523
|
+
maxX = Math.max(maxX, extremaX);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// Find extrema for Y
|
|
527
|
+
const aY = startY - 2 * controlY + endY;
|
|
528
|
+
if (aY !== 0) {
|
|
529
|
+
const tY = (startY - controlY) / aY;
|
|
530
|
+
if (tY > 0 && tY < 1) {
|
|
531
|
+
const extremaY = (1 - tY) * (1 - tY) * startY + 2 * (1 - tY) * tY * controlY + tY * tY * endY;
|
|
532
|
+
minY = Math.min(minY, extremaY);
|
|
533
|
+
maxY = Math.max(maxY, extremaY);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
const halfStroke = strokeWidth / 2;
|
|
538
|
+
return {
|
|
539
|
+
minX: minX - halfStroke,
|
|
540
|
+
minY: minY - halfStroke,
|
|
541
|
+
maxX: maxX + halfStroke,
|
|
542
|
+
maxY: maxY + halfStroke,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
calculateBoundingBox() {
|
|
546
|
+
return KritzelLine.calculateBoundingBox(this.startX, this.startY, this.endX, this.endY, this.controlX, this.controlY, this.strokeWidth);
|
|
547
|
+
}
|
|
548
|
+
updateDimensions() {
|
|
549
|
+
const { minX, minY, maxX, maxY } = this.calculateBoundingBox();
|
|
550
|
+
this.width = maxX - minX;
|
|
551
|
+
this.height = maxY - minY;
|
|
552
|
+
this.x = minX;
|
|
553
|
+
this.y = minY;
|
|
554
|
+
this.translateX = (this.x + this.translateX) / this.scale;
|
|
555
|
+
this.translateY = (this.y + this.translateY) / this.scale;
|
|
556
|
+
}
|
|
557
|
+
/** Get unique marker ID for SVG defs at the start of the line */
|
|
558
|
+
get startMarkerId() {
|
|
559
|
+
return `arrow-start-${this.id}`;
|
|
560
|
+
}
|
|
561
|
+
/** Get unique marker ID for SVG defs at the end of the line */
|
|
562
|
+
get endMarkerId() {
|
|
563
|
+
return `arrow-end-${this.id}`;
|
|
564
|
+
}
|
|
565
|
+
/** Get the arrow size for start or end, defaulting to strokeWidth * 3 */
|
|
566
|
+
getArrowSize(end) {
|
|
567
|
+
var _a, _b, _c;
|
|
568
|
+
const config = end === 'start' ? (_a = this.arrows) === null || _a === void 0 ? void 0 : _a.start : (_b = this.arrows) === null || _b === void 0 ? void 0 : _b.end;
|
|
569
|
+
return (_c = config === null || config === void 0 ? void 0 : config.size) !== null && _c !== void 0 ? _c : this.strokeWidth * 3;
|
|
570
|
+
}
|
|
571
|
+
/** Get the arrow fill color for start or end, defaulting to stroke color */
|
|
572
|
+
getArrowFill(end) {
|
|
573
|
+
var _a, _b, _c;
|
|
574
|
+
const config = end === 'start' ? (_a = this.arrows) === null || _a === void 0 ? void 0 : _a.start : (_b = this.arrows) === null || _b === void 0 ? void 0 : _b.end;
|
|
575
|
+
const color = (_c = config === null || config === void 0 ? void 0 : config.fill) !== null && _c !== void 0 ? _c : this.stroke;
|
|
576
|
+
return KritzelColorHelper.resolveThemeColor(color);
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Generate SVG path data for an arrow head based on the given style.
|
|
580
|
+
* The path is designed to fit in a 10x10 viewBox with the tip at (10, 5).
|
|
581
|
+
* @param style The arrow head style
|
|
582
|
+
* @returns SVG path data string
|
|
583
|
+
*/
|
|
584
|
+
getArrowPath(style = 'triangle') {
|
|
585
|
+
switch (style) {
|
|
586
|
+
case 'triangle':
|
|
587
|
+
return 'M 0 0 L 10 5 L 0 10 z';
|
|
588
|
+
case 'open':
|
|
589
|
+
return 'M 0 0 L 10 5 L 0 10';
|
|
590
|
+
case 'diamond':
|
|
591
|
+
return 'M 0 5 L 5 0 L 10 5 L 5 10 z';
|
|
592
|
+
case 'circle':
|
|
593
|
+
return 'M 5,0 A 5,5 0 1,1 5,10 A 5,5 0 1,1 5,0';
|
|
594
|
+
default:
|
|
595
|
+
return 'M 0 0 L 10 5 L 0 10 z';
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
/** Check if start arrow is enabled */
|
|
599
|
+
get hasStartArrow() {
|
|
600
|
+
var _a, _b;
|
|
601
|
+
return ((_b = (_a = this.arrows) === null || _a === void 0 ? void 0 : _a.start) === null || _b === void 0 ? void 0 : _b.enabled) === true;
|
|
602
|
+
}
|
|
603
|
+
/** Check if end arrow is enabled */
|
|
604
|
+
get hasEndArrow() {
|
|
605
|
+
var _a, _b;
|
|
606
|
+
return ((_b = (_a = this.arrows) === null || _a === void 0 ? void 0 : _a.end) === null || _b === void 0 ? void 0 : _b.enabled) === true;
|
|
607
|
+
}
|
|
608
|
+
}
|