@363045841yyt/klinechart-core 0.7.3 → 0.7.5
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/controllers/index.d.ts +1 -0
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js +1 -0
- package/dist/controllers/index.js.map +1 -1
- package/dist/engine/chart.d.ts +11 -19
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +92 -109
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.d.ts +1 -0
- package/dist/engine/renderers/Indicator/indicatorData.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js +1 -1
- package/dist/engine/renderers/Indicator/indicatorData.js.map +1 -1
- package/dist/engine/renderers/webgl/candleSurface.js +47 -47
- package/dist/engine/subPaneManager.d.ts +4 -0
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +13 -0
- package/dist/engine/subPaneManager.js.map +1 -1
- 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 +20 -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 +2803 -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 +442 -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,260 +1,260 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 像素对齐工具函数 - 逻辑像素空间(配合 ctx.scale(dpr) 使用)
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { getColors } from '../theme/colors'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 将逻辑坐标对齐到物理像素边界(用于矩形填充)
|
|
9
|
-
* @param value - 逻辑坐标值
|
|
10
|
-
* @param dpr - 设备像素比
|
|
11
|
-
* @returns 对齐后的逻辑坐标
|
|
12
|
-
*/
|
|
13
|
-
export function roundToPhysicalPixel(value: number, dpr: number, theme?: 'light' | 'dark'): number {
|
|
14
|
-
return Math.round(value * dpr) / dpr
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* 将逻辑坐标对齐到物理像素中心(用于 1px 线条)
|
|
19
|
-
* @param value - 逻辑坐标值
|
|
20
|
-
* @param dpr - 设备像素比
|
|
21
|
-
* @returns 对齐后的逻辑坐标
|
|
22
|
-
*/
|
|
23
|
-
export function alignToPhysicalPixelCenter(value: number, dpr: number, theme?: 'light' | 'dark'): number {
|
|
24
|
-
return (Math.floor(value * dpr) + 0.5) / dpr
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 对齐矩形到物理像素边界
|
|
29
|
-
* @param x - 矩形左边界 X 坐标
|
|
30
|
-
* @param y - 矩形顶部 Y 坐标
|
|
31
|
-
* @param width - 矩形宽度
|
|
32
|
-
* @param height - 矩形高度
|
|
33
|
-
* @param dpr - 设备像素比
|
|
34
|
-
* @returns 对齐后的矩形信息
|
|
35
|
-
*/
|
|
36
|
-
export function alignRect(
|
|
37
|
-
x: number,
|
|
38
|
-
y: number,
|
|
39
|
-
width: number,
|
|
40
|
-
height: number,
|
|
41
|
-
dpr: number,
|
|
42
|
-
theme?: 'light' | 'dark'
|
|
43
|
-
): { x: number; y: number; width: number; height: number } {
|
|
44
|
-
const alignedX = roundToPhysicalPixel(x, dpr)
|
|
45
|
-
const alignedY = roundToPhysicalPixel(y, dpr)
|
|
46
|
-
const alignedEndX = roundToPhysicalPixel(x + width, dpr)
|
|
47
|
-
const alignedEndY = roundToPhysicalPixel(y + height, dpr)
|
|
48
|
-
|
|
49
|
-
return {
|
|
50
|
-
x: alignedX,
|
|
51
|
-
y: alignedY,
|
|
52
|
-
width: Math.max(1 / dpr, alignedEndX - alignedX),
|
|
53
|
-
height: Math.max(1 / dpr, alignedEndY - alignedY),
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* 创建用于绘制垂直线的矩形(1 物理像素宽)
|
|
59
|
-
* @param centerX - 垂直线中心 X 坐标
|
|
60
|
-
* @param y1 - 垂直线起始点 Y 坐标
|
|
61
|
-
* @param y2 - 垂直线结束点 Y 坐标
|
|
62
|
-
* @param dpr - 设备像素比
|
|
63
|
-
* @returns 对齐到物理像素的矩形信息,如果 y1 和 y2 相等则返回 null
|
|
64
|
-
*/
|
|
65
|
-
export function createVerticalLineRect(
|
|
66
|
-
centerX: number,
|
|
67
|
-
y1: number,
|
|
68
|
-
y2: number,
|
|
69
|
-
dpr: number,
|
|
70
|
-
theme?: 'light' | 'dark'
|
|
71
|
-
): { x: number; y: number; width: number; height: number } | null {
|
|
72
|
-
if (y1 === y2) return null
|
|
73
|
-
|
|
74
|
-
const top = Math.min(y1, y2)
|
|
75
|
-
const bottom = Math.max(y1, y2)
|
|
76
|
-
|
|
77
|
-
// 转换到物理像素空间取整,再转回逻辑像素
|
|
78
|
-
const physX = Math.round(centerX * dpr)
|
|
79
|
-
const physTop = Math.round(top * dpr)
|
|
80
|
-
const physBottom = Math.round(bottom * dpr)
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
x: physX / dpr,
|
|
84
|
-
y: physTop / dpr,
|
|
85
|
-
width: 1 / dpr,
|
|
86
|
-
height: Math.max(1, physBottom - physTop) / dpr,
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* 创建用于绘制水平线的矩形(1 物理像素高)
|
|
92
|
-
* @param x1 - 水平线起始点的 X 坐标
|
|
93
|
-
* @param x2 - 水平线结束点的 X 坐标
|
|
94
|
-
* @param centerY - 水平线中心 Y 坐标
|
|
95
|
-
* @param dpr - 设备像素比
|
|
96
|
-
* @returns 对齐到物理像素的矩形信息,如果 x1 和 x2 相等则返回 null
|
|
97
|
-
*/
|
|
98
|
-
export function createHorizontalLineRect(
|
|
99
|
-
x1: number,
|
|
100
|
-
x2: number,
|
|
101
|
-
centerY: number,
|
|
102
|
-
dpr: number,
|
|
103
|
-
theme?: 'light' | 'dark'
|
|
104
|
-
): { x: number; y: number; width: number; height: number } | null {
|
|
105
|
-
if (x1 === x2) return null
|
|
106
|
-
|
|
107
|
-
const left = Math.min(x1, x2)
|
|
108
|
-
const right = Math.max(x1, x2)
|
|
109
|
-
|
|
110
|
-
const physLeft = Math.round(left * dpr)
|
|
111
|
-
const physRight = Math.round(right * dpr)
|
|
112
|
-
const physY = Math.round(centerY * dpr)
|
|
113
|
-
|
|
114
|
-
return {
|
|
115
|
-
x: physLeft / dpr,
|
|
116
|
-
y: physY / dpr,
|
|
117
|
-
width: Math.max(1, physRight - physLeft) / dpr,
|
|
118
|
-
height: 1 / dpr,
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 创建对齐的K线实体和影线
|
|
124
|
-
* @param rectX - 实体左边界 X 坐标(逻辑像素)
|
|
125
|
-
* @param rectY - 实体顶部 Y 坐标(逻辑像素)
|
|
126
|
-
* @param kWidth - 实体宽度(逻辑像素)
|
|
127
|
-
* @param height - 实体高度(逻辑像素)
|
|
128
|
-
* @param dpr - 设备像素比
|
|
129
|
-
* @returns 对齐后的实体和影线信息
|
|
130
|
-
*/
|
|
131
|
-
export function createAlignedKLine(
|
|
132
|
-
rectX: number,
|
|
133
|
-
rectY: number,
|
|
134
|
-
kWidth: number,
|
|
135
|
-
height: number,
|
|
136
|
-
dpr: number,
|
|
137
|
-
theme?: 'light' | 'dark'
|
|
138
|
-
): {
|
|
139
|
-
bodyRect: { x: number; y: number; width: number; height: number }
|
|
140
|
-
physBodyLeft: number
|
|
141
|
-
physBodyRight: number
|
|
142
|
-
physBodyWidth: number
|
|
143
|
-
physBodyCenter: number
|
|
144
|
-
physWickX: number
|
|
145
|
-
wickRect: { x: number; width: number }
|
|
146
|
-
isPerfectlyAligned: boolean
|
|
147
|
-
} {
|
|
148
|
-
// 1. 统一在物理像素空间计算,避免二次round
|
|
149
|
-
|
|
150
|
-
// 1.1 左边界:round到整数像素列
|
|
151
|
-
const leftPx = Math.round(rectX * dpr)
|
|
152
|
-
|
|
153
|
-
// 1.2 宽度:round到整数,并确保是奇数
|
|
154
|
-
let widthPx = Math.round(kWidth * dpr)
|
|
155
|
-
if (widthPx % 2 === 0) {
|
|
156
|
-
widthPx += 1
|
|
157
|
-
}
|
|
158
|
-
widthPx = Math.max(1, widthPx)
|
|
159
|
-
|
|
160
|
-
// 1.3 右边界:由左边界+宽度决定
|
|
161
|
-
const rightPx = leftPx + widthPx
|
|
162
|
-
|
|
163
|
-
// 1.4 物理宽度
|
|
164
|
-
const physBodyWidth = widthPx
|
|
165
|
-
|
|
166
|
-
// 2. Y轴对齐
|
|
167
|
-
const topPx = Math.round(rectY * dpr)
|
|
168
|
-
const bottomPx = Math.round((rectY + height) * dpr)
|
|
169
|
-
const heightPx = Math.max(1, bottomPx - topPx)
|
|
170
|
-
|
|
171
|
-
// 3. 计算物理中心和影线位置
|
|
172
|
-
const physWickX = leftPx + (widthPx - 1) / 2
|
|
173
|
-
const physBodyCenter = physWickX
|
|
174
|
-
const isPerfectlyAligned = physBodyWidth % 2 === 1
|
|
175
|
-
|
|
176
|
-
// 4. 返回逻辑像素坐标
|
|
177
|
-
return {
|
|
178
|
-
bodyRect: {
|
|
179
|
-
x: leftPx / dpr,
|
|
180
|
-
y: topPx / dpr,
|
|
181
|
-
width: widthPx / dpr,
|
|
182
|
-
height: heightPx / dpr,
|
|
183
|
-
},
|
|
184
|
-
physBodyLeft: leftPx,
|
|
185
|
-
physBodyRight: rightPx,
|
|
186
|
-
physBodyWidth,
|
|
187
|
-
physBodyCenter,
|
|
188
|
-
physWickX,
|
|
189
|
-
wickRect: {
|
|
190
|
-
x: physWickX / dpr,
|
|
191
|
-
width: 1 / dpr,
|
|
192
|
-
},
|
|
193
|
-
isPerfectlyAligned,
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* 创建对齐的K线实体和影线(物理像素直接版)
|
|
199
|
-
* @param leftPx - 实体左边界物理像素坐标(整数)
|
|
200
|
-
* @param rectY - 实体顶部 Y 坐标(逻辑像素)
|
|
201
|
-
* @param widthPx - 实体宽度物理像素(奇数)
|
|
202
|
-
* @param height - 实体高度(逻辑像素)
|
|
203
|
-
* @param dpr - 设备像素比
|
|
204
|
-
* @returns 对齐后的实体和影线信息
|
|
205
|
-
*/
|
|
206
|
-
export function createAlignedKLineFromPx(
|
|
207
|
-
leftPx: number,
|
|
208
|
-
rectY: number,
|
|
209
|
-
widthPx: number,
|
|
210
|
-
height: number,
|
|
211
|
-
dpr: number,
|
|
212
|
-
theme?: 'light' | 'dark'
|
|
213
|
-
): {
|
|
214
|
-
bodyRect: { x: number; y: number; width: number; height: number }
|
|
215
|
-
physBodyLeft: number
|
|
216
|
-
physBodyRight: number
|
|
217
|
-
physBodyWidth: number
|
|
218
|
-
physBodyCenter: number
|
|
219
|
-
physWickX: number
|
|
220
|
-
wickRect: { x: number; width: number }
|
|
221
|
-
isPerfectlyAligned: boolean
|
|
222
|
-
} {
|
|
223
|
-
// 1. 物理像素空间计算
|
|
224
|
-
|
|
225
|
-
// 1.1 左边界直接使用传入的整数
|
|
226
|
-
// 1.2 宽度直接使用传入的奇数
|
|
227
|
-
// 1.3 右边界由左边界+宽度决定
|
|
228
|
-
const rightPx = leftPx + widthPx
|
|
229
|
-
const physBodyWidth = widthPx
|
|
230
|
-
|
|
231
|
-
// 2. Y轴对齐
|
|
232
|
-
const topPx = Math.round(rectY * dpr)
|
|
233
|
-
const bottomPx = Math.round((rectY + height) * dpr)
|
|
234
|
-
const heightPx = Math.max(1, bottomPx - topPx)
|
|
235
|
-
|
|
236
|
-
// 3. 计算影线位置
|
|
237
|
-
const physWickX = leftPx + (widthPx - 1) / 2
|
|
238
|
-
const physBodyCenter = physWickX
|
|
239
|
-
const isPerfectlyAligned = physBodyWidth % 2 === 1
|
|
240
|
-
|
|
241
|
-
// 4. 返回逻辑像素坐标
|
|
242
|
-
return {
|
|
243
|
-
bodyRect: {
|
|
244
|
-
x: leftPx / dpr,
|
|
245
|
-
y: topPx / dpr,
|
|
246
|
-
width: widthPx / dpr,
|
|
247
|
-
height: heightPx / dpr,
|
|
248
|
-
},
|
|
249
|
-
physBodyLeft: leftPx,
|
|
250
|
-
physBodyRight: rightPx,
|
|
251
|
-
physBodyWidth,
|
|
252
|
-
physBodyCenter,
|
|
253
|
-
physWickX,
|
|
254
|
-
wickRect: {
|
|
255
|
-
x: physWickX / dpr,
|
|
256
|
-
width: 1 / dpr,
|
|
257
|
-
},
|
|
258
|
-
isPerfectlyAligned,
|
|
259
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 像素对齐工具函数 - 逻辑像素空间(配合 ctx.scale(dpr) 使用)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { getColors } from '../theme/colors'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 将逻辑坐标对齐到物理像素边界(用于矩形填充)
|
|
9
|
+
* @param value - 逻辑坐标值
|
|
10
|
+
* @param dpr - 设备像素比
|
|
11
|
+
* @returns 对齐后的逻辑坐标
|
|
12
|
+
*/
|
|
13
|
+
export function roundToPhysicalPixel(value: number, dpr: number, theme?: 'light' | 'dark'): number {
|
|
14
|
+
return Math.round(value * dpr) / dpr
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 将逻辑坐标对齐到物理像素中心(用于 1px 线条)
|
|
19
|
+
* @param value - 逻辑坐标值
|
|
20
|
+
* @param dpr - 设备像素比
|
|
21
|
+
* @returns 对齐后的逻辑坐标
|
|
22
|
+
*/
|
|
23
|
+
export function alignToPhysicalPixelCenter(value: number, dpr: number, theme?: 'light' | 'dark'): number {
|
|
24
|
+
return (Math.floor(value * dpr) + 0.5) / dpr
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 对齐矩形到物理像素边界
|
|
29
|
+
* @param x - 矩形左边界 X 坐标
|
|
30
|
+
* @param y - 矩形顶部 Y 坐标
|
|
31
|
+
* @param width - 矩形宽度
|
|
32
|
+
* @param height - 矩形高度
|
|
33
|
+
* @param dpr - 设备像素比
|
|
34
|
+
* @returns 对齐后的矩形信息
|
|
35
|
+
*/
|
|
36
|
+
export function alignRect(
|
|
37
|
+
x: number,
|
|
38
|
+
y: number,
|
|
39
|
+
width: number,
|
|
40
|
+
height: number,
|
|
41
|
+
dpr: number,
|
|
42
|
+
theme?: 'light' | 'dark'
|
|
43
|
+
): { x: number; y: number; width: number; height: number } {
|
|
44
|
+
const alignedX = roundToPhysicalPixel(x, dpr)
|
|
45
|
+
const alignedY = roundToPhysicalPixel(y, dpr)
|
|
46
|
+
const alignedEndX = roundToPhysicalPixel(x + width, dpr)
|
|
47
|
+
const alignedEndY = roundToPhysicalPixel(y + height, dpr)
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
x: alignedX,
|
|
51
|
+
y: alignedY,
|
|
52
|
+
width: Math.max(1 / dpr, alignedEndX - alignedX),
|
|
53
|
+
height: Math.max(1 / dpr, alignedEndY - alignedY),
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 创建用于绘制垂直线的矩形(1 物理像素宽)
|
|
59
|
+
* @param centerX - 垂直线中心 X 坐标
|
|
60
|
+
* @param y1 - 垂直线起始点 Y 坐标
|
|
61
|
+
* @param y2 - 垂直线结束点 Y 坐标
|
|
62
|
+
* @param dpr - 设备像素比
|
|
63
|
+
* @returns 对齐到物理像素的矩形信息,如果 y1 和 y2 相等则返回 null
|
|
64
|
+
*/
|
|
65
|
+
export function createVerticalLineRect(
|
|
66
|
+
centerX: number,
|
|
67
|
+
y1: number,
|
|
68
|
+
y2: number,
|
|
69
|
+
dpr: number,
|
|
70
|
+
theme?: 'light' | 'dark'
|
|
71
|
+
): { x: number; y: number; width: number; height: number } | null {
|
|
72
|
+
if (y1 === y2) return null
|
|
73
|
+
|
|
74
|
+
const top = Math.min(y1, y2)
|
|
75
|
+
const bottom = Math.max(y1, y2)
|
|
76
|
+
|
|
77
|
+
// 转换到物理像素空间取整,再转回逻辑像素
|
|
78
|
+
const physX = Math.round(centerX * dpr)
|
|
79
|
+
const physTop = Math.round(top * dpr)
|
|
80
|
+
const physBottom = Math.round(bottom * dpr)
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
x: physX / dpr,
|
|
84
|
+
y: physTop / dpr,
|
|
85
|
+
width: 1 / dpr,
|
|
86
|
+
height: Math.max(1, physBottom - physTop) / dpr,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 创建用于绘制水平线的矩形(1 物理像素高)
|
|
92
|
+
* @param x1 - 水平线起始点的 X 坐标
|
|
93
|
+
* @param x2 - 水平线结束点的 X 坐标
|
|
94
|
+
* @param centerY - 水平线中心 Y 坐标
|
|
95
|
+
* @param dpr - 设备像素比
|
|
96
|
+
* @returns 对齐到物理像素的矩形信息,如果 x1 和 x2 相等则返回 null
|
|
97
|
+
*/
|
|
98
|
+
export function createHorizontalLineRect(
|
|
99
|
+
x1: number,
|
|
100
|
+
x2: number,
|
|
101
|
+
centerY: number,
|
|
102
|
+
dpr: number,
|
|
103
|
+
theme?: 'light' | 'dark'
|
|
104
|
+
): { x: number; y: number; width: number; height: number } | null {
|
|
105
|
+
if (x1 === x2) return null
|
|
106
|
+
|
|
107
|
+
const left = Math.min(x1, x2)
|
|
108
|
+
const right = Math.max(x1, x2)
|
|
109
|
+
|
|
110
|
+
const physLeft = Math.round(left * dpr)
|
|
111
|
+
const physRight = Math.round(right * dpr)
|
|
112
|
+
const physY = Math.round(centerY * dpr)
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
x: physLeft / dpr,
|
|
116
|
+
y: physY / dpr,
|
|
117
|
+
width: Math.max(1, physRight - physLeft) / dpr,
|
|
118
|
+
height: 1 / dpr,
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 创建对齐的K线实体和影线
|
|
124
|
+
* @param rectX - 实体左边界 X 坐标(逻辑像素)
|
|
125
|
+
* @param rectY - 实体顶部 Y 坐标(逻辑像素)
|
|
126
|
+
* @param kWidth - 实体宽度(逻辑像素)
|
|
127
|
+
* @param height - 实体高度(逻辑像素)
|
|
128
|
+
* @param dpr - 设备像素比
|
|
129
|
+
* @returns 对齐后的实体和影线信息
|
|
130
|
+
*/
|
|
131
|
+
export function createAlignedKLine(
|
|
132
|
+
rectX: number,
|
|
133
|
+
rectY: number,
|
|
134
|
+
kWidth: number,
|
|
135
|
+
height: number,
|
|
136
|
+
dpr: number,
|
|
137
|
+
theme?: 'light' | 'dark'
|
|
138
|
+
): {
|
|
139
|
+
bodyRect: { x: number; y: number; width: number; height: number }
|
|
140
|
+
physBodyLeft: number
|
|
141
|
+
physBodyRight: number
|
|
142
|
+
physBodyWidth: number
|
|
143
|
+
physBodyCenter: number
|
|
144
|
+
physWickX: number
|
|
145
|
+
wickRect: { x: number; width: number }
|
|
146
|
+
isPerfectlyAligned: boolean
|
|
147
|
+
} {
|
|
148
|
+
// 1. 统一在物理像素空间计算,避免二次round
|
|
149
|
+
|
|
150
|
+
// 1.1 左边界:round到整数像素列
|
|
151
|
+
const leftPx = Math.round(rectX * dpr)
|
|
152
|
+
|
|
153
|
+
// 1.2 宽度:round到整数,并确保是奇数
|
|
154
|
+
let widthPx = Math.round(kWidth * dpr)
|
|
155
|
+
if (widthPx % 2 === 0) {
|
|
156
|
+
widthPx += 1
|
|
157
|
+
}
|
|
158
|
+
widthPx = Math.max(1, widthPx)
|
|
159
|
+
|
|
160
|
+
// 1.3 右边界:由左边界+宽度决定
|
|
161
|
+
const rightPx = leftPx + widthPx
|
|
162
|
+
|
|
163
|
+
// 1.4 物理宽度
|
|
164
|
+
const physBodyWidth = widthPx
|
|
165
|
+
|
|
166
|
+
// 2. Y轴对齐
|
|
167
|
+
const topPx = Math.round(rectY * dpr)
|
|
168
|
+
const bottomPx = Math.round((rectY + height) * dpr)
|
|
169
|
+
const heightPx = Math.max(1, bottomPx - topPx)
|
|
170
|
+
|
|
171
|
+
// 3. 计算物理中心和影线位置
|
|
172
|
+
const physWickX = leftPx + (widthPx - 1) / 2
|
|
173
|
+
const physBodyCenter = physWickX
|
|
174
|
+
const isPerfectlyAligned = physBodyWidth % 2 === 1
|
|
175
|
+
|
|
176
|
+
// 4. 返回逻辑像素坐标
|
|
177
|
+
return {
|
|
178
|
+
bodyRect: {
|
|
179
|
+
x: leftPx / dpr,
|
|
180
|
+
y: topPx / dpr,
|
|
181
|
+
width: widthPx / dpr,
|
|
182
|
+
height: heightPx / dpr,
|
|
183
|
+
},
|
|
184
|
+
physBodyLeft: leftPx,
|
|
185
|
+
physBodyRight: rightPx,
|
|
186
|
+
physBodyWidth,
|
|
187
|
+
physBodyCenter,
|
|
188
|
+
physWickX,
|
|
189
|
+
wickRect: {
|
|
190
|
+
x: physWickX / dpr,
|
|
191
|
+
width: 1 / dpr,
|
|
192
|
+
},
|
|
193
|
+
isPerfectlyAligned,
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 创建对齐的K线实体和影线(物理像素直接版)
|
|
199
|
+
* @param leftPx - 实体左边界物理像素坐标(整数)
|
|
200
|
+
* @param rectY - 实体顶部 Y 坐标(逻辑像素)
|
|
201
|
+
* @param widthPx - 实体宽度物理像素(奇数)
|
|
202
|
+
* @param height - 实体高度(逻辑像素)
|
|
203
|
+
* @param dpr - 设备像素比
|
|
204
|
+
* @returns 对齐后的实体和影线信息
|
|
205
|
+
*/
|
|
206
|
+
export function createAlignedKLineFromPx(
|
|
207
|
+
leftPx: number,
|
|
208
|
+
rectY: number,
|
|
209
|
+
widthPx: number,
|
|
210
|
+
height: number,
|
|
211
|
+
dpr: number,
|
|
212
|
+
theme?: 'light' | 'dark'
|
|
213
|
+
): {
|
|
214
|
+
bodyRect: { x: number; y: number; width: number; height: number }
|
|
215
|
+
physBodyLeft: number
|
|
216
|
+
physBodyRight: number
|
|
217
|
+
physBodyWidth: number
|
|
218
|
+
physBodyCenter: number
|
|
219
|
+
physWickX: number
|
|
220
|
+
wickRect: { x: number; width: number }
|
|
221
|
+
isPerfectlyAligned: boolean
|
|
222
|
+
} {
|
|
223
|
+
// 1. 物理像素空间计算
|
|
224
|
+
|
|
225
|
+
// 1.1 左边界直接使用传入的整数
|
|
226
|
+
// 1.2 宽度直接使用传入的奇数
|
|
227
|
+
// 1.3 右边界由左边界+宽度决定
|
|
228
|
+
const rightPx = leftPx + widthPx
|
|
229
|
+
const physBodyWidth = widthPx
|
|
230
|
+
|
|
231
|
+
// 2. Y轴对齐
|
|
232
|
+
const topPx = Math.round(rectY * dpr)
|
|
233
|
+
const bottomPx = Math.round((rectY + height) * dpr)
|
|
234
|
+
const heightPx = Math.max(1, bottomPx - topPx)
|
|
235
|
+
|
|
236
|
+
// 3. 计算影线位置
|
|
237
|
+
const physWickX = leftPx + (widthPx - 1) / 2
|
|
238
|
+
const physBodyCenter = physWickX
|
|
239
|
+
const isPerfectlyAligned = physBodyWidth % 2 === 1
|
|
240
|
+
|
|
241
|
+
// 4. 返回逻辑像素坐标
|
|
242
|
+
return {
|
|
243
|
+
bodyRect: {
|
|
244
|
+
x: leftPx / dpr,
|
|
245
|
+
y: topPx / dpr,
|
|
246
|
+
width: widthPx / dpr,
|
|
247
|
+
height: heightPx / dpr,
|
|
248
|
+
},
|
|
249
|
+
physBodyLeft: leftPx,
|
|
250
|
+
physBodyRight: rightPx,
|
|
251
|
+
physBodyWidth,
|
|
252
|
+
physBodyCenter,
|
|
253
|
+
physWickX,
|
|
254
|
+
wickRect: {
|
|
255
|
+
x: physWickX / dpr,
|
|
256
|
+
width: 1 / dpr,
|
|
257
|
+
},
|
|
258
|
+
isPerfectlyAligned,
|
|
259
|
+
}
|
|
260
260
|
}
|