@363045841yyt/klinechart-core 0.8.10-alpha.2 → 0.8.10

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.
Files changed (89) hide show
  1. package/dist/controllers/index.d.ts +1 -1
  2. package/dist/controllers/index.d.ts.map +1 -1
  3. package/dist/controllers/index.js.map +1 -1
  4. package/dist/data-fetchers/dataBuffer.d.ts +0 -1
  5. package/dist/data-fetchers/dataBuffer.d.ts.map +1 -1
  6. package/dist/data-fetchers/dataBuffer.effects.d.ts +21 -0
  7. package/dist/data-fetchers/dataBuffer.effects.d.ts.map +1 -0
  8. package/dist/data-fetchers/dataBuffer.effects.js +55 -0
  9. package/dist/data-fetchers/dataBuffer.effects.js.map +1 -0
  10. package/dist/data-fetchers/dataBuffer.js +58 -93
  11. package/dist/data-fetchers/dataBuffer.js.map +1 -1
  12. package/dist/data-fetchers/index.d.ts +1 -0
  13. package/dist/data-fetchers/index.d.ts.map +1 -1
  14. package/dist/data-fetchers/index.js +1 -0
  15. package/dist/data-fetchers/index.js.map +1 -1
  16. package/dist/data-fetchers/timeShareBuffer.d.ts +2 -1
  17. package/dist/data-fetchers/timeShareBuffer.d.ts.map +1 -1
  18. package/dist/data-fetchers/timeShareBuffer.js +36 -14
  19. package/dist/data-fetchers/timeShareBuffer.js.map +1 -1
  20. package/dist/engine/data/chartDataManager.d.ts.map +1 -1
  21. package/dist/engine/data/chartDataManager.js +2 -1
  22. package/dist/engine/data/chartDataManager.js.map +1 -1
  23. package/dist/engine/drawing/AnchorCollector.d.ts +26 -0
  24. package/dist/engine/drawing/AnchorCollector.d.ts.map +1 -0
  25. package/dist/engine/drawing/AnchorCollector.js +47 -0
  26. package/dist/engine/drawing/AnchorCollector.js.map +1 -0
  27. package/dist/engine/drawing/DragHandler.d.ts +38 -0
  28. package/dist/engine/drawing/DragHandler.d.ts.map +1 -0
  29. package/dist/engine/drawing/DragHandler.js +92 -0
  30. package/dist/engine/drawing/DragHandler.js.map +1 -0
  31. package/dist/engine/drawing/DrawingState.d.ts +51 -0
  32. package/dist/engine/drawing/DrawingState.d.ts.map +1 -0
  33. package/dist/engine/drawing/DrawingState.js +115 -0
  34. package/dist/engine/drawing/DrawingState.js.map +1 -0
  35. package/dist/engine/drawing/HitTester.d.ts +59 -0
  36. package/dist/engine/drawing/HitTester.d.ts.map +1 -0
  37. package/dist/engine/drawing/HitTester.js +219 -0
  38. package/dist/engine/drawing/HitTester.js.map +1 -0
  39. package/dist/engine/drawing/PreviewRenderer.d.ts +26 -0
  40. package/dist/engine/drawing/PreviewRenderer.d.ts.map +1 -0
  41. package/dist/engine/drawing/PreviewRenderer.js +131 -0
  42. package/dist/engine/drawing/PreviewRenderer.js.map +1 -0
  43. package/dist/engine/drawing/coordinateUtils.d.ts +57 -0
  44. package/dist/engine/drawing/coordinateUtils.d.ts.map +1 -0
  45. package/dist/engine/drawing/coordinateUtils.js +103 -0
  46. package/dist/engine/drawing/coordinateUtils.js.map +1 -0
  47. package/dist/engine/drawing/index.d.ts.map +1 -1
  48. package/dist/engine/drawing/index.js +11 -3
  49. package/dist/engine/drawing/index.js.map +1 -1
  50. package/dist/engine/drawing/interaction.d.ts +44 -40
  51. package/dist/engine/drawing/interaction.d.ts.map +1 -1
  52. package/dist/engine/drawing/interaction.js +132 -571
  53. package/dist/engine/drawing/interaction.js.map +1 -1
  54. package/dist/engine/drawing/toolConfig.d.ts +24 -0
  55. package/dist/engine/drawing/toolConfig.d.ts.map +1 -0
  56. package/dist/engine/drawing/toolConfig.js +76 -0
  57. package/dist/engine/drawing/toolConfig.js.map +1 -0
  58. package/dist/plugin/types.d.ts +1 -0
  59. package/dist/plugin/types.d.ts.map +1 -1
  60. package/dist/plugin/types.js.map +1 -1
  61. package/dist/version.d.ts +1 -1
  62. package/dist/version.d.ts.map +1 -1
  63. package/dist/version.js +1 -1
  64. package/dist/version.js.map +1 -1
  65. package/package.json +4 -1
  66. package/src/controllers/index.ts +1 -0
  67. package/src/data-fetchers/__tests__/dataBuffer.test.ts +1 -3
  68. package/src/data-fetchers/dataBuffer.effects.ts +118 -0
  69. package/src/data-fetchers/dataBuffer.ts +45 -86
  70. package/src/data-fetchers/index.ts +7 -0
  71. package/src/data-fetchers/timeShareBuffer.ts +58 -19
  72. package/src/engine/__tests__/paneRenderer.resize.test.ts +3 -0
  73. package/src/engine/__tests__/subPaneManager.test.ts +13 -3
  74. package/src/engine/data/chartDataManager.ts +2 -1
  75. package/src/engine/drawing/AnchorCollector.ts +57 -0
  76. package/src/engine/drawing/DragHandler.ts +121 -0
  77. package/src/engine/drawing/DrawingState.ts +132 -0
  78. package/src/engine/drawing/HitTester.ts +288 -0
  79. package/src/engine/drawing/PreviewRenderer.ts +157 -0
  80. package/src/engine/drawing/coordinateUtils.ts +139 -0
  81. package/src/engine/drawing/index.ts +10 -3
  82. package/src/engine/drawing/interaction.ts +177 -687
  83. package/src/engine/drawing/toolConfig.ts +103 -0
  84. package/src/engine/indicators/__tests__/chartIndicatorManager.test.ts +1 -0
  85. package/src/engine/indicators/__tests__/stateComposer.test.ts +5 -4
  86. package/src/engine/renderers/Indicator/__tests__/createSubIndicatorRenderer.test.ts +1 -0
  87. package/src/plugin/types.ts +1 -0
  88. package/src/tokens/__tests__/tokens.test.ts +2 -1
  89. package/src/version.ts +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HitTester.d.ts","sourceRoot":"","sources":["../../../src/engine/drawing/HitTester.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAOlE,yCAAyC;AACzC,MAAM,MAAM,SAAS,GACjB;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAC/C;IAAE,OAAO,EAAE,aAAa,CAAA;CAAE,CAAA;AAE9B,wBAAwB;AACxB,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,SAAS,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAA;KAAE,CAAC,CAAA;CAC1E;AAOD;;;GAGG;AACH,qBAAa,SAAS;IACpB;;;OAGG;IACH,OAAO,CACL,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,EAAE,mBAAmB,GAC3B,SAAS,GAAG,IAAI;IAoCnB;;OAEG;IACH,sBAAsB,CACpB,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,mBAAmB,EAC5B,uBAAuB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC,GACtE,WAAW,EAAE;IAgHhB;;OAEG;IACH,4BAA4B,CAC1B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,mBAAmB,EAC5B,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,yBAAyB,GAAG,IAAI,CAAC,GACpD,yBAAyB,GAAG,IAAI;IAuDnC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;CAmBnC"}
