@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,139 @@
1
+ import type { DrawingAnchor } from '../../plugin'
2
+ import type { DrawingChartAdapter } from '../../controllers/types'
3
+ import { getPhysicalKLineConfig } from '../utils/klineConfig'
4
+
5
+ // ---- Types ----
6
+
7
+ /** 原始锚点输入(逻辑坐标:K线索引 + 价格) */
8
+ export interface DrawingAnchorInput {
9
+ /** K线柱逻辑索引(可以是小数,表示在两柱之间) */
10
+ index: number
11
+ /** 对应的时间戳(ms) */
12
+ time?: number
13
+ /** 价格 */
14
+ price: number
15
+ }
16
+
17
+ // ---- Coordinate conversion ----
18
+
19
+ /**
20
+ * 将图元锚点的逻辑坐标(index + price)转换为屏幕坐标(px)。
21
+ *
22
+ * 计算过程:
23
+ * 1. 通过 getPhysicalKLineConfig 获取 K 线柱的起始像素位置和单柱像素宽度
24
+ * 2. anchor.index × unitPx 得到距起始位置的偏移
25
+ * 3. 减去 viewport.scrollLeft 得到相对视口的 X
26
+ * 4. 通过 adapter.priceToY 将价格转为 Y
27
+ *
28
+ * @returns {x, y} 屏幕坐标(px),viewport 不可用时返回 null
29
+ */
30
+ export function anchorToScreen(
31
+ anchor: DrawingAnchor,
32
+ adapter: DrawingChartAdapter
33
+ ): { x: number; y: number } | null {
34
+ const viewport = adapter.getViewport()
35
+ if (!viewport) return null
36
+
37
+ const { kWidth, kGap } = adapter.getKWidthKGap()
38
+ const dpr = adapter.getCurrentDpr()
39
+ const { startXPx, unitPx } = getPhysicalKLineConfig(kWidth, kGap, dpr)
40
+ if (!Number.isFinite(anchor.index)) return null
41
+
42
+ const x = (startXPx + anchor.index * unitPx + (unitPx - 1) / 2) / dpr - viewport.scrollLeft
43
+ const y = adapter.priceToY('main', anchor.price)
44
+ return { x, y }
45
+ }
46
+
47
+ /**
48
+ * 将屏幕坐标(px)反向解析为逻辑锚点坐标(index + price)。
49
+ *
50
+ * 用于拖拽整线时的屏幕偏移量回算。
51
+ *
52
+ * @returns DrawingAnchorInput,viewport 不可用或索引不在数据范围内时返回 null
53
+ */
54
+ export function screenToAnchor(
55
+ screenX: number,
56
+ screenY: number,
57
+ adapter: DrawingChartAdapter
58
+ ): DrawingAnchorInput | null {
59
+ const data = adapter.getData()
60
+ const viewport = adapter.getViewport()
61
+ if (!viewport || data.length === 0) return null
62
+
63
+ const logicalIndex = adapter.getLogicalIndexAtX(screenX)
64
+ if (logicalIndex === null) return null
65
+
66
+ const paneInfo = adapter.getPaneInfo('main')
67
+ if (!paneInfo) return null
68
+
69
+ const timestamp = adapter.getTimestampAtLogicalIndex(logicalIndex) ?? undefined
70
+
71
+ return {
72
+ index: logicalIndex,
73
+ time: timestamp ?? undefined,
74
+ price: adapter.yToPrice('main', screenY - paneInfo.top),
75
+ }
76
+ }
77
+
78
+ /**
79
+ * 从 PointerEvent 中解析出光标位置对应的逻辑锚点。
80
+ *
81
+ * 边界检测:
82
+ * - 鼠标超出 viewport.plotWidth / plotHeight → null
83
+ * - 鼠标不在 main pane 范围内 → null
84
+ * - 鼠标位置无对应 K 线索引 → null
85
+ *
86
+ * @returns DrawingAnchorInput,超出范围或数据不可用时返回 null
87
+ */
88
+ export function resolveAnchorFromPointer(
89
+ e: PointerEvent,
90
+ container: HTMLElement,
91
+ adapter: DrawingChartAdapter
92
+ ): DrawingAnchorInput | null {
93
+ const data = adapter.getData()
94
+ const viewport = adapter.getViewport()
95
+ if (!viewport || data.length === 0) return null
96
+
97
+ const rect = container.getBoundingClientRect()
98
+ const mouseX = e.clientX - rect.left
99
+ const mouseY = e.clientY - rect.top
100
+ if (mouseX < 0 || mouseY < 0 || mouseX > viewport.plotWidth || mouseY > viewport.plotHeight) {
101
+ return null
102
+ }
103
+
104
+ const paneInfo = adapter.getPaneInfo('main')
105
+ if (!paneInfo) return null
106
+ if (mouseY < paneInfo.top || mouseY > paneInfo.top + paneInfo.height) return null
107
+
108
+ const logicalIndex = adapter.getLogicalIndexAtX(mouseX)
109
+ if (logicalIndex === null) return null
110
+ const timestamp = adapter.getTimestampAtLogicalIndex(logicalIndex) ?? undefined
111
+
112
+ return {
113
+ index: logicalIndex,
114
+ time: timestamp ?? undefined,
115
+ price: adapter.yToPrice('main', mouseY - paneInfo.top),
116
+ }
117
+ }
118
+
119
+ // ---- Geometry ----
120
+
121
+ /**
122
+ * 计算点 P 到线段 AB 的最短距离。
123
+ * 投影点在 AB 线段外时取最近端点距离。
124
+ */
125
+ export function pointToSegmentDist(
126
+ px: number,
127
+ py: number,
128
+ a: { x: number; y: number },
129
+ b: { x: number; y: number }
130
+ ): number {
131
+ const dx = b.x - a.x
132
+ const dy = b.y - a.y
133
+ const lenSq = dx * dx + dy * dy
134
+ if (lenSq === 0) return Math.hypot(px - a.x, py - a.y)
135
+
136
+ let t = ((px - a.x) * dx + (py - a.y) * dy) / lenSq
137
+ t = Math.max(0, Math.min(1, t))
138
+ return Math.hypot(px - (a.x + t * dx), py - (a.y + t * dy))
139
+ }
@@ -297,7 +297,13 @@ export function createDefaultPrimitiveRendererSet(): PrimitiveRendererSet {
297
297
  ctx.font = `${primitive.style?.fontSize ?? 12}px sans-serif`
298
298
  ctx.textAlign = primitive.align ?? 'left'
299
299
  ctx.textBaseline = primitive.baseline ?? 'bottom'
300
- ctx.fillText(primitive.text, primitive.point.x, primitive.point.y)
300
+ if (primitive.rotation !== undefined) {
301
+ ctx.translate(primitive.point.x, primitive.point.y)
302
+ ctx.rotate(primitive.rotation)
303
+ ctx.fillText(primitive.text, 0, 0)
304
+ } else {
305
+ ctx.fillText(primitive.text, primitive.point.x, primitive.point.y)
306
+ }
301
307
  ctx.restore()
302
308
  },
303
309
  }
@@ -400,10 +406,11 @@ export function createInfoLineDefinition(): DrawingDefinition {
400
406
  { kind: 'line', a, b, style: drawing.style },
401
407
  {
402
408
  kind: 'text',
403
- point: { x: (a.x + b.x) / 2 + 8, y: Math.min(a.y, b.y) - 8 },
409
+ point: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
404
410
  text,
405
- align: 'left',
411
+ align: 'center',
406
412
  baseline: 'bottom',
413
+ rotation: Math.atan2(b.y - a.y, b.x - a.x),
407
414
  style: drawing.style,
408
415
  },
409
416
  ],