@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.
- package/dist/controllers/index.d.ts +1 -1
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/data-fetchers/dataBuffer.d.ts +0 -1
- package/dist/data-fetchers/dataBuffer.d.ts.map +1 -1
- package/dist/data-fetchers/dataBuffer.effects.d.ts +21 -0
- package/dist/data-fetchers/dataBuffer.effects.d.ts.map +1 -0
- package/dist/data-fetchers/dataBuffer.effects.js +55 -0
- package/dist/data-fetchers/dataBuffer.effects.js.map +1 -0
- package/dist/data-fetchers/dataBuffer.js +58 -93
- package/dist/data-fetchers/dataBuffer.js.map +1 -1
- package/dist/data-fetchers/index.d.ts +1 -0
- package/dist/data-fetchers/index.d.ts.map +1 -1
- package/dist/data-fetchers/index.js +1 -0
- package/dist/data-fetchers/index.js.map +1 -1
- package/dist/data-fetchers/timeShareBuffer.d.ts +2 -1
- package/dist/data-fetchers/timeShareBuffer.d.ts.map +1 -1
- package/dist/data-fetchers/timeShareBuffer.js +36 -14
- package/dist/data-fetchers/timeShareBuffer.js.map +1 -1
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +2 -1
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/drawing/AnchorCollector.d.ts +26 -0
- package/dist/engine/drawing/AnchorCollector.d.ts.map +1 -0
- package/dist/engine/drawing/AnchorCollector.js +47 -0
- package/dist/engine/drawing/AnchorCollector.js.map +1 -0
- package/dist/engine/drawing/DragHandler.d.ts +38 -0
- package/dist/engine/drawing/DragHandler.d.ts.map +1 -0
- package/dist/engine/drawing/DragHandler.js +92 -0
- package/dist/engine/drawing/DragHandler.js.map +1 -0
- package/dist/engine/drawing/DrawingState.d.ts +51 -0
- package/dist/engine/drawing/DrawingState.d.ts.map +1 -0
- package/dist/engine/drawing/DrawingState.js +115 -0
- package/dist/engine/drawing/DrawingState.js.map +1 -0
- package/dist/engine/drawing/HitTester.d.ts +59 -0
- package/dist/engine/drawing/HitTester.d.ts.map +1 -0
- package/dist/engine/drawing/HitTester.js +219 -0
- package/dist/engine/drawing/HitTester.js.map +1 -0
- package/dist/engine/drawing/PreviewRenderer.d.ts +26 -0
- package/dist/engine/drawing/PreviewRenderer.d.ts.map +1 -0
- package/dist/engine/drawing/PreviewRenderer.js +131 -0
- package/dist/engine/drawing/PreviewRenderer.js.map +1 -0
- package/dist/engine/drawing/coordinateUtils.d.ts +57 -0
- package/dist/engine/drawing/coordinateUtils.d.ts.map +1 -0
- package/dist/engine/drawing/coordinateUtils.js +103 -0
- package/dist/engine/drawing/coordinateUtils.js.map +1 -0
- package/dist/engine/drawing/index.d.ts.map +1 -1
- package/dist/engine/drawing/index.js +11 -3
- package/dist/engine/drawing/index.js.map +1 -1
- package/dist/engine/drawing/interaction.d.ts +44 -40
- package/dist/engine/drawing/interaction.d.ts.map +1 -1
- package/dist/engine/drawing/interaction.js +132 -571
- package/dist/engine/drawing/interaction.js.map +1 -1
- package/dist/engine/drawing/toolConfig.d.ts +24 -0
- package/dist/engine/drawing/toolConfig.d.ts.map +1 -0
- package/dist/engine/drawing/toolConfig.js +76 -0
- package/dist/engine/drawing/toolConfig.js.map +1 -0
- package/dist/plugin/types.d.ts +1 -0
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/plugin/types.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +4 -1
- package/src/controllers/index.ts +1 -0
- package/src/data-fetchers/__tests__/dataBuffer.test.ts +1 -3
- package/src/data-fetchers/dataBuffer.effects.ts +118 -0
- package/src/data-fetchers/dataBuffer.ts +45 -86
- package/src/data-fetchers/index.ts +7 -0
- package/src/data-fetchers/timeShareBuffer.ts +58 -19
- package/src/engine/__tests__/paneRenderer.resize.test.ts +3 -0
- package/src/engine/__tests__/subPaneManager.test.ts +13 -3
- package/src/engine/data/chartDataManager.ts +2 -1
- package/src/engine/drawing/AnchorCollector.ts +57 -0
- package/src/engine/drawing/DragHandler.ts +121 -0
- package/src/engine/drawing/DrawingState.ts +132 -0
- package/src/engine/drawing/HitTester.ts +288 -0
- package/src/engine/drawing/PreviewRenderer.ts +157 -0
- package/src/engine/drawing/coordinateUtils.ts +139 -0
- package/src/engine/drawing/index.ts +10 -3
- package/src/engine/drawing/interaction.ts +177 -687
- package/src/engine/drawing/toolConfig.ts +103 -0
- package/src/engine/indicators/__tests__/chartIndicatorManager.test.ts +1 -0
- package/src/engine/indicators/__tests__/stateComposer.test.ts +5 -4
- package/src/engine/renderers/Indicator/__tests__/createSubIndicatorRenderer.test.ts +1 -0
- package/src/plugin/types.ts +1 -0
- package/src/tokens/__tests__/tokens.test.ts +2 -1
- 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
|
-
|
|
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
|
|
409
|
+
point: { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 },
|
|
404
410
|
text,
|
|
405
|
-
align: '
|
|
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
|
],
|