@@ -0,0 +1,219 @@
1
+ import { anchorToScreen, pointToSegmentDist } from './coordinateUtils';
2
+ import { getExtendMode } from './toolConfig';
3
+ import { computeLinearRegression } from './linearRegression';
4
+ /** 锚点点击命中半径(px) */
5
+ const ANCHOR_HIT_RADIUS = 8;
6
+ /** 线段点击命中半径(px) */
7
+ const LINE_HIT_RADIUS = 6;
8
+ /**
9
+ * Hit detection — test mouse position against drawing anchors and line segments.
10
+ * Pure computation, no side effects.
11
+ */
12
+ export class HitTester {
13
+ /**
14
+ * Find the drawing (and optionally which anchor) under the given mouse position.
15
+ * Anchors are checked first, then line segments.
16
+ */
17
+ hitTest(mouseX, mouseY, drawings, adapter) {
18
+ const visibleDrawings = drawings.filter((d) => d.visible);
19
+ const regressionGeometryCache = new Map();
20
+ // Check anchor hits first
21
+ for (const drawing of visibleDrawings) {
22
+ // regression-channel: computed endpoints are also draggable
23
+ if (drawing.kind === 'regression-channel' && drawing.anchors.length >= 2) {
24
+ const hit = this.hitTestRegressionEndpoints(drawing, mouseX, mouseY, adapter, regressionGeometryCache);
25
+ if (hit)
26
+ return hit;
27
+ }
28
+ for (let i = 0; i < drawing.anchors.length; i++) {
29
+ const screen = anchorToScreen(drawing.anchors[i], adapter);
30
+ if (!screen)
31
+ continue;
32
+ const dist = Math.hypot(mouseX - screen.x, mouseY - screen.y);
33
+ if (dist <= ANCHOR_HIT_RADIUS) {
34
+ return { drawing, anchorIndex: i };
35
+ }
36
+ }
37
+ }
38
+ // Check line segment hits
39
+ for (const drawing of visibleDrawings) {
40
+ const segments = this.getDrawingLineSegments(drawing, adapter, regressionGeometryCache);
41
+ for (const seg of segments) {
42
+ const dist = pointToSegmentDist(mouseX, mouseY, seg.a, seg.b);
43
+ if (dist <= LINE_HIT_RADIUS) {
44
+ return { drawing };
45
+ }
46
+ }
47
+ }
48
+ return null;
49
+ }
50
+ /**
51
+ * Get the screen-space line segments for a drawing, used for hit-testing.
52
+ */
53
+ getDrawingLineSegments(drawing, adapter, regressionGeometryCache) {
54
+ const viewport = adapter.getViewport();
55
+ if (!viewport)
56
+ return [];
57
+ // regression-channel: compute from linear regression geometry
58
+ if (drawing.kind === 'regression-channel') {
59
+ return this.getRegressionChannelGeometry(drawing, adapter, regressionGeometryCache)?.segments ?? [];
60
+ }
61
+ // Single-anchor drawings (horizontal-line, horizontal-ray, vertical-line, cross-line)
62
+ if (drawing.anchors.length === 1) {
63
+ const screen = anchorToScreen(drawing.anchors[0], adapter);
64
+ if (!screen)
65
+ return [];
66
+ const paneInfo = adapter.getPaneInfo('main');
67
+ if (!paneInfo)
68
+ return [];
69
+ const right = viewport.plotWidth;
70
+ const bottom = paneInfo.height;
71
+ switch (drawing.kind) {
72
+ case 'horizontal-line':
73
+ return [{ a: { x: 0, y: screen.y }, b: { x: right, y: screen.y } }];
74
+ case 'horizontal-ray':
75
+ return [{ a: screen, b: { x: right, y: screen.y } }];
76
+ case 'vertical-line':
77
+ return [{ a: { x: screen.x, y: 0 }, b: { x: screen.x, y: bottom } }];
78
+ case 'cross-line':
79
+ return [
80
+ { a: { x: 0, y: screen.y }, b: { x: right, y: screen.y } },
81
+ { a: { x: screen.x, y: 0 }, b: { x: screen.x, y: bottom } },
82
+ ];
83
+ default:
84
+ return [];
85
+ }
86
+ }
87
+ // Multi-anchor drawings (2+)
88
+ const points = drawing.anchors
89
+ .map((a) => anchorToScreen(a, adapter))
90
+ .filter(Boolean);
91
+ if (points.length < 2)
92
+ return [];
93
+ const segments = [];
94
+ if (points.length === 2) {
95
+ const a = points[0];
96
+ const b = points[1];
97
+ const dx = b.x - a.x;
98
+ const dy = b.y - a.y;
99
+ let start = a;
100
+ let end = b;
101
+ const extend = getExtendMode(drawing.kind);
102
+ const maxLen = Math.max(viewport.plotWidth, viewport.plotHeight) * 4;
103
+ if (extend === 'right' || extend === 'both') {
104
+ end = { x: b.x + dx * maxLen, y: b.y + dy * maxLen };
105
+ }
106
+ if (extend === 'left' || extend === 'both') {
107
+ start = { x: a.x - dx * maxLen, y: a.y - dy * maxLen };
108
+ }
109
+ segments.push({ a: start, b: end });
110
+ }
111
+ else if (points.length >= 3) {
112
+ switch (drawing.kind) {
113
+ case 'parallel-channel': {
114
+ const [p1, p2, p3] = points;
115
+ const dx = p2.x - p1.x;
116
+ const dy = p2.y - p1.y;
117
+ const p4 = { x: p3.x + dx, y: p3.y + dy };
118
+ segments.push({ a: p1, b: p2 }, { a: p3, b: p4 });
119
+ break;
120
+ }
121
+ case 'flat-line': {
122
+ const [p1, p2, p3] = points;
123
+ const h1 = { x: p1.x, y: p3.y };
124
+ const h2 = { x: p2.x, y: p3.y };
125
+ segments.push({ a: p1, b: p2 }, { a: h1, b: h2 });
126
+ break;
127
+ }
128
+ case 'disjoint-channel': {
129
+ const [p1, p2, p3] = points;
130
+ const dx = p2.x - p1.x;
131
+ const dy = p2.y - p1.y;
132
+ const p4 = { x: p3.x + dx, y: p3.y - dy };
133
+ segments.push({ a: p1, b: p2 }, { a: p3, b: p4 });
134
+ break;
135
+ }
136
+ default:
137
+ for (let i = 0; i < points.length - 1; i++) {
138
+ segments.push({ a: points[i], b: points[i + 1] });
139
+ }
140
+ }
141
+ }
142
+ return segments;
143
+ }
144
+ /**
145
+ * Compute the screen-space geometry of a regression channel.
146
+ */
147
+ getRegressionChannelGeometry(drawing, adapter, cache) {
148
+ const cached = cache?.get(drawing.id);
149
+ if (cached !== undefined)
150
+ return cached;
151
+ const data = adapter.getData();
152
+ if (data.length === 0 || drawing.anchors.length < 2) {
153
+ cache?.set(drawing.id, null);
154
+ return null;
155
+ }
156
+ const firstIndex = Math.round(drawing.anchors[0].index);
157
+ const secondIndex = Math.round(drawing.anchors[1].index);
158
+ const clampedFirst = Math.min(Math.max(firstIndex, 0), data.length - 1);
159
+ const clampedSecond = Math.min(Math.max(secondIndex, 0), data.length - 1);
160
+ const startIndex = Math.min(clampedFirst, clampedSecond);
161
+ const endIndex = Math.max(clampedFirst, clampedSecond);
162
+ const slice = data.slice(startIndex, endIndex + 1);
163
+ const regression = computeLinearRegression(slice.map((item) => item.close));
164
+ if (!regression) {
165
+ cache?.set(drawing.id, null);
166
+ return null;
167
+ }
168
+ const sigma = (drawing.params?.sigma) ?? 2;
169
+ const offset = regression.stdDev * sigma;
170
+ const firstValue = regression.intercept;
171
+ const lastValue = regression.intercept + regression.slope * (slice.length - 1);
172
+ const middleStart = anchorToScreen({ id: '', index: firstIndex, price: firstValue }, adapter);
173
+ const middleEnd = anchorToScreen({ id: '', index: secondIndex, price: lastValue }, adapter);
174
+ const upperStart = anchorToScreen({ id: '', index: firstIndex, price: firstValue + offset }, adapter);
175
+ const upperEnd = anchorToScreen({ id: '', index: secondIndex, price: lastValue + offset }, adapter);
176
+ const lowerStart = anchorToScreen({ id: '', index: firstIndex, price: firstValue - offset }, adapter);
177
+ const lowerEnd = anchorToScreen({ id: '', index: secondIndex, price: lastValue - offset }, adapter);
178
+ const segments = [];
179
+ if (middleStart && middleEnd)
180
+ segments.push({ a: middleStart, b: middleEnd });
181
+ if (upperStart && upperEnd)
182
+ segments.push({ a: upperStart, b: upperEnd });
183
+ if (lowerStart && lowerEnd)
184
+ segments.push({ a: lowerStart, b: lowerEnd });
185
+ const endpoints = [];
186
+ if (middleStart)
187
+ endpoints.push({ point: middleStart, anchorIndex: 0 });
188
+ if (middleEnd)
189
+ endpoints.push({ point: middleEnd, anchorIndex: 1 });
190
+ if (upperStart)
191
+ endpoints.push({ point: upperStart, anchorIndex: 0 });
192
+ if (upperEnd)
193
+ endpoints.push({ point: upperEnd, anchorIndex: 1 });
194
+ if (lowerStart)
195
+ endpoints.push({ point: lowerStart, anchorIndex: 0 });
196
+ if (lowerEnd)
197
+ endpoints.push({ point: lowerEnd, anchorIndex: 1 });
198
+ const geometry = { segments, endpoints };
199
+ cache?.set(drawing.id, geometry);
200
+ return geometry;
201
+ }
202
+ /**
203
+ * regression-channel only: check hit against computed regression endpoints
204
+ * (which may be far from stored anchor positions).
205
+ */
206
+ hitTestRegressionEndpoints(drawing, mouseX, mouseY, adapter, cache) {
207
+ const geometry = this.getRegressionChannelGeometry(drawing, adapter, cache);
208
+ if (!geometry)
209
+ return null;
210
+ for (const endpoint of geometry.endpoints) {
211
+ const dist = Math.hypot(mouseX - endpoint.point.x, mouseY - endpoint.point.y);
212
+ if (dist <= ANCHOR_HIT_RADIUS) {
213
+ return { drawing, anchorIndex: endpoint.anchorIndex };
214
+ }
215
+ }
216
+ return null;
217
+ }
218
+ }
219
+ //# sourceMappingURL=HitTester.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HitTester.js","sourceRoot":"","sources":["../../../src/engine/drawing/HitTester.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { DrawingObject } from '../../plugin';
2
+ import type { DrawingToolId } from './toolConfig';
3
+ import type { DrawingAnchorInput } from './coordinateUtils';
4
+ /**
5
+ * Constructs preview DrawingObject instances for various tool types.
6
+ * Pure construction — no side effects, no adapter calls.
7
+ */
8
+ export declare class PreviewRenderer {
9
+ /**
10
+ * Build a preview drawing from the current tool state and pointer anchor.
11
+ * @returns a preview DrawingObject, or null if the state is insufficient for a preview.
12
+ */
13
+ buildPreview(activeTool: DrawingToolId, pendingAnchors: DrawingAnchorInput[], currentAnchor: DrawingAnchorInput): DrawingObject | null;
14
+ /** 单锚点工具预览:虚线样式 */
15
+ private buildSingleAnchorPreview;
16
+ /** 双锚点工具预览:两个锚点之间的虚线,回归通道附带填充区域 */
17
+ private buildDoubleAnchorPreview;
18
+ /**
19
+ * 三锚点工具预览:
20
+ * - pending 数 = 0 → 无法预览,返回 null
21
+ * - pending 数 = 1 → 暂以趋势线(双锚点)形式显示前两个点
22
+ * - pending 数 ≥ 2 → 完整三锚点预览(含 flat-line 的特殊 price 处理)
23
+ */
24
+ private buildTripleAnchorPreview;
25
+ }
26
+ //# sourceMappingURL=PreviewRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewRenderer.d.ts","sourceRoot":"","sources":["../../../src/engine/drawing/PreviewRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAEjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAE3D;;;GAGG;AACH,qBAAa,eAAe;IAC1B;;;OAGG;IACH,YAAY,CACV,UAAU,EAAE,aAAa,EACzB,cAAc,EAAE,kBAAkB,EAAE,EACpC,aAAa,EAAE,kBAAkB,GAChC,aAAa,GAAG,IAAI;IAoBvB,mBAAmB;IACnB,OAAO,CAAC,wBAAwB;IAqBhC,mCAAmC;IACnC,OAAO,CAAC,wBAAwB;IAwBhC;;;;;OAKG;IACH,OAAO,CAAC,wBAAwB;CAgEjC"}
@@ -0,0 +1,131 @@
1
+ import { PREVIEW_ID } from './DrawingState';
2
+ import { SINGLE_ANCHOR_TOOLS, DOUBLE_ANCHOR_TOOLS, TRIPLE_ANCHOR_TOOLS, getDrawingKind, CHANNEL_KINDS } from './toolConfig';
3
+ /**
4
+ * Constructs preview DrawingObject instances for various tool types.
5
+ * Pure construction — no side effects, no adapter calls.
6
+ */
7
+ export class PreviewRenderer {
8
+ /**
9
+ * Build a preview drawing from the current tool state and pointer anchor.
10
+ * @returns a preview DrawingObject, or null if the state is insufficient for a preview.
11
+ */
12
+ buildPreview(activeTool, pendingAnchors, currentAnchor) {
13
+ const isSingle = SINGLE_ANCHOR_TOOLS.includes(activeTool);
14
+ const isDouble = DOUBLE_ANCHOR_TOOLS.includes(activeTool);
15
+ const isTriple = TRIPLE_ANCHOR_TOOLS.includes(activeTool);
16
+ if (!isSingle && !isDouble && !isTriple)
17
+ return null;
18
+ if (isSingle) {
19
+ return this.buildSingleAnchorPreview(activeTool, currentAnchor);
20
+ }
21
+ if (isDouble) {
22
+ if (pendingAnchors.length < 1)
23
+ return null;
24
+ return this.buildDoubleAnchorPreview(activeTool, pendingAnchors[0], currentAnchor);
25
+ }
26
+ // Triple anchor tools
27
+ return this.buildTripleAnchorPreview(activeTool, pendingAnchors, currentAnchor);
28
+ }
29
+ /** 单锚点工具预览:虚线样式 */
30
+ buildSingleAnchorPreview(activeTool, anchor) {
31
+ return {
32
+ id: PREVIEW_ID,
33
+ kind: getDrawingKind(activeTool),
34
+ paneId: 'main',
35
+ visible: true,
36
+ anchors: [
37
+ { id: `${PREVIEW_ID}-a`, index: anchor.index, time: anchor.time, price: anchor.price },
38
+ ],
39
+ params: {},
40
+ style: {
41
+ stroke: '#2962ff',
42
+ strokeWidth: 1,
43
+ strokeStyle: 'dashed',
44
+ },
45
+ };
46
+ }
47
+ /** 双锚点工具预览:两个锚点之间的虚线,回归通道附带填充区域 */
48
+ buildDoubleAnchorPreview(activeTool, first, second) {
49
+ return {
50
+ id: PREVIEW_ID,
51
+ kind: getDrawingKind(activeTool),
52
+ paneId: 'main',
53
+ visible: true,
54
+ anchors: [
55
+ { id: `${PREVIEW_ID}-a`, index: first.index, time: first.time, price: first.price },
56
+ { id: `${PREVIEW_ID}-b`, index: second.index, time: second.time, price: second.price },
57
+ ],
58
+ params: activeTool === 'regression-channel' ? { sigma: 2 } : {},
59
+ style: {
60
+ stroke: '#2962ff',
61
+ strokeWidth: 1,
62
+ strokeStyle: 'dashed',
63
+ ...(activeTool === 'regression-channel' ? { fillOpacity: 0.1 } : {}),
64
+ },
65
+ };
66
+ }
67
+ /**
68
+ * 三锚点工具预览:
69
+ * - pending 数 = 0 → 无法预览,返回 null
70
+ * - pending 数 = 1 → 暂以趋势线(双锚点)形式显示前两个点
71
+ * - pending 数 ≥ 2 → 完整三锚点预览(含 flat-line 的特殊 price 处理)
72
+ */
73
+ buildTripleAnchorPreview(activeTool, pendingAnchors, currentAnchor) {
74
+ if (pendingAnchors.length === 0)
75
+ return null;
76
+ if (pendingAnchors.length === 1) {
77
+ // Need 3 anchors but only have 1 pending — render as a trend-line segment (2 anchors)
78
+ // so the user can see what they're drawing before placing the 3rd point
79
+ return {
80
+ id: PREVIEW_ID,
81
+ kind: 'trend-line',
82
+ paneId: 'main',
83
+ visible: true,
84
+ anchors: [
85
+ { id: `${PREVIEW_ID}-a`, index: pendingAnchors[0].index, time: pendingAnchors[0].time, price: pendingAnchors[0].price },
86
+ { id: `${PREVIEW_ID}-b`, index: currentAnchor.index, time: currentAnchor.time, price: currentAnchor.price },
87
+ ],
88
+ params: {},
89
+ style: {
90
+ stroke: '#2962ff',
91
+ strokeWidth: 1,
92
+ strokeStyle: 'dashed',
93
+ },
94
+ };
95
+ }
96
+ // pendingAnchors.length >= 2 — full 3-anchor preview
97
+ const thirdAnchor = activeTool === 'flat-line'
98
+ ? {
99
+ id: `${PREVIEW_ID}-c`,
100
+ index: pendingAnchors[1].index,
101
+ time: pendingAnchors[1].time,
102
+ price: currentAnchor.price,
103
+ }
104
+ : {
105
+ id: `${PREVIEW_ID}-c`,
106
+ index: currentAnchor.index,
107
+ time: currentAnchor.time,
108
+ price: currentAnchor.price,
109
+ };
110
+ const isChannel = CHANNEL_KINDS.includes(getDrawingKind(activeTool));
111
+ return {
112
+ id: PREVIEW_ID,
113
+ kind: getDrawingKind(activeTool),
114
+ paneId: 'main',
115
+ visible: true,
116
+ anchors: [
117
+ { id: `${PREVIEW_ID}-a`, index: pendingAnchors[0].index, time: pendingAnchors[0].time, price: pendingAnchors[0].price },
118
+ { id: `${PREVIEW_ID}-b`, index: pendingAnchors[1].index, time: pendingAnchors[1].time, price: pendingAnchors[1].price },
119
+ thirdAnchor,
120
+ ],
121
+ params: {},
122
+ style: {
123
+ stroke: '#2962ff',
124
+ strokeWidth: 1,
125
+ strokeStyle: 'dashed',
126
+ ...(isChannel ? { fillOpacity: 0.1 } : {}),
127
+ },
128
+ };
129
+ }
130
+ }
131
+ //# sourceMappingURL=PreviewRenderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewRenderer.js","sourceRoot":"","sources":["../../../src/engine/drawing/PreviewRenderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { DrawingAnchor } from '../../plugin';
2
+ import type { DrawingChartAdapter } from '../../controllers/types';
3
+ /** 原始锚点输入(逻辑坐标:K线索引 + 价格) */
4
+ export interface DrawingAnchorInput {
5
+ /** K线柱逻辑索引(可以是小数,表示在两柱之间) */
6
+ index: number;
7
+ /** 对应的时间戳(ms) */
8
+ time?: number;
9
+ /** 价格 */
10
+ price: number;
11
+ }
12
+ /**
13
+ * 将图元锚点的逻辑坐标(index + price)转换为屏幕坐标(px)。
14
+ *
15
+ * 计算过程:
16
+ * 1. 通过 getPhysicalKLineConfig 获取 K 线柱的起始像素位置和单柱像素宽度
17
+ * 2. anchor.index × unitPx 得到距起始位置的偏移
18
+ * 3. 减去 viewport.scrollLeft 得到相对视口的 X
19
+ * 4. 通过 adapter.priceToY 将价格转为 Y
20
+ *
21
+ * @returns {x, y} 屏幕坐标(px),viewport 不可用时返回 null
22
+ */
23
+ export declare function anchorToScreen(anchor: DrawingAnchor, adapter: DrawingChartAdapter): {
24
+ x: number;
25
+ y: number;
26
+ } | null;
27
+ /**
28
+ * 将屏幕坐标(px)反向解析为逻辑锚点坐标(index + price)。
29
+ *
30
+ * 用于拖拽整线时的屏幕偏移量回算。
31
+ *
32
+ * @returns DrawingAnchorInput,viewport 不可用或索引不在数据范围内时返回 null
33
+ */
34
+ export declare function screenToAnchor(screenX: number, screenY: number, adapter: DrawingChartAdapter): DrawingAnchorInput | null;
35
+ /**
36
+ * 从 PointerEvent 中解析出光标位置对应的逻辑锚点。
37
+ *
38
+ * 边界检测:
39
+ * - 鼠标超出 viewport.plotWidth / plotHeight → null
40
+ * - 鼠标不在 main pane 范围内 → null
41
+ * - 鼠标位置无对应 K 线索引 → null
42
+ *
43
+ * @returns DrawingAnchorInput,超出范围或数据不可用时返回 null
44
+ */
45
+ export declare function resolveAnchorFromPointer(e: PointerEvent, container: HTMLElement, adapter: DrawingChartAdapter): DrawingAnchorInput | null;
46
+ /**
47
+ * 计算点 P 到线段 AB 的最短距离。
48
+ * 投影点在 AB 线段外时取最近端点距离。
49
+ */
50
+ export declare function pointToSegmentDist(px: number, py: number, a: {
51
+ x: number;
52
+ y: number;
53
+ }, b: {
54
+ x: number;
55
+ y: number;
56
+ }): number;
57
+ //# sourceMappingURL=coordinateUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateUtils.d.ts","sourceRoot":"","sources":["../../../src/engine/drawing/coordinateUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAKlE,6BAA6B;AAC7B,MAAM,WAAW,kBAAkB;IACjC,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS;IACT,KAAK,EAAE,MAAM,CAAA;CACd;AAID;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,mBAAmB,GAC3B;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAYjC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,GAAG,IAAI,CAkB3B;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,CAAC,EAAE,YAAY,EACf,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,mBAAmB,GAC3B,kBAAkB,GAAG,IAAI,CAyB3B;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B,CAAC,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1B,MAAM,CASR"}
@@ -0,0 +1,103 @@
1
+ import { getPhysicalKLineConfig } from '../utils/klineConfig';
2
+ // ---- Coordinate conversion ----
3
+ /**
4
+ * 将图元锚点的逻辑坐标(index + price)转换为屏幕坐标(px)。
5
+ *
6
+ * 计算过程:
7
+ * 1. 通过 getPhysicalKLineConfig 获取 K 线柱的起始像素位置和单柱像素宽度
8
+ * 2. anchor.index × unitPx 得到距起始位置的偏移
9
+ * 3. 减去 viewport.scrollLeft 得到相对视口的 X
10
+ * 4. 通过 adapter.priceToY 将价格转为 Y
11
+ *
12
+ * @returns {x, y} 屏幕坐标(px),viewport 不可用时返回 null
13
+ */
14
+ export function anchorToScreen(anchor, adapter) {
15
+ const viewport = adapter.getViewport();
16
+ if (!viewport)
17
+ return null;
18
+ const { kWidth, kGap } = adapter.getKWidthKGap();
19
+ const dpr = adapter.getCurrentDpr();
20
+ const { startXPx, unitPx } = getPhysicalKLineConfig(kWidth, kGap, dpr);
21
+ if (!Number.isFinite(anchor.index))
22
+ return null;
23
+ const x = (startXPx + anchor.index * unitPx + (unitPx - 1) / 2) / dpr - viewport.scrollLeft;
24
+ const y = adapter.priceToY('main', anchor.price);
25
+ return { x, y };
26
+ }
27
+ /**
28
+ * 将屏幕坐标(px)反向解析为逻辑锚点坐标(index + price)。
29
+ *
30
+ * 用于拖拽整线时的屏幕偏移量回算。
31
+ *
32
+ * @returns DrawingAnchorInput,viewport 不可用或索引不在数据范围内时返回 null
33
+ */
34
+ export function screenToAnchor(screenX, screenY, adapter) {
35
+ const data = adapter.getData();
36
+ const viewport = adapter.getViewport();
37
+ if (!viewport || data.length === 0)
38
+ return null;
39
+ const logicalIndex = adapter.getLogicalIndexAtX(screenX);
40
+ if (logicalIndex === null)
41
+ return null;
42
+ const paneInfo = adapter.getPaneInfo('main');
43
+ if (!paneInfo)
44
+ return null;
45
+ const timestamp = adapter.getTimestampAtLogicalIndex(logicalIndex) ?? undefined;
46
+ return {
47
+ index: logicalIndex,
48
+ time: timestamp ?? undefined,
49
+ price: adapter.yToPrice('main', screenY - paneInfo.top),
50
+ };
51
+ }
52
+ /**
53
+ * 从 PointerEvent 中解析出光标位置对应的逻辑锚点。
54
+ *
55
+ * 边界检测:
56
+ * - 鼠标超出 viewport.plotWidth / plotHeight → null
57
+ * - 鼠标不在 main pane 范围内 → null
58
+ * - 鼠标位置无对应 K 线索引 → null
59
+ *
60
+ * @returns DrawingAnchorInput,超出范围或数据不可用时返回 null
61
+ */
62
+ export function resolveAnchorFromPointer(e, container, adapter) {
63
+ const data = adapter.getData();
64
+ const viewport = adapter.getViewport();
65
+ if (!viewport || data.length === 0)
66
+ return null;
67
+ const rect = container.getBoundingClientRect();
68
+ const mouseX = e.clientX - rect.left;
69
+ const mouseY = e.clientY - rect.top;
70
+ if (mouseX < 0 || mouseY < 0 || mouseX > viewport.plotWidth || mouseY > viewport.plotHeight) {
71
+ return null;
72
+ }
73
+ const paneInfo = adapter.getPaneInfo('main');
74
+ if (!paneInfo)
75
+ return null;
76
+ if (mouseY < paneInfo.top || mouseY > paneInfo.top + paneInfo.height)
77
+ return null;
78
+ const logicalIndex = adapter.getLogicalIndexAtX(mouseX);
79
+ if (logicalIndex === null)
80
+ return null;
81
+ const timestamp = adapter.getTimestampAtLogicalIndex(logicalIndex) ?? undefined;
82
+ return {
83
+ index: logicalIndex,
84
+ time: timestamp ?? undefined,
85
+ price: adapter.yToPrice('main', mouseY - paneInfo.top),
86
+ };
87
+ }
88
+ // ---- Geometry ----
89
+ /**
90
+ * 计算点 P 到线段 AB 的最短距离。
91
+ * 投影点在 AB 线段外时取最近端点距离。
92
+ */
93
+ export function pointToSegmentDist(px, py, a, b) {
94
+ const dx = b.x - a.x;
95
+ const dy = b.y - a.y;
96
+ const lenSq = dx * dx + dy * dy;
97
+ if (lenSq === 0)
98
+ return Math.hypot(px - a.x, py - a.y);
99
+ let t = ((px - a.x) * dx + (py - a.y) * dy) / lenSq;
100
+ t = Math.max(0, Math.min(1, t));
101
+ return Math.hypot(px - (a.x + t * dx), py - (a.y + t * dy));
102
+ }
103
+ //# sourceMappingURL=coordinateUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coordinateUtils.js","sourceRoot":"","sources":["../../../src/engine/drawing/coordinateUtils.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/drawing/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/engine/drawing/index.ts"],"names":[],"mappings":"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"}
@@ -224,7 +224,14 @@ export function createDefaultPrimitiveRendererSet() {
224
224
  ctx.font = `${primitive.style?.fontSize ?? 12}px sans-serif`;
225
225
  ctx.textAlign = primitive.align ?? 'left';
226
226
  ctx.textBaseline = primitive.baseline ?? 'bottom';
227
- ctx.fillText(primitive.text, primitive.point.x, primitive.point.y);
227
+ if (primitive.rotation !== undefined) {
228
+ ctx.translate(primitive.point.x, primitive.point.y);
229
+ ctx.rotate(primitive.rotation);
230
+ ctx.fillText(primitive.text, 0, 0);
231
+ }
232
+ else {
233
+ ctx.fillText(primitive.text, primitive.point.x, primitive.point.y);
234
+ }
228
235
  ctx.restore();
229
236
  },
230
237
  };
@@ -322,10 +329,11 @@ export function createInfoLineDefinition() {
322
329
  { kind: 'line', a, b, style: drawing.style },
323
330
  {
324
331
  kind: 'text',
325
- point: { x: (a.x + b.x) / 2 + 8, y: Math.min(a.y, b.y) - 8 },
332
+ point: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
326
333
  text,
327
- align: 'left',
334
+ align: 'center',
328
335
  baseline: 'bottom',
336
+ rotation: Math.atan2(b.y - a.y, b.x - a.x),
329
337
  style: drawing.style,
330
338
  },
331
339
  ],