@363045841yyt/klinechart-core 0.7.3 → 0.7.5-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -201
- package/README.zh-CN.md +201 -201
- package/dist/engine/renderers/webgl/candleSurface.js +47 -47
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +129 -122
- package/src/__tests__/signal.test.ts +124 -124
- package/src/config/chartSettings.ts +66 -66
- package/src/controllers/__tests__/drawing.test.ts +214 -214
- package/src/controllers/__tests__/indicatorSelector.test.ts +481 -481
- package/src/controllers/__tests__/toolbar.test.ts +225 -225
- package/src/controllers/createChartController.ts +665 -665
- package/src/controllers/createDrawingController.ts +96 -96
- package/src/controllers/createIndicatorSelectorController.ts +307 -307
- package/src/controllers/createToolbarController.ts +146 -146
- package/src/controllers/index.ts +19 -19
- package/src/controllers/types.ts +284 -284
- package/src/engine/__tests__/chart.dpr.test.ts +401 -401
- package/src/engine/__tests__/paneRenderer.resize.test.ts +92 -92
- package/src/engine/chart-store.ts +121 -121
- package/src/engine/chart.d.ts +617 -617
- package/src/engine/chart.ts +2815 -2815
- package/src/engine/controller/__tests__/interaction.dpr.test.ts +259 -259
- package/src/engine/controller/interaction.ts +722 -722
- package/src/engine/controller/markerInteraction.ts +130 -130
- package/src/engine/controller/pinchTracker.ts +82 -82
- package/src/engine/controller/tooltipPosition.ts +48 -48
- package/src/engine/draw/__tests__/pixelAlign.spec.ts +176 -176
- package/src/engine/draw/pixelAlign.ts +259 -259
- package/src/engine/drawing/index.ts +655 -655
- package/src/engine/drawing/interaction.ts +842 -842
- package/src/engine/drawing/plugin.ts +343 -343
- package/src/engine/indicators/__tests__/__fixtures__/golden/atr.json +38 -38
- package/src/engine/indicators/__tests__/__fixtures__/golden/dema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/hma.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/index.ts +55 -55
- package/src/engine/indicators/__tests__/__fixtures__/golden/kama.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/tema.json +14 -14
- package/src/engine/indicators/__tests__/__fixtures__/golden/wma.json +40 -40
- package/src/engine/indicators/__tests__/__fixtures__/synthetic.ts +65 -65
- package/src/engine/indicators/__tests__/_propertyAssertions.ts +76 -76
- package/src/engine/indicators/__tests__/atr.test.ts +153 -153
- package/src/engine/indicators/__tests__/calculators.test.ts +614 -614
- package/src/engine/indicators/__tests__/cmf-mfi.test.ts +100 -100
- package/src/engine/indicators/__tests__/dema.test.ts +73 -73
- package/src/engine/indicators/__tests__/donchian.test.ts +70 -70
- package/src/engine/indicators/__tests__/hma.test.ts +73 -73
- package/src/engine/indicators/__tests__/ichimoku.test.ts +105 -105
- package/src/engine/indicators/__tests__/kama.test.ts +80 -80
- package/src/engine/indicators/__tests__/keltner.test.ts +65 -65
- package/src/engine/indicators/__tests__/pivot-fib.test.ts +110 -110
- package/src/engine/indicators/__tests__/roc.test.ts +68 -68
- package/src/engine/indicators/__tests__/sar.test.ts +86 -86
- package/src/engine/indicators/__tests__/scheduler.test.ts +831 -831
- package/src/engine/indicators/__tests__/soa.test.ts +533 -533
- package/src/engine/indicators/__tests__/structure.test.ts +110 -110
- package/src/engine/indicators/__tests__/supertrend.test.ts +65 -65
- package/src/engine/indicators/__tests__/tema.test.ts +68 -68
- package/src/engine/indicators/__tests__/trix.test.ts +70 -70
- package/src/engine/indicators/__tests__/volatility.test.ts +117 -117
- package/src/engine/indicators/__tests__/volume.test.ts +115 -115
- package/src/engine/indicators/__tests__/volumeProfile.test.ts +74 -74
- package/src/engine/indicators/__tests__/vwap.test.ts +69 -69
- package/src/engine/indicators/__tests__/wma.test.ts +112 -112
- package/src/engine/indicators/__tests__/zones.test.ts +95 -95
- package/src/engine/indicators/atrState.ts +27 -27
- package/src/engine/indicators/bollState.ts +51 -51
- package/src/engine/indicators/calculators.ts +2593 -2593
- package/src/engine/indicators/cciState.ts +25 -25
- package/src/engine/indicators/chaikinVolState.ts +32 -32
- package/src/engine/indicators/cmfState.ts +27 -27
- package/src/engine/indicators/demaState.ts +27 -27
- package/src/engine/indicators/donchianState.ts +43 -43
- package/src/engine/indicators/eneState.ts +43 -43
- package/src/engine/indicators/expmaState.ts +43 -43
- package/src/engine/indicators/fastkState.ts +25 -25
- package/src/engine/indicators/fibState.ts +41 -41
- package/src/engine/indicators/hmaState.ts +27 -27
- package/src/engine/indicators/hvState.ts +28 -28
- package/src/engine/indicators/ichimokuState.ts +70 -70
- package/src/engine/indicators/indicator.worker.ts +169 -169
- package/src/engine/indicators/indicatorDefinitionRegistry.ts +62 -62
- package/src/engine/indicators/indicatorMetadata.ts +110 -110
- package/src/engine/indicators/indicatorRegistry.ts +106 -106
- package/src/engine/indicators/indicatorRuntime.ts +1548 -1548
- package/src/engine/indicators/kamaState.ts +34 -34
- package/src/engine/indicators/keltnerState.ts +49 -49
- package/src/engine/indicators/kstState.ts +42 -42
- package/src/engine/indicators/maState.ts +36 -36
- package/src/engine/indicators/macdState.ts +76 -76
- package/src/engine/indicators/mfiState.ts +27 -27
- package/src/engine/indicators/momState.ts +25 -25
- package/src/engine/indicators/obvState.ts +25 -25
- package/src/engine/indicators/parkinsonState.ts +28 -28
- package/src/engine/indicators/pivotState.ts +51 -51
- package/src/engine/indicators/pvtState.ts +25 -25
- package/src/engine/indicators/rocState.ts +27 -27
- package/src/engine/indicators/rsiState.ts +65 -65
- package/src/engine/indicators/sarState.ts +41 -41
- package/src/engine/indicators/scheduler.ts +1205 -1205
- package/src/engine/indicators/soa.ts +352 -352
- package/src/engine/indicators/stateComposer.ts +1262 -1262
- package/src/engine/indicators/stochState.ts +26 -26
- package/src/engine/indicators/structureState.ts +69 -69
- package/src/engine/indicators/supertrendState.ts +37 -37
- package/src/engine/indicators/temaState.ts +27 -27
- package/src/engine/indicators/trixState.ts +35 -35
- package/src/engine/indicators/vmaState.ts +27 -27
- package/src/engine/indicators/volumeProfileState.ts +63 -63
- package/src/engine/indicators/vwapState.ts +29 -29
- package/src/engine/indicators/wmaState.ts +27 -27
- package/src/engine/indicators/wmsrState.ts +25 -25
- package/src/engine/indicators/workerProtocol.ts +613 -613
- package/src/engine/indicators/zonesState.ts +47 -47
- package/src/engine/layout/pane.ts +161 -161
- package/src/engine/marker/registry.ts +265 -265
- package/src/engine/paneRenderer.ts +169 -169
- package/src/engine/renderers/Indicator/atr.ts +237 -237
- package/src/engine/renderers/Indicator/boll.ts +317 -317
- package/src/engine/renderers/Indicator/cci.ts +275 -275
- package/src/engine/renderers/Indicator/chaikinVol.ts +138 -138
- package/src/engine/renderers/Indicator/cmf.ts +137 -137
- package/src/engine/renderers/Indicator/dema.ts +136 -136
- package/src/engine/renderers/Indicator/donchian.ts +137 -137
- package/src/engine/renderers/Indicator/ene.ts +271 -271
- package/src/engine/renderers/Indicator/expma.ts +197 -197
- package/src/engine/renderers/Indicator/fastk.ts +316 -316
- package/src/engine/renderers/Indicator/fib.ts +141 -141
- package/src/engine/renderers/Indicator/hma.ts +136 -136
- package/src/engine/renderers/Indicator/hv.ts +124 -124
- package/src/engine/renderers/Indicator/ichimoku.ts +181 -181
- package/src/engine/renderers/Indicator/index.ts +241 -241
- package/src/engine/renderers/Indicator/indicatorData.ts +650 -650
- package/src/engine/renderers/Indicator/kama.ts +136 -136
- package/src/engine/renderers/Indicator/keltner.ts +137 -137
- package/src/engine/renderers/Indicator/kst.ts +302 -302
- package/src/engine/renderers/Indicator/ma.ts +200 -200
- package/src/engine/renderers/Indicator/macd.ts +477 -477
- package/src/engine/renderers/Indicator/macdLegend.ts +141 -141
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +272 -272
- package/src/engine/renderers/Indicator/mfi.ts +142 -142
- package/src/engine/renderers/Indicator/mom.ts +311 -311
- package/src/engine/renderers/Indicator/obv.ts +123 -123
- package/src/engine/renderers/Indicator/parkinson.ts +124 -124
- package/src/engine/renderers/Indicator/pivot.ts +131 -131
- package/src/engine/renderers/Indicator/pvt.ts +123 -123
- package/src/engine/renderers/Indicator/roc.ts +143 -143
- package/src/engine/renderers/Indicator/rsi.ts +390 -390
- package/src/engine/renderers/Indicator/sar.ts +113 -113
- package/src/engine/renderers/Indicator/scale/atr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/cci_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/fastk_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/indicator_scale.ts +204 -204
- package/src/engine/renderers/Indicator/scale/kst_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/macd_scale.ts +22 -22
- package/src/engine/renderers/Indicator/scale/mom_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/rsi_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/stoch_scale.ts +19 -19
- package/src/engine/renderers/Indicator/scale/volume_scale.ts +26 -26
- package/src/engine/renderers/Indicator/scale/wmsr_scale.ts +19 -19
- package/src/engine/renderers/Indicator/stoch.ts +359 -359
- package/src/engine/renderers/Indicator/structure.ts +126 -126
- package/src/engine/renderers/Indicator/subPaneConfig.ts +265 -265
- package/src/engine/renderers/Indicator/supertrend.ts +115 -115
- package/src/engine/renderers/Indicator/tema.ts +136 -136
- package/src/engine/renderers/Indicator/trix.ts +158 -158
- package/src/engine/renderers/Indicator/vma.ts +124 -124
- package/src/engine/renderers/Indicator/volumeProfile.ts +125 -125
- package/src/engine/renderers/Indicator/vwap.ts +123 -123
- package/src/engine/renderers/Indicator/wma.ts +136 -136
- package/src/engine/renderers/Indicator/wmsr.ts +328 -328
- package/src/engine/renderers/Indicator/zones.ts +104 -104
- package/src/engine/renderers/__tests__/boll.renderer.test.ts +314 -314
- package/src/engine/renderers/__tests__/ene.renderer.test.ts +305 -305
- package/src/engine/renderers/__tests__/expma.renderer.test.ts +279 -279
- package/src/engine/renderers/__tests__/ma.renderer.test.ts +426 -426
- package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +502 -502
- package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +173 -173
- package/src/engine/renderers/candle.ts +459 -459
- package/src/engine/renderers/crosshair.ts +69 -69
- package/src/engine/renderers/customMarkers.ts +162 -162
- package/src/engine/renderers/extremaMarkers.ts +246 -246
- package/src/engine/renderers/gridLines.ts +90 -90
- package/src/engine/renderers/lastPrice.ts +97 -97
- package/src/engine/renderers/paneTitle.ts +136 -136
- package/src/engine/renderers/subVolume.ts +236 -236
- package/src/engine/renderers/timeAxis.ts +121 -121
- package/src/engine/renderers/webgl/candleSurface.ts +955 -955
- package/src/engine/renderers/webgl/sharedWebGLSurface.ts +146 -146
- package/src/engine/renderers/yAxis.ts +105 -105
- package/src/engine/scale/__tests__/logFormula.spec.ts +148 -148
- package/src/engine/scale/logFormula.ts +130 -130
- package/src/engine/scale/price.ts +39 -39
- package/src/engine/scale/priceScale.ts +264 -264
- package/src/engine/subPaneManager.ts +427 -427
- package/src/engine/theme/colors.ts +642 -642
- package/src/engine/theme/fonts.ts +20 -20
- package/src/engine/utils/klineConfig.ts +49 -49
- package/src/engine/utils/tickCount.ts +11 -11
- package/src/engine/utils/tickPosition.ts +214 -214
- package/src/engine/utils/zoom.ts +83 -83
- package/src/engine/viewport/viewport.ts +67 -67
- package/src/index.ts +3 -3
- package/src/plugin/ConfigManager.ts +93 -93
- package/src/plugin/EventBus.ts +77 -77
- package/src/plugin/HookSystem.ts +106 -106
- package/src/plugin/PluginHost.ts +243 -243
- package/src/plugin/PluginRegistry.ts +92 -92
- package/src/plugin/StateStore.ts +73 -73
- package/src/plugin/index.ts +19 -19
- package/src/plugin/rendererPluginManager.ts +368 -368
- package/src/plugin/stateKeys.ts +8 -8
- package/src/plugin/types.ts +526 -526
- package/src/reactivity/index.ts +2 -2
- package/src/reactivity/signal.ts +119 -119
- package/src/semantic/controller.ts +251 -251
- package/src/semantic/drawShape.ts +260 -260
- package/src/semantic/index.ts +28 -28
- package/src/semantic/schema.json +256 -256
- package/src/semantic/types.ts +251 -251
- package/src/semantic/validator.ts +349 -349
- package/src/types/kLine.ts +13 -13
- package/src/types/price.ts +56 -56
- package/src/types/volumePrice.ts +33 -33
- package/src/utils/dateFormat.ts +208 -208
- package/src/utils/kLineDraw/axis.ts +562 -562
- package/src/utils/priceToY.ts +34 -34
- package/src/utils/volumePrice.ts +202 -202
- package/src/version.ts +1 -1
|
@@ -1,266 +1,266 @@
|
|
|
1
|
-
import { hitTestShape } from '../../semantic/drawShape'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 标记类型
|
|
5
|
-
*/
|
|
6
|
-
export type MarkerShape = 'triangle' | 'circle'
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* 标记状态
|
|
10
|
-
*/
|
|
11
|
-
export type MarkerState = 'normal' | 'hovered'
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* 标记类型描述注册表
|
|
15
|
-
*/
|
|
16
|
-
export const MARKER_TYPE_DESCRIPTIONS: Record<string, string> = {
|
|
17
|
-
'RISE_WITH_VOLUME': '量价齐升',
|
|
18
|
-
'RISE_WITHOUT_VOLUME': '量缩价升',
|
|
19
|
-
'FALL_WITH_VOLUME': '量价齐缩',
|
|
20
|
-
'FALL_WITHOUT_VOLUME': '量升价缩',
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* 注册新的标记类型描述
|
|
25
|
-
* @param type 标记类型
|
|
26
|
-
* @param description 描述文本
|
|
27
|
-
*/
|
|
28
|
-
export function registerMarkerTypeDescription(type: string, description: string): void {
|
|
29
|
-
MARKER_TYPE_DESCRIPTIONS[type] = description
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* 标记实体
|
|
34
|
-
*/
|
|
35
|
-
export interface MarkerEntity {
|
|
36
|
-
id: string
|
|
37
|
-
type: MarkerShape
|
|
38
|
-
/** 标记类型描述 */
|
|
39
|
-
markerType: string
|
|
40
|
-
/** 包围盒左上角 x 坐标 */
|
|
41
|
-
x: number
|
|
42
|
-
/** 包围盒左上角 y 坐标 */
|
|
43
|
-
y: number
|
|
44
|
-
/** 包围盒宽度 */
|
|
45
|
-
width: number
|
|
46
|
-
/** 包围盒高度 */
|
|
47
|
-
height: number
|
|
48
|
-
/** 对应的 K 线索引 */
|
|
49
|
-
dataIndex: number
|
|
50
|
-
/** 额外元数据(如量价关系类型等) */
|
|
51
|
-
metadata: Record<string, any>
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// ============ 自定义标记类型(语义化配置) ============
|
|
55
|
-
|
|
56
|
-
/** 自定义标记形状 */
|
|
57
|
-
export type CustomMarkerShape = 'arrow_up' | 'arrow_down' | 'flag' | 'circle' | 'rectangle' | 'diamond'
|
|
58
|
-
|
|
59
|
-
/** 自定义标记样式 */
|
|
60
|
-
export interface CustomMarkerStyle {
|
|
61
|
-
fillColor?: string
|
|
62
|
-
strokeColor?: string
|
|
63
|
-
textColor?: string
|
|
64
|
-
size?: number
|
|
65
|
-
lineWidth?: number
|
|
66
|
-
opacity?: number
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** 自定义标记标签 */
|
|
70
|
-
export interface CustomMarkerLabel {
|
|
71
|
-
text: string
|
|
72
|
-
position?: 'left' | 'right' | 'top' | 'bottom' | 'inside'
|
|
73
|
-
align?: 'start' | 'center' | 'end'
|
|
74
|
-
fontSize?: number
|
|
75
|
-
offset?: { x?: number; y?: number }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** 自定义标记实体 */
|
|
79
|
-
export interface CustomMarkerEntity {
|
|
80
|
-
id: string
|
|
81
|
-
/**
|
|
82
|
-
* 日期时间字符串
|
|
83
|
-
* - 日K/周K/月K: "YYYY-MM-DD"
|
|
84
|
-
* - 分钟K: "YYYY-MM-DD HH:mm"
|
|
85
|
-
*/
|
|
86
|
-
date: string
|
|
87
|
-
/** Unix 毫秒时间戳(由 date 解析生成,用于二分查找) */
|
|
88
|
-
timestamp: number
|
|
89
|
-
shape: CustomMarkerShape
|
|
90
|
-
groupKey?: string
|
|
91
|
-
offset?: { x?: number; y?: number }
|
|
92
|
-
style?: CustomMarkerStyle
|
|
93
|
-
label?: CustomMarkerLabel
|
|
94
|
-
metadata?: Record<string, unknown>
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 标记 Manager
|
|
99
|
-
*/
|
|
100
|
-
export class MarkerManager {
|
|
101
|
-
/** 当前帧可见的标记集合(key: marker.id) */
|
|
102
|
-
private markers: Map<string, MarkerEntity> = new Map()
|
|
103
|
-
/** 当前 hover 的标记 ID(跨帧持久) */
|
|
104
|
-
private hoveredMarkerId: string | null = null
|
|
105
|
-
/** 上一帧 hover 的标记 ID(用于触发 enter/leave 事件) */
|
|
106
|
-
private lastHoveredId: string | null = null
|
|
107
|
-
|
|
108
|
-
// ============ 自定义标记状态管理 ============
|
|
109
|
-
/** 自定义标记集合 */
|
|
110
|
-
private customMarkers: Map<string, CustomMarkerEntity> = new Map()
|
|
111
|
-
/** 自定义标记位置缓存(用于 hitTest) */
|
|
112
|
-
private customMarkerPositions: Map<string, { x: number; y: number; size: number; shape: CustomMarkerShape }> = new Map()
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* 清空标记集合
|
|
116
|
-
* 注意:不清除 hoveredMarkerId,保持 hover 状态跨帧持久
|
|
117
|
-
*/
|
|
118
|
-
clear(): void {
|
|
119
|
-
this.markers.clear()
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 注册标记
|
|
124
|
-
* @param marker 标记实体
|
|
125
|
-
*/
|
|
126
|
-
register(marker: MarkerEntity): void {
|
|
127
|
-
this.markers.set(marker.id, marker)
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* 获取标记状态
|
|
132
|
-
* @param id 标记 ID
|
|
133
|
-
* @returns 'hovered' 或 'normal'
|
|
134
|
-
*/
|
|
135
|
-
getState(id: string): MarkerState {
|
|
136
|
-
if (this.hoveredMarkerId === id) {
|
|
137
|
-
return 'hovered'
|
|
138
|
-
}
|
|
139
|
-
return 'normal'
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* 命中测试
|
|
144
|
-
* @param x 鼠标 x 坐标
|
|
145
|
-
* @param y 鼠标 y 坐标
|
|
146
|
-
* @param padding 命中区域扩展(默认 3px)
|
|
147
|
-
* @returns 命中的标记,未命中返回 null
|
|
148
|
-
*/
|
|
149
|
-
hitTest(x: number, y: number, padding: number = 3): MarkerEntity | null {
|
|
150
|
-
for (const marker of this.markers.values()) {
|
|
151
|
-
if (x >= marker.x - padding && x <= marker.x + marker.width + padding &&
|
|
152
|
-
y >= marker.y - padding && y <= marker.y + marker.height + padding
|
|
153
|
-
) {
|
|
154
|
-
return marker
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
return null
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* 设置 hover 状态
|
|
162
|
-
* @param id 标记 ID,null 表示清除 hover
|
|
163
|
-
*/
|
|
164
|
-
setHover(id: string | null): void {
|
|
165
|
-
this.hoveredMarkerId = id
|
|
166
|
-
this.lastHoveredId = id
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* 验证 hover 状态
|
|
171
|
-
* 检查当前 hover 的标记是否仍在视口内,不在则清除
|
|
172
|
-
*/
|
|
173
|
-
validateHoverState(): void {
|
|
174
|
-
if (this.hoveredMarkerId !== null && !this.markers.has(this.hoveredMarkerId)) {
|
|
175
|
-
this.hoveredMarkerId = null
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* 获取当前 hover 的标记实体
|
|
181
|
-
* @returns hover 的标记,不存在返回 null
|
|
182
|
-
*/
|
|
183
|
-
getHoveredMarker(): MarkerEntity | null {
|
|
184
|
-
if (this.hoveredMarkerId !== null) {
|
|
185
|
-
return this.markers.get(this.hoveredMarkerId) || null
|
|
186
|
-
}
|
|
187
|
-
return null
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 获取上一帧 hover 的标记 ID
|
|
192
|
-
* 用于检测 hover 状态变化
|
|
193
|
-
* @returns 上一帧的 hover ID
|
|
194
|
-
*/
|
|
195
|
-
getLastHoverId(): string | null {
|
|
196
|
-
return this.lastHoveredId
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* 获取所有当前可见的标记
|
|
201
|
-
* @returns 标记数组
|
|
202
|
-
*/
|
|
203
|
-
getAllMarkers(): MarkerEntity[] {
|
|
204
|
-
return Array.from(this.markers.values())
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// ============ 自定义标记管理方法 ============
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* 注册自定义标记
|
|
211
|
-
*/
|
|
212
|
-
registerCustomMarker(marker: CustomMarkerEntity): void {
|
|
213
|
-
this.customMarkers.set(marker.id, marker)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* 批量设置自定义标记
|
|
218
|
-
*/
|
|
219
|
-
setCustomMarkers(markers: CustomMarkerEntity[]): void {
|
|
220
|
-
this.clearCustomMarkers()
|
|
221
|
-
for (const marker of markers) {
|
|
222
|
-
this.customMarkers.set(marker.id, marker)
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* 清空自定义标记(含位置缓存)
|
|
228
|
-
*/
|
|
229
|
-
clearCustomMarkers(): void {
|
|
230
|
-
this.customMarkers.clear()
|
|
231
|
-
this.customMarkerPositions.clear()
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* 获取所有自定义标记
|
|
236
|
-
*/
|
|
237
|
-
getCustomMarkers(): CustomMarkerEntity[] {
|
|
238
|
-
return Array.from(this.customMarkers.values())
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* 记录自定义标记位置(render 时调用)
|
|
243
|
-
*/
|
|
244
|
-
setCustomMarkerPosition(id: string, x: number, y: number, size: number, shape: CustomMarkerShape): void {
|
|
245
|
-
this.customMarkerPositions.set(id, { x, y, size, shape })
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* 自定义标记点击测试
|
|
250
|
-
* @param x 鼠标 x 坐标
|
|
251
|
-
* @param y 鼠标 y 坐标
|
|
252
|
-
* @returns 命中的自定义标记,未命中返回 null
|
|
253
|
-
*/
|
|
254
|
-
hitTestCustomMarker(x: number, y: number): CustomMarkerEntity | null {
|
|
255
|
-
for (const marker of this.customMarkers.values()) {
|
|
256
|
-
const pos = this.customMarkerPositions.get(marker.id)
|
|
257
|
-
if (pos) {
|
|
258
|
-
// 使用实际渲染的大小进行命中测试
|
|
259
|
-
if (hitTestShape(x, y, pos.shape, pos.x, pos.y, pos.size)) {
|
|
260
|
-
return marker
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return null
|
|
265
|
-
}
|
|
1
|
+
import { hitTestShape } from '../../semantic/drawShape'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 标记类型
|
|
5
|
+
*/
|
|
6
|
+
export type MarkerShape = 'triangle' | 'circle'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* 标记状态
|
|
10
|
+
*/
|
|
11
|
+
export type MarkerState = 'normal' | 'hovered'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* 标记类型描述注册表
|
|
15
|
+
*/
|
|
16
|
+
export const MARKER_TYPE_DESCRIPTIONS: Record<string, string> = {
|
|
17
|
+
'RISE_WITH_VOLUME': '量价齐升',
|
|
18
|
+
'RISE_WITHOUT_VOLUME': '量缩价升',
|
|
19
|
+
'FALL_WITH_VOLUME': '量价齐缩',
|
|
20
|
+
'FALL_WITHOUT_VOLUME': '量升价缩',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* 注册新的标记类型描述
|
|
25
|
+
* @param type 标记类型
|
|
26
|
+
* @param description 描述文本
|
|
27
|
+
*/
|
|
28
|
+
export function registerMarkerTypeDescription(type: string, description: string): void {
|
|
29
|
+
MARKER_TYPE_DESCRIPTIONS[type] = description
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* 标记实体
|
|
34
|
+
*/
|
|
35
|
+
export interface MarkerEntity {
|
|
36
|
+
id: string
|
|
37
|
+
type: MarkerShape
|
|
38
|
+
/** 标记类型描述 */
|
|
39
|
+
markerType: string
|
|
40
|
+
/** 包围盒左上角 x 坐标 */
|
|
41
|
+
x: number
|
|
42
|
+
/** 包围盒左上角 y 坐标 */
|
|
43
|
+
y: number
|
|
44
|
+
/** 包围盒宽度 */
|
|
45
|
+
width: number
|
|
46
|
+
/** 包围盒高度 */
|
|
47
|
+
height: number
|
|
48
|
+
/** 对应的 K 线索引 */
|
|
49
|
+
dataIndex: number
|
|
50
|
+
/** 额外元数据(如量价关系类型等) */
|
|
51
|
+
metadata: Record<string, any>
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ============ 自定义标记类型(语义化配置) ============
|
|
55
|
+
|
|
56
|
+
/** 自定义标记形状 */
|
|
57
|
+
export type CustomMarkerShape = 'arrow_up' | 'arrow_down' | 'flag' | 'circle' | 'rectangle' | 'diamond'
|
|
58
|
+
|
|
59
|
+
/** 自定义标记样式 */
|
|
60
|
+
export interface CustomMarkerStyle {
|
|
61
|
+
fillColor?: string
|
|
62
|
+
strokeColor?: string
|
|
63
|
+
textColor?: string
|
|
64
|
+
size?: number
|
|
65
|
+
lineWidth?: number
|
|
66
|
+
opacity?: number
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** 自定义标记标签 */
|
|
70
|
+
export interface CustomMarkerLabel {
|
|
71
|
+
text: string
|
|
72
|
+
position?: 'left' | 'right' | 'top' | 'bottom' | 'inside'
|
|
73
|
+
align?: 'start' | 'center' | 'end'
|
|
74
|
+
fontSize?: number
|
|
75
|
+
offset?: { x?: number; y?: number }
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** 自定义标记实体 */
|
|
79
|
+
export interface CustomMarkerEntity {
|
|
80
|
+
id: string
|
|
81
|
+
/**
|
|
82
|
+
* 日期时间字符串
|
|
83
|
+
* - 日K/周K/月K: "YYYY-MM-DD"
|
|
84
|
+
* - 分钟K: "YYYY-MM-DD HH:mm"
|
|
85
|
+
*/
|
|
86
|
+
date: string
|
|
87
|
+
/** Unix 毫秒时间戳(由 date 解析生成,用于二分查找) */
|
|
88
|
+
timestamp: number
|
|
89
|
+
shape: CustomMarkerShape
|
|
90
|
+
groupKey?: string
|
|
91
|
+
offset?: { x?: number; y?: number }
|
|
92
|
+
style?: CustomMarkerStyle
|
|
93
|
+
label?: CustomMarkerLabel
|
|
94
|
+
metadata?: Record<string, unknown>
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* 标记 Manager
|
|
99
|
+
*/
|
|
100
|
+
export class MarkerManager {
|
|
101
|
+
/** 当前帧可见的标记集合(key: marker.id) */
|
|
102
|
+
private markers: Map<string, MarkerEntity> = new Map()
|
|
103
|
+
/** 当前 hover 的标记 ID(跨帧持久) */
|
|
104
|
+
private hoveredMarkerId: string | null = null
|
|
105
|
+
/** 上一帧 hover 的标记 ID(用于触发 enter/leave 事件) */
|
|
106
|
+
private lastHoveredId: string | null = null
|
|
107
|
+
|
|
108
|
+
// ============ 自定义标记状态管理 ============
|
|
109
|
+
/** 自定义标记集合 */
|
|
110
|
+
private customMarkers: Map<string, CustomMarkerEntity> = new Map()
|
|
111
|
+
/** 自定义标记位置缓存(用于 hitTest) */
|
|
112
|
+
private customMarkerPositions: Map<string, { x: number; y: number; size: number; shape: CustomMarkerShape }> = new Map()
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* 清空标记集合
|
|
116
|
+
* 注意:不清除 hoveredMarkerId,保持 hover 状态跨帧持久
|
|
117
|
+
*/
|
|
118
|
+
clear(): void {
|
|
119
|
+
this.markers.clear()
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 注册标记
|
|
124
|
+
* @param marker 标记实体
|
|
125
|
+
*/
|
|
126
|
+
register(marker: MarkerEntity): void {
|
|
127
|
+
this.markers.set(marker.id, marker)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* 获取标记状态
|
|
132
|
+
* @param id 标记 ID
|
|
133
|
+
* @returns 'hovered' 或 'normal'
|
|
134
|
+
*/
|
|
135
|
+
getState(id: string): MarkerState {
|
|
136
|
+
if (this.hoveredMarkerId === id) {
|
|
137
|
+
return 'hovered'
|
|
138
|
+
}
|
|
139
|
+
return 'normal'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 命中测试
|
|
144
|
+
* @param x 鼠标 x 坐标
|
|
145
|
+
* @param y 鼠标 y 坐标
|
|
146
|
+
* @param padding 命中区域扩展(默认 3px)
|
|
147
|
+
* @returns 命中的标记,未命中返回 null
|
|
148
|
+
*/
|
|
149
|
+
hitTest(x: number, y: number, padding: number = 3): MarkerEntity | null {
|
|
150
|
+
for (const marker of this.markers.values()) {
|
|
151
|
+
if (x >= marker.x - padding && x <= marker.x + marker.width + padding &&
|
|
152
|
+
y >= marker.y - padding && y <= marker.y + marker.height + padding
|
|
153
|
+
) {
|
|
154
|
+
return marker
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 设置 hover 状态
|
|
162
|
+
* @param id 标记 ID,null 表示清除 hover
|
|
163
|
+
*/
|
|
164
|
+
setHover(id: string | null): void {
|
|
165
|
+
this.hoveredMarkerId = id
|
|
166
|
+
this.lastHoveredId = id
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 验证 hover 状态
|
|
171
|
+
* 检查当前 hover 的标记是否仍在视口内,不在则清除
|
|
172
|
+
*/
|
|
173
|
+
validateHoverState(): void {
|
|
174
|
+
if (this.hoveredMarkerId !== null && !this.markers.has(this.hoveredMarkerId)) {
|
|
175
|
+
this.hoveredMarkerId = null
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* 获取当前 hover 的标记实体
|
|
181
|
+
* @returns hover 的标记,不存在返回 null
|
|
182
|
+
*/
|
|
183
|
+
getHoveredMarker(): MarkerEntity | null {
|
|
184
|
+
if (this.hoveredMarkerId !== null) {
|
|
185
|
+
return this.markers.get(this.hoveredMarkerId) || null
|
|
186
|
+
}
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* 获取上一帧 hover 的标记 ID
|
|
192
|
+
* 用于检测 hover 状态变化
|
|
193
|
+
* @returns 上一帧的 hover ID
|
|
194
|
+
*/
|
|
195
|
+
getLastHoverId(): string | null {
|
|
196
|
+
return this.lastHoveredId
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 获取所有当前可见的标记
|
|
201
|
+
* @returns 标记数组
|
|
202
|
+
*/
|
|
203
|
+
getAllMarkers(): MarkerEntity[] {
|
|
204
|
+
return Array.from(this.markers.values())
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// ============ 自定义标记管理方法 ============
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* 注册自定义标记
|
|
211
|
+
*/
|
|
212
|
+
registerCustomMarker(marker: CustomMarkerEntity): void {
|
|
213
|
+
this.customMarkers.set(marker.id, marker)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* 批量设置自定义标记
|
|
218
|
+
*/
|
|
219
|
+
setCustomMarkers(markers: CustomMarkerEntity[]): void {
|
|
220
|
+
this.clearCustomMarkers()
|
|
221
|
+
for (const marker of markers) {
|
|
222
|
+
this.customMarkers.set(marker.id, marker)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* 清空自定义标记(含位置缓存)
|
|
228
|
+
*/
|
|
229
|
+
clearCustomMarkers(): void {
|
|
230
|
+
this.customMarkers.clear()
|
|
231
|
+
this.customMarkerPositions.clear()
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* 获取所有自定义标记
|
|
236
|
+
*/
|
|
237
|
+
getCustomMarkers(): CustomMarkerEntity[] {
|
|
238
|
+
return Array.from(this.customMarkers.values())
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 记录自定义标记位置(render 时调用)
|
|
243
|
+
*/
|
|
244
|
+
setCustomMarkerPosition(id: string, x: number, y: number, size: number, shape: CustomMarkerShape): void {
|
|
245
|
+
this.customMarkerPositions.set(id, { x, y, size, shape })
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 自定义标记点击测试
|
|
250
|
+
* @param x 鼠标 x 坐标
|
|
251
|
+
* @param y 鼠标 y 坐标
|
|
252
|
+
* @returns 命中的自定义标记,未命中返回 null
|
|
253
|
+
*/
|
|
254
|
+
hitTestCustomMarker(x: number, y: number): CustomMarkerEntity | null {
|
|
255
|
+
for (const marker of this.customMarkers.values()) {
|
|
256
|
+
const pos = this.customMarkerPositions.get(marker.id)
|
|
257
|
+
if (pos) {
|
|
258
|
+
// 使用实际渲染的大小进行命中测试
|
|
259
|
+
if (hitTestShape(x, y, pos.shape, pos.x, pos.y, pos.size)) {
|
|
260
|
+
return marker
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return null
|
|
265
|
+
}
|
|
266
266
|
}
|