@363045841yyt/klinechart-core 0.9.0-alpha.2 → 0.9.0-alpha.4
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/createChartController.d.ts.map +1 -1
- package/dist/controllers/createChartController.js +9 -8
- package/dist/controllers/createChartController.js.map +1 -1
- package/dist/controllers/index.d.ts +1 -0
- package/dist/controllers/index.d.ts.map +1 -1
- package/dist/controllers/index.js.map +1 -1
- package/dist/controllers/types.d.ts +5 -0
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/data/binance.d.ts +1 -1
- package/dist/data/binance.d.ts.map +1 -1
- package/dist/data/binance.js +1 -1
- package/dist/data/binance.js.map +1 -1
- package/dist/data/timeShareBuffer.d.ts +3 -0
- package/dist/data/timeShareBuffer.d.ts.map +1 -1
- package/dist/data/timeShareBuffer.js +13 -0
- package/dist/data/timeShareBuffer.js.map +1 -1
- package/dist/engine/chart.d.ts +9 -9
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +87 -101
- package/dist/engine/chart.js.map +1 -1
- package/dist/engine/chartTypes.d.ts +5 -0
- package/dist/engine/chartTypes.d.ts.map +1 -1
- package/dist/engine/controller/interaction.d.ts +4 -2
- package/dist/engine/controller/interaction.d.ts.map +1 -1
- package/dist/engine/controller/interaction.js +18 -10
- package/dist/engine/controller/interaction.js.map +1 -1
- package/dist/engine/data/chartDataManager.d.ts +14 -18
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +55 -37
- package/dist/engine/data/chartDataManager.js.map +1 -1
- package/dist/engine/data/incrementalLoadHint.d.ts +2 -4
- package/dist/engine/data/incrementalLoadHint.d.ts.map +1 -1
- package/dist/engine/data/incrementalLoadHint.js +5 -2
- package/dist/engine/data/incrementalLoadHint.js.map +1 -1
- package/dist/engine/data/scrollCompensator.d.ts +3 -13
- package/dist/engine/data/scrollCompensator.d.ts.map +1 -1
- package/dist/engine/data/scrollCompensator.js +13 -14
- package/dist/engine/data/scrollCompensator.js.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.d.ts +16 -17
- package/dist/engine/indicators/chartIndicatorManager.d.ts.map +1 -1
- package/dist/engine/indicators/chartIndicatorManager.js +37 -37
- package/dist/engine/indicators/chartIndicatorManager.js.map +1 -1
- package/dist/engine/layout/chartPaneLayout.d.ts +11 -7
- package/dist/engine/layout/chartPaneLayout.d.ts.map +1 -1
- package/dist/engine/layout/chartPaneLayout.js +58 -16
- package/dist/engine/layout/chartPaneLayout.js.map +1 -1
- package/dist/engine/modes/timeShareMath.d.ts +56 -0
- package/dist/engine/modes/timeShareMath.d.ts.map +1 -0
- package/dist/engine/modes/timeShareMath.js +90 -0
- package/dist/engine/modes/timeShareMath.js.map +1 -0
- package/dist/engine/modes/timeShareMode.d.ts +5 -0
- package/dist/engine/modes/timeShareMode.d.ts.map +1 -1
- package/dist/engine/modes/timeShareMode.js +27 -27
- package/dist/engine/modes/timeShareMode.js.map +1 -1
- package/dist/engine/paneRenderer.d.ts +2 -0
- package/dist/engine/paneRenderer.d.ts.map +1 -1
- package/dist/engine/paneRenderer.js +15 -5
- package/dist/engine/paneRenderer.js.map +1 -1
- package/dist/engine/render/chartRenderer.d.ts +28 -22
- package/dist/engine/render/chartRenderer.d.ts.map +1 -1
- package/dist/engine/render/chartRenderer.js +143 -85
- package/dist/engine/render/chartRenderer.js.map +1 -1
- package/dist/engine/render/layers/leftYAxisLayer.d.ts +9 -2
- package/dist/engine/render/layers/leftYAxisLayer.d.ts.map +1 -1
- package/dist/engine/render/layers/leftYAxisLayer.js +11 -2
- package/dist/engine/render/layers/leftYAxisLayer.js.map +1 -1
- package/dist/engine/render/layers/mainIndicatorLegendLayer.d.ts +6 -4
- package/dist/engine/render/layers/mainIndicatorLegendLayer.d.ts.map +1 -1
- package/dist/engine/render/layers/mainIndicatorLegendLayer.js +6 -9
- package/dist/engine/render/layers/mainIndicatorLegendLayer.js.map +1 -1
- package/dist/engine/render/layers/mainIndicatorLegendLayer.test.d.ts +2 -0
- package/dist/engine/render/layers/mainIndicatorLegendLayer.test.d.ts.map +1 -0
- package/dist/engine/render/layers/mainIndicatorLegendLayer.test.js +19 -0
- package/dist/engine/render/layers/mainIndicatorLegendLayer.test.js.map +1 -0
- package/dist/engine/render/layers/yAxisLayer.d.ts +9 -2
- package/dist/engine/render/layers/yAxisLayer.d.ts.map +1 -1
- package/dist/engine/render/layers/yAxisLayer.js +11 -2
- package/dist/engine/render/layers/yAxisLayer.js.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.d.ts +7 -3
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.d.ts.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js +234 -330
- package/dist/engine/renderers/Indicator/mainIndicatorLegend.js.map +1 -1
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.d.ts +73 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.d.ts.map +1 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.js +182 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.js.map +1 -0
- package/dist/engine/renderers/leftYAxis.d.ts +15 -2
- package/dist/engine/renderers/leftYAxis.d.ts.map +1 -1
- package/dist/engine/renderers/leftYAxis.js +56 -16
- package/dist/engine/renderers/leftYAxis.js.map +1 -1
- package/dist/engine/renderers/timeShare.d.ts.map +1 -1
- package/dist/engine/renderers/timeShare.js +20 -9
- package/dist/engine/renderers/timeShare.js.map +1 -1
- package/dist/engine/renderers/yAxis.d.ts +16 -6
- package/dist/engine/renderers/yAxis.d.ts.map +1 -1
- package/dist/engine/renderers/yAxis.js +49 -16
- package/dist/engine/renderers/yAxis.js.map +1 -1
- package/dist/engine/state/viewportState.d.ts +4 -1
- package/dist/engine/state/viewportState.d.ts.map +1 -1
- package/dist/engine/state/viewportState.js +40 -8
- package/dist/engine/state/viewportState.js.map +1 -1
- package/dist/engine/subPaneManager.d.ts +5 -3
- package/dist/engine/subPaneManager.d.ts.map +1 -1
- package/dist/engine/subPaneManager.js +3 -2
- package/dist/engine/subPaneManager.js.map +1 -1
- package/dist/engine/utils/chartZoomController.d.ts +9 -7
- package/dist/engine/utils/chartZoomController.d.ts.map +1 -1
- package/dist/engine/utils/chartZoomController.js +13 -12
- package/dist/engine/utils/chartZoomController.js.map +1 -1
- package/dist/engine/viewport/chartViewportManager.d.ts +5 -16
- package/dist/engine/viewport/chartViewportManager.d.ts.map +1 -1
- package/dist/engine/viewport/chartViewportManager.js +7 -48
- package/dist/engine/viewport/chartViewportManager.js.map +1 -1
- package/dist/engine/viewport/viewport.d.ts +14 -0
- package/dist/engine/viewport/viewport.d.ts.map +1 -1
- package/dist/engine/viewport/viewport.js +10 -0
- package/dist/engine/viewport/viewport.js.map +1 -1
- package/dist/foundation/config/chartSettings.d.ts +0 -5
- package/dist/foundation/config/chartSettings.d.ts.map +1 -1
- package/dist/foundation/config/chartSettings.js +14 -0
- package/dist/foundation/config/chartSettings.js.map +1 -1
- package/dist/foundation/plugin/rendererPluginManager.test.js +15 -0
- package/dist/foundation/plugin/rendererPluginManager.test.js.map +1 -1
- package/dist/foundation/plugin/types.d.ts +3 -0
- package/dist/foundation/plugin/types.d.ts.map +1 -1
- package/dist/foundation/plugin/types.js.map +1 -1
- package/dist/foundation/reactivity/frameTransaction.d.ts +11 -0
- package/dist/foundation/reactivity/frameTransaction.d.ts.map +1 -1
- package/dist/foundation/reactivity/frameTransaction.js +17 -2
- package/dist/foundation/reactivity/frameTransaction.js.map +1 -1
- package/dist/foundation/utils/kLineDraw/axis.d.ts +3 -0
- package/dist/foundation/utils/kLineDraw/axis.d.ts.map +1 -1
- package/dist/foundation/utils/kLineDraw/axis.js +40 -9
- package/dist/foundation/utils/kLineDraw/axis.js.map +1 -1
- package/dist/foundation/utils/sessionTimeLabels.d.ts +59 -0
- package/dist/foundation/utils/sessionTimeLabels.d.ts.map +1 -0
- package/dist/foundation/utils/sessionTimeLabels.js +170 -0
- package/dist/foundation/utils/sessionTimeLabels.js.map +1 -0
- package/dist/foundation/utils/timeShareAxisLabels.d.ts +27 -0
- package/dist/foundation/utils/timeShareAxisLabels.d.ts.map +1 -0
- package/dist/foundation/utils/timeShareAxisLabels.js +45 -0
- package/dist/foundation/utils/timeShareAxisLabels.js.map +1 -0
- package/dist/rendering/render/Renderer.d.ts +58 -74
- package/dist/rendering/render/Renderer.d.ts.map +1 -1
- package/dist/rendering/render/Renderer.js +8 -18
- package/dist/rendering/render/Renderer.js.map +1 -1
- package/dist/rendering/render/createWebGPURenderer.d.ts.map +1 -1
- package/dist/rendering/render/createWebGPURenderer.js +30 -17
- package/dist/rendering/render/createWebGPURenderer.js.map +1 -1
- package/dist/rendering/render/createWebGPUSurfaceBackend.js +3 -3
- package/dist/rendering/render/createWebGPUSurfaceBackend.js.map +1 -1
- package/dist/rendering/render/physicalLine.d.ts +4 -0
- package/dist/rendering/render/physicalLine.d.ts.map +1 -0
- package/dist/rendering/render/physicalLine.js +37 -0
- package/dist/rendering/render/physicalLine.js.map +1 -0
- package/dist/rendering/render/physicalRegion.d.ts +14 -0
- package/dist/rendering/render/physicalRegion.d.ts.map +1 -0
- package/dist/rendering/render/physicalRegion.js +15 -0
- package/dist/rendering/render/physicalRegion.js.map +1 -0
- package/dist/rendering/scene/createLayerFromPlugin.d.ts.map +1 -1
- package/dist/rendering/scene/createLayerFromPlugin.js +8 -3
- package/dist/rendering/scene/createLayerFromPlugin.js.map +1 -1
- package/dist/rendering/scene/createScene.d.ts.map +1 -1
- package/dist/rendering/scene/createScene.js +4 -3
- package/dist/rendering/scene/createScene.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/src/__tests__/stateKernel.test.ts +1 -0
- package/src/controllers/createChartController.ts +9 -8
- package/src/controllers/index.ts +11 -0
- package/src/controllers/types.ts +7 -0
- package/src/data/__tests__/timeShareBuffer.test.ts +45 -0
- package/src/data/binance.ts +1 -1
- package/src/data/timeShareBuffer.ts +15 -0
- package/src/engine/__tests__/chart.dpr.test.ts +31 -2
- package/src/engine/__tests__/paneRenderer.resize.test.ts +52 -54
- package/src/engine/__tests__/subPaneManager.test.ts +5 -3
- package/src/engine/chart.ts +105 -115
- package/src/engine/chartTypes.ts +5 -0
- package/src/engine/controller/__tests__/interaction.dpr.test.ts +39 -2
- package/src/engine/controller/interaction.ts +18 -10
- package/src/engine/data/__tests__/chartDataManager.incrementalLoad.test.ts +37 -17
- package/src/engine/data/__tests__/scrollCompensator.geometry.test.ts +87 -75
- package/src/engine/data/chartDataManager.ts +64 -59
- package/src/engine/data/incrementalLoadHint.ts +8 -7
- package/src/engine/data/scrollCompensator.ts +16 -24
- package/src/engine/indicators/__tests__/chartIndicatorManager.test.ts +18 -26
- package/src/engine/indicators/chartIndicatorManager.ts +62 -62
- package/src/engine/layout/chartPaneLayout.ts +73 -21
- package/src/engine/modes/__tests__/timeShareMath.test.ts +185 -0
- package/src/engine/modes/__tests__/timeShareMode.test.ts +81 -0
- package/src/engine/modes/timeShareMath.ts +150 -0
- package/src/engine/modes/timeShareMode.ts +35 -28
- package/src/engine/paneRenderer.ts +17 -10
- package/src/engine/render/chartRenderer.ts +214 -145
- package/src/engine/render/layers/leftYAxisLayer.ts +29 -7
- package/src/engine/render/layers/mainIndicatorLegendLayer.test.ts +26 -0
- package/src/engine/render/layers/mainIndicatorLegendLayer.ts +13 -10
- package/src/engine/render/layers/yAxisLayer.ts +29 -7
- package/src/engine/renderers/Indicator/mainIndicatorLegend.ts +270 -403
- package/src/engine/renderers/Indicator/mainIndicatorLegendContext.ts +290 -0
- package/src/engine/renderers/__tests__/mainIndicatorLegend.renderer.test.ts +73 -2
- package/src/engine/renderers/__tests__/yAxis.renderer.test.ts +10 -6
- package/src/engine/renderers/leftYAxis.ts +60 -18
- package/src/engine/renderers/timeShare.ts +25 -9
- package/src/engine/renderers/yAxis.ts +57 -22
- package/src/engine/state/__tests__/settingsState.test.ts +9 -0
- package/src/engine/state/viewportState.ts +44 -8
- package/src/engine/subPaneManager.ts +8 -5
- package/src/engine/utils/chartZoomController.ts +22 -19
- package/src/engine/viewport/__tests__/visibleRange.clamp.test.ts +50 -0
- package/src/engine/viewport/chartViewportManager.ts +9 -60
- package/src/engine/viewport/viewport.ts +14 -0
- package/src/foundation/config/chartSettings.ts +13 -0
- package/src/foundation/plugin/rendererPluginManager.test.ts +18 -0
- package/src/foundation/plugin/types.ts +3 -0
- package/src/foundation/reactivity/frameTransaction.ts +20 -6
- package/src/foundation/utils/__tests__/sessionTimeLabels.test.ts +91 -0
- package/src/foundation/utils/kLineDraw/axis.ts +50 -9
- package/src/foundation/utils/sessionTimeLabels.ts +237 -0
- package/src/foundation/utils/timeShareAxisLabels.ts +94 -0
- package/src/rendering/render/Renderer.ts +69 -85
- package/src/rendering/render/__tests__/physicalLine.test.ts +51 -0
- package/src/rendering/render/__tests__/physicalRegion.test.ts +23 -0
- package/src/rendering/render/__tests__/webgpuRenderer.test.ts +31 -1
- package/src/rendering/render/__tests__/webgpuSurfaceBackend.test.ts +11 -0
- package/src/rendering/render/createWebGPURenderer.ts +30 -17
- package/src/rendering/render/createWebGPUSurfaceBackend.ts +3 -3
- package/src/rendering/render/physicalLine.ts +45 -0
- package/src/rendering/render/physicalRegion.ts +32 -0
- package/src/rendering/scene/createLayerFromPlugin.ts +8 -3
- package/src/rendering/scene/createScene.ts +4 -3
- package/src/version.ts +1 -1
|
@@ -2,10 +2,12 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
2
2
|
import { JSDOM } from 'jsdom'
|
|
3
3
|
|
|
4
4
|
import type { DataFetcher, KLineData, SymbolSpec } from '../../../controllers/types'
|
|
5
|
-
import {
|
|
5
|
+
import { createSignal } from '../../../foundation/reactivity/signal'
|
|
6
6
|
import type { ChartDom } from '../../chartTypes'
|
|
7
|
+
import { createComparisonState } from '../../state/comparisonState'
|
|
7
8
|
import { createDataManagerState } from '../../state/dataManagerState'
|
|
8
9
|
import { createDataState } from '../../state/dataState'
|
|
10
|
+
import type { ViewportStateModule } from '../../state/viewportState'
|
|
9
11
|
import { ChartDataManager, type DataDependencies } from '../chartDataManager'
|
|
10
12
|
|
|
11
13
|
const MS_PER_DAY = 86_400_000
|
|
@@ -21,26 +23,48 @@ function makeKLine(timestamp: number): KLineData {
|
|
|
21
23
|
}
|
|
22
24
|
}
|
|
23
25
|
|
|
26
|
+
function createMockViewport(scrollLeft = 800): ViewportStateModule {
|
|
27
|
+
let scroll = scrollLeft
|
|
28
|
+
return {
|
|
29
|
+
readonly: {
|
|
30
|
+
dpr: { peek: () => 1 },
|
|
31
|
+
scrollLeft: { peek: () => scroll },
|
|
32
|
+
scrollLeftLogical: { peek: () => scroll },
|
|
33
|
+
leftLoadBufferWidth: { peek: () => 800 },
|
|
34
|
+
contentWidth: { peek: () => 1600 },
|
|
35
|
+
viewWidth: { peek: () => 800 },
|
|
36
|
+
viewHeight: { peek: () => 600 },
|
|
37
|
+
visibleRange: { peek: () => ({ start: 0, end: 0 }) },
|
|
38
|
+
rawVisibleRange: { peek: () => ({ start: 0, end: 0 }) },
|
|
39
|
+
viewport: {
|
|
40
|
+
peek: () => ({
|
|
41
|
+
viewWidth: 800,
|
|
42
|
+
viewHeight: 600,
|
|
43
|
+
plotWidth: 800,
|
|
44
|
+
plotHeight: 600,
|
|
45
|
+
scrollLeft: scroll,
|
|
46
|
+
dpr: 1,
|
|
47
|
+
}),
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
actions: {
|
|
51
|
+
scrollTo: (v: number) => {
|
|
52
|
+
scroll = v
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
} as unknown as ViewportStateModule
|
|
56
|
+
}
|
|
57
|
+
|
|
24
58
|
function createDependencies(
|
|
25
59
|
dom: ChartDom,
|
|
26
60
|
setSymbols: (symbols: ReadonlyArray<SymbolSpec>) => void,
|
|
27
61
|
symbols$: ReturnType<typeof createSignal<ReadonlyArray<SymbolSpec>>>,
|
|
28
62
|
): DataDependencies {
|
|
29
|
-
let scrollLeft = 800
|
|
30
63
|
return {
|
|
31
64
|
getOption: () => ({ kWidth: 8, kGap: 2 }),
|
|
32
|
-
getEffectiveDpr: () => 1,
|
|
33
|
-
getLogicalScrollLeft: () => scrollLeft,
|
|
34
|
-
getCachedScrollLeft: () => scrollLeft,
|
|
35
|
-
setScrollLeft: (value) => {
|
|
36
|
-
scrollLeft = value
|
|
37
|
-
},
|
|
38
65
|
getDom: () => dom,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
getVisibleRange: () => null,
|
|
42
|
-
getLeftLoadBufferWidth: () => 800,
|
|
43
|
-
getContentWidth: () => 1600,
|
|
66
|
+
viewport: createMockViewport(),
|
|
67
|
+
comparison: createComparisonState({ symbols$ }),
|
|
44
68
|
scheduleDraw: () => {},
|
|
45
69
|
resetInteraction: () => {},
|
|
46
70
|
getIndicatorScheduler: () => ({
|
|
@@ -50,10 +74,6 @@ function createDependencies(
|
|
|
50
74
|
isPointerDown: () => false,
|
|
51
75
|
onTimeShareDataReady: () => {},
|
|
52
76
|
setSymbols,
|
|
53
|
-
setComparisonLoading: () => {},
|
|
54
|
-
comparisonSpecs$: computed(() => symbols$().slice(1)),
|
|
55
|
-
comparisonColors$: createSignal(new Map() as ReadonlyMap<string, string>),
|
|
56
|
-
comparisonLoading$: createSignal(false),
|
|
57
77
|
}
|
|
58
78
|
}
|
|
59
79
|
|
|
@@ -1,18 +1,56 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
|
|
3
|
-
import type { ChartDom, Viewport } from '../../chartTypes'
|
|
4
3
|
import { getPhysicalKLineConfig } from '../../utils/klineConfig'
|
|
5
4
|
import {
|
|
6
5
|
computeContentWidth,
|
|
7
6
|
computeLeftLoadBufferWidth,
|
|
8
7
|
computeMaxScrollLeft,
|
|
9
8
|
} from '../../state/contentGeometry'
|
|
9
|
+
import type { ViewportStateModule } from '../../state/viewportState'
|
|
10
10
|
import { ScrollCompensator, type ScrollDeps } from '../scrollCompensator'
|
|
11
11
|
|
|
12
|
-
function
|
|
12
|
+
function makeViewportModule(options: {
|
|
13
|
+
scrollLeft?: number
|
|
14
|
+
leftBuffer?: number
|
|
15
|
+
contentWidth?: number
|
|
16
|
+
viewWidth?: number
|
|
17
|
+
dpr?: number
|
|
18
|
+
}): { viewport: ViewportStateModule; getScrollLeft: () => number } {
|
|
19
|
+
let scrollLeft = options.scrollLeft ?? 0
|
|
20
|
+
const viewWidth = options.viewWidth ?? 800
|
|
21
|
+
const dpr = options.dpr ?? 1
|
|
22
|
+
const leftBuffer = options.leftBuffer ?? 800
|
|
23
|
+
const contentWidth = options.contentWidth ?? 1600
|
|
24
|
+
|
|
25
|
+
const viewport = {
|
|
26
|
+
readonly: {
|
|
27
|
+
dpr: { peek: () => dpr },
|
|
28
|
+
scrollLeft: { peek: () => scrollLeft },
|
|
29
|
+
leftLoadBufferWidth: { peek: () => leftBuffer },
|
|
30
|
+
contentWidth: { peek: () => contentWidth },
|
|
31
|
+
viewWidth: { peek: () => viewWidth },
|
|
32
|
+
viewHeight: { peek: () => 600 },
|
|
33
|
+
viewport: {
|
|
34
|
+
peek: () => ({
|
|
35
|
+
viewWidth,
|
|
36
|
+
viewHeight: 600,
|
|
37
|
+
plotWidth: viewWidth,
|
|
38
|
+
plotHeight: 600,
|
|
39
|
+
scrollLeft,
|
|
40
|
+
dpr,
|
|
41
|
+
}),
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
actions: {
|
|
45
|
+
scrollTo: (v: number) => {
|
|
46
|
+
scrollLeft = v
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
} as unknown as ViewportStateModule
|
|
50
|
+
|
|
13
51
|
return {
|
|
14
|
-
|
|
15
|
-
|
|
52
|
+
viewport,
|
|
53
|
+
getScrollLeft: () => scrollLeft,
|
|
16
54
|
}
|
|
17
55
|
}
|
|
18
56
|
|
|
@@ -23,7 +61,6 @@ function makeDeps(options: {
|
|
|
23
61
|
viewWidth?: number
|
|
24
62
|
dataLength?: number
|
|
25
63
|
} = {}): { deps: ScrollDeps; getScrollLeft: () => number } {
|
|
26
|
-
let scrollLeft = options.scrollLeft ?? 0
|
|
27
64
|
const viewWidth = options.viewWidth ?? 800
|
|
28
65
|
const dataLength = options.dataLength ?? 100
|
|
29
66
|
const kWidth = 8
|
|
@@ -53,32 +90,20 @@ function makeDeps(options: {
|
|
|
53
90
|
kGap,
|
|
54
91
|
})
|
|
55
92
|
|
|
56
|
-
const viewport
|
|
93
|
+
const { viewport, getScrollLeft } = makeViewportModule({
|
|
94
|
+
scrollLeft: options.scrollLeft ?? 0,
|
|
95
|
+
leftBuffer,
|
|
96
|
+
contentWidth,
|
|
57
97
|
viewWidth,
|
|
58
|
-
viewHeight: 600,
|
|
59
|
-
plotWidth: viewWidth,
|
|
60
|
-
plotHeight: 600,
|
|
61
|
-
scrollLeft,
|
|
62
98
|
dpr,
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const deps: ScrollDeps = {
|
|
66
|
-
getOption: () => ({ kWidth, kGap }),
|
|
67
|
-
getEffectiveDpr: () => dpr,
|
|
68
|
-
getCachedScrollLeft: () => scrollLeft,
|
|
69
|
-
setScrollLeft: (v) => {
|
|
70
|
-
scrollLeft = v
|
|
71
|
-
},
|
|
72
|
-
getDom: () => makeDom(),
|
|
73
|
-
getObservedSize: () => ({ width: viewWidth, height: 600 }),
|
|
74
|
-
getViewport: () => viewport,
|
|
75
|
-
getLeftLoadBufferWidth: () => leftBuffer,
|
|
76
|
-
getContentWidth: () => contentWidth,
|
|
77
|
-
}
|
|
99
|
+
})
|
|
78
100
|
|
|
79
101
|
return {
|
|
80
|
-
deps
|
|
81
|
-
|
|
102
|
+
deps: {
|
|
103
|
+
getOption: () => ({ kWidth, kGap }),
|
|
104
|
+
viewport,
|
|
105
|
+
},
|
|
106
|
+
getScrollLeft,
|
|
82
107
|
}
|
|
83
108
|
}
|
|
84
109
|
|
|
@@ -89,7 +114,7 @@ describe('ScrollCompensator geometry SSOT', () => {
|
|
|
89
114
|
const kWidth = 8
|
|
90
115
|
const kGap = 2
|
|
91
116
|
const dpr = 1
|
|
92
|
-
const
|
|
117
|
+
const leftBuffer = computeLeftLoadBufferWidth({
|
|
93
118
|
viewWidth,
|
|
94
119
|
plotWidth: viewWidth,
|
|
95
120
|
dataLength,
|
|
@@ -97,27 +122,28 @@ describe('ScrollCompensator geometry SSOT', () => {
|
|
|
97
122
|
dpr,
|
|
98
123
|
kWidth,
|
|
99
124
|
kGap,
|
|
100
|
-
}
|
|
101
|
-
const
|
|
102
|
-
|
|
125
|
+
})
|
|
126
|
+
const contentWidth = computeContentWidth({
|
|
127
|
+
viewWidth,
|
|
128
|
+
plotWidth: viewWidth,
|
|
129
|
+
dataLength,
|
|
130
|
+
period: 'daily',
|
|
131
|
+
dpr,
|
|
132
|
+
kWidth,
|
|
133
|
+
kGap,
|
|
134
|
+
})
|
|
103
135
|
const maxScroll = computeMaxScrollLeft(contentWidth, viewWidth)
|
|
104
136
|
|
|
105
137
|
const { deps, getScrollLeft } = makeDeps({
|
|
106
|
-
|
|
107
|
-
dataLength,
|
|
138
|
+
scrollLeft: 0,
|
|
108
139
|
leftBuffer,
|
|
109
140
|
contentWidth,
|
|
110
|
-
|
|
141
|
+
viewWidth,
|
|
142
|
+
dataLength,
|
|
111
143
|
})
|
|
112
|
-
|
|
113
|
-
const compensator = new ScrollCompensator(deps)
|
|
114
|
-
compensator.scrollToRight(dataLength)
|
|
115
|
-
|
|
144
|
+
new ScrollCompensator(deps).scrollToRight(dataLength)
|
|
116
145
|
const scrollLeft = getScrollLeft()
|
|
117
|
-
expect(scrollLeft).toBeLessThanOrEqual(maxScroll)
|
|
118
|
-
expect(scrollLeft).toBeGreaterThanOrEqual(0)
|
|
119
146
|
|
|
120
|
-
// target 计算应与 clamp 后一致(数据足够长时贴右)
|
|
121
147
|
const { unitPx, startXPx } = getPhysicalKLineConfig(kWidth, kGap, dpr)
|
|
122
148
|
const lastKLineEndPx = (startXPx + dataLength * unitPx) / dpr
|
|
123
149
|
const rawTarget = leftBuffer + (lastKLineEndPx - viewWidth)
|
|
@@ -125,60 +151,46 @@ describe('ScrollCompensator geometry SSOT', () => {
|
|
|
125
151
|
expect(scrollLeft).toBe(expected)
|
|
126
152
|
})
|
|
127
153
|
|
|
128
|
-
it('scrollToRight uses
|
|
154
|
+
it('scrollToRight uses viewport contentWidth / leftLoadBufferWidth, not local formulas', () => {
|
|
129
155
|
const injectedLeft = 111
|
|
130
156
|
const injectedContent = 500
|
|
131
157
|
const viewWidth = 400
|
|
132
|
-
|
|
158
|
+
const { viewport, getScrollLeft } = makeViewportModule({
|
|
159
|
+
scrollLeft: 0,
|
|
160
|
+
leftBuffer: injectedLeft,
|
|
161
|
+
contentWidth: injectedContent,
|
|
162
|
+
viewWidth,
|
|
163
|
+
dpr: 1,
|
|
164
|
+
})
|
|
133
165
|
|
|
134
166
|
const deps: ScrollDeps = {
|
|
135
167
|
getOption: () => ({ kWidth: 8, kGap: 2 }),
|
|
136
|
-
|
|
137
|
-
getCachedScrollLeft: () => scrollLeft,
|
|
138
|
-
setScrollLeft: (v) => {
|
|
139
|
-
scrollLeft = v
|
|
140
|
-
},
|
|
141
|
-
getDom: () => makeDom(),
|
|
142
|
-
getObservedSize: () => ({ width: viewWidth, height: 600 }),
|
|
143
|
-
getViewport: () => ({
|
|
144
|
-
viewWidth,
|
|
145
|
-
viewHeight: 600,
|
|
146
|
-
plotWidth: viewWidth,
|
|
147
|
-
plotHeight: 600,
|
|
148
|
-
scrollLeft: 0,
|
|
149
|
-
dpr: 1,
|
|
150
|
-
}),
|
|
151
|
-
getLeftLoadBufferWidth: () => injectedLeft,
|
|
152
|
-
getContentWidth: () => injectedContent,
|
|
168
|
+
viewport,
|
|
153
169
|
}
|
|
154
170
|
|
|
155
171
|
const compensator = new ScrollCompensator(deps)
|
|
156
172
|
compensator.scrollToRight(50)
|
|
157
173
|
|
|
158
174
|
const maxScroll = Math.max(0, injectedContent - viewWidth)
|
|
159
|
-
expect(
|
|
160
|
-
|
|
161
|
-
expect(scrollLeft).toBe(maxScroll)
|
|
175
|
+
expect(getScrollLeft()).toBeLessThanOrEqual(maxScroll)
|
|
176
|
+
expect(getScrollLeft()).toBe(maxScroll)
|
|
162
177
|
})
|
|
163
178
|
|
|
164
179
|
it('adjustScrollAfterDataChange uses injected left buffer when scrollLeft <= 0', () => {
|
|
165
|
-
let scrollLeft = 0
|
|
166
180
|
const injectedLeft = 640
|
|
181
|
+
const { viewport, getScrollLeft } = makeViewportModule({
|
|
182
|
+
scrollLeft: 0,
|
|
183
|
+
leftBuffer: injectedLeft,
|
|
184
|
+
contentWidth: 2000,
|
|
185
|
+
viewWidth: 800,
|
|
186
|
+
dpr: 1,
|
|
187
|
+
})
|
|
167
188
|
const deps: ScrollDeps = {
|
|
168
189
|
getOption: () => ({ kWidth: 8, kGap: 2 }),
|
|
169
|
-
|
|
170
|
-
getCachedScrollLeft: () => scrollLeft,
|
|
171
|
-
setScrollLeft: (v) => {
|
|
172
|
-
scrollLeft = v
|
|
173
|
-
},
|
|
174
|
-
getDom: () => makeDom(),
|
|
175
|
-
getObservedSize: () => ({ width: 800, height: 600 }),
|
|
176
|
-
getViewport: () => null,
|
|
177
|
-
getLeftLoadBufferWidth: () => injectedLeft,
|
|
178
|
-
getContentWidth: () => 2000,
|
|
190
|
+
viewport,
|
|
179
191
|
}
|
|
180
192
|
|
|
181
193
|
new ScrollCompensator(deps).adjustScrollAfterDataChange(10)
|
|
182
|
-
expect(
|
|
194
|
+
expect(getScrollLeft()).toBe(injectedLeft)
|
|
183
195
|
})
|
|
184
196
|
})
|
|
@@ -6,12 +6,13 @@ import { TimeShareBuffer } from '../../data/timeShareBuffer'
|
|
|
6
6
|
import type { TimeShareFetcherFn } from '../../data/types'
|
|
7
7
|
import { createSignal, type ReadonlySignal, type Signal } from '../../foundation/reactivity/signal'
|
|
8
8
|
import type { KLineData, TimeShareData } from '../../foundation/types/price'
|
|
9
|
-
import type { ChartDom
|
|
9
|
+
import type { ChartDom } from '../chartTypes'
|
|
10
10
|
import type { VisibleRange, UpdateLevel } from '../layout/pane'
|
|
11
11
|
import { getPhysicalKLineConfig } from '../utils/klineConfig'
|
|
12
|
-
import { getVisibleRange } from '../viewport/viewport'
|
|
13
12
|
import type { DataStateModule } from '../state/dataState'
|
|
14
13
|
import type { DataManagerStateModule } from '../state/dataManagerState'
|
|
14
|
+
import type { ViewportStateModule } from '../state/viewportState'
|
|
15
|
+
import type { ComparisonStateModule } from '../state/comparisonState'
|
|
15
16
|
|
|
16
17
|
import { ComparisonManager } from './comparisonManager'
|
|
17
18
|
import { FetchBatchScheduler } from './fetchBatchScheduler'
|
|
@@ -20,17 +21,11 @@ import { ScrollCompensator } from './scrollCompensator'
|
|
|
20
21
|
|
|
21
22
|
export interface DataDependencies {
|
|
22
23
|
getOption: () => { kWidth: number; kGap: number }
|
|
23
|
-
getEffectiveDpr: () => number
|
|
24
|
-
getLogicalScrollLeft: () => number
|
|
25
|
-
getCachedScrollLeft: () => number
|
|
26
|
-
setScrollLeft: (v: number) => void
|
|
27
24
|
getDom: () => ChartDom
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
getLeftLoadBufferWidth: () => number
|
|
33
|
-
getContentWidth: () => number
|
|
25
|
+
/** scroll / dpr / 可见区间 / 几何 SSOT */
|
|
26
|
+
viewport: ViewportStateModule
|
|
27
|
+
/** 对比叠加状态 SSOT */
|
|
28
|
+
comparison: ComparisonStateModule
|
|
34
29
|
scheduleDraw: (level?: UpdateLevel) => void
|
|
35
30
|
resetInteraction: () => void
|
|
36
31
|
getIndicatorScheduler: () => {
|
|
@@ -40,11 +35,8 @@ export interface DataDependencies {
|
|
|
40
35
|
isPointerDown: () => boolean
|
|
41
36
|
onTimeShareDataReady: (dataLength: number) => void
|
|
42
37
|
onDataProcessed?: (data: KLineData[], range: VisibleRange) => void
|
|
38
|
+
/** 写 symbols 选择(含 primary + comparison) */
|
|
43
39
|
setSymbols: (symbols: ReadonlyArray<SymbolSpec>) => void
|
|
44
|
-
setComparisonLoading: (loading: boolean) => void
|
|
45
|
-
comparisonSpecs$: ReadonlySignal<ReadonlyArray<SymbolSpec>>
|
|
46
|
-
comparisonColors$: ReadonlySignal<ReadonlyMap<string, string>>
|
|
47
|
-
comparisonLoading$: ReadonlySignal<boolean>
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
const BUF_PRIMARY = 'main'
|
|
@@ -95,10 +87,10 @@ export class ChartDataManager {
|
|
|
95
87
|
getKLineBuffer: (key) => this._klineBuffers.get(key),
|
|
96
88
|
getKLineBufferKeys: () => [...this._klineBuffers.keys()],
|
|
97
89
|
scheduleDraw: () => this.deps.scheduleDraw(),
|
|
98
|
-
getSpecs: () => this.deps.
|
|
99
|
-
setLoading: (loading) => this.deps.
|
|
90
|
+
getSpecs: () => this.deps.comparison.readonly.specs.peek(),
|
|
91
|
+
setLoading: (loading) => this.deps.comparison.actions.setLoading(loading),
|
|
100
92
|
})
|
|
101
|
-
this._comparisonSpecsUnsub = this.deps.
|
|
93
|
+
this._comparisonSpecsUnsub = this.deps.comparison.readonly.specs.subscribe(() => {
|
|
102
94
|
this.reconcileComparisonBuffers()
|
|
103
95
|
})
|
|
104
96
|
this.reconcileComparisonBuffers()
|
|
@@ -305,7 +297,7 @@ export class ChartDataManager {
|
|
|
305
297
|
this._dmState.actions.setRangeInitialized(true)
|
|
306
298
|
}
|
|
307
299
|
|
|
308
|
-
let currentRange = this.
|
|
300
|
+
let currentRange = this.getVisibleRangeOrNull()
|
|
309
301
|
if (!currentRange && this._dmState.readonly.rangeInitialized.peek() && bufferData.length > 0) {
|
|
310
302
|
currentRange = { start: 0, end: bufferData.length }
|
|
311
303
|
}
|
|
@@ -325,7 +317,7 @@ export class ChartDataManager {
|
|
|
325
317
|
}
|
|
326
318
|
|
|
327
319
|
private recordIncrementalLoad(prependedCount: number): void {
|
|
328
|
-
this._dmState.actions.recordIncrementalLoad(prependedCount, this.deps.
|
|
320
|
+
this._dmState.actions.recordIncrementalLoad(prependedCount, this.deps.viewport.readonly.leftLoadBufferWidth.peek())
|
|
329
321
|
}
|
|
330
322
|
|
|
331
323
|
private scheduleIncrementalLoadHintFlush(key: string): void {
|
|
@@ -370,7 +362,7 @@ export class ChartDataManager {
|
|
|
370
362
|
// ── Internal helpers ──
|
|
371
363
|
|
|
372
364
|
getLeftLoadBufferWidth(): number {
|
|
373
|
-
return this.deps.
|
|
365
|
+
return this.deps.viewport.readonly.leftLoadBufferWidth.peek()
|
|
374
366
|
}
|
|
375
367
|
|
|
376
368
|
private getActiveKLineLength(): number {
|
|
@@ -378,9 +370,21 @@ export class ChartDataManager {
|
|
|
378
370
|
return buf ? buf.getRawData().length : 0
|
|
379
371
|
}
|
|
380
372
|
|
|
373
|
+
/** 无 viewport / 无数据时返回 null;clamped 可索引区间(start>=0) */
|
|
374
|
+
private getVisibleRangeOrNull(): VisibleRange | null {
|
|
375
|
+
if (this.deps.viewport.readonly.viewWidth.peek() === 0) return null
|
|
376
|
+
return this.deps.viewport.readonly.visibleRange.peek()
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** raw 可见区间(含左右扩窗,start 可能为 -1);供增量加载左缘检测 */
|
|
380
|
+
private getRawVisibleRangeOrNull(): VisibleRange | null {
|
|
381
|
+
if (this.deps.viewport.readonly.viewWidth.peek() === 0) return null
|
|
382
|
+
return this.deps.viewport.readonly.rawVisibleRange.peek()
|
|
383
|
+
}
|
|
384
|
+
|
|
381
385
|
/** 当前可见范围(on-demand 实时计算,消除 stale 缓存) */
|
|
382
386
|
getCurrentVisibleRange(): VisibleRange | null {
|
|
383
|
-
return this.
|
|
387
|
+
return this.getVisibleRangeOrNull()
|
|
384
388
|
}
|
|
385
389
|
|
|
386
390
|
/** Unified data signal — always reflects the active buffer's data */
|
|
@@ -448,6 +452,16 @@ export class ChartDataManager {
|
|
|
448
452
|
return buf ? buf.getRawData() : []
|
|
449
453
|
}
|
|
450
454
|
|
|
455
|
+
getTimeSharePreClose(): number | null {
|
|
456
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
457
|
+
return buf?.getPreClose() ?? null
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
setTimeSharePreClose(preClose: number | null): void {
|
|
461
|
+
const buf = this.getActiveTimeShareBuffer()
|
|
462
|
+
if (buf) buf.setPreClose(preClose)
|
|
463
|
+
}
|
|
464
|
+
|
|
451
465
|
getTimeShareSignal(): ReadonlySignal<ReadonlyArray<TimeShareData>> {
|
|
452
466
|
const buf = this.getActiveTimeShareBuffer()
|
|
453
467
|
return (buf?.data ?? createSignal<ReadonlyArray<TimeShareData>>([])) as ReadonlySignal<
|
|
@@ -469,7 +483,7 @@ export class ChartDataManager {
|
|
|
469
483
|
}
|
|
470
484
|
|
|
471
485
|
getComparisonSpecs(): SymbolSpec[] {
|
|
472
|
-
return this.deps.
|
|
486
|
+
return this.deps.comparison.readonly.specs.peek().map((spec) => ({ ...spec }))
|
|
473
487
|
}
|
|
474
488
|
|
|
475
489
|
get dataBuffer(): KLineBuffer {
|
|
@@ -485,15 +499,15 @@ export class ChartDataManager {
|
|
|
485
499
|
}
|
|
486
500
|
|
|
487
501
|
get comparisonColors(): ReadonlySignal<ReadonlyMap<string, string>> {
|
|
488
|
-
return this.deps.
|
|
502
|
+
return this.deps.comparison.readonly.colors
|
|
489
503
|
}
|
|
490
504
|
|
|
491
505
|
get comparisonLoading(): ReadonlySignal<boolean> {
|
|
492
|
-
return this.deps.
|
|
506
|
+
return this.deps.comparison.readonly.loading
|
|
493
507
|
}
|
|
494
508
|
|
|
495
509
|
getComparisonColors(): Map<string, string> {
|
|
496
|
-
return new Map(this.deps.
|
|
510
|
+
return new Map(this.deps.comparison.readonly.colors.peek())
|
|
497
511
|
}
|
|
498
512
|
|
|
499
513
|
// ── Data updates (KLine) ──
|
|
@@ -554,20 +568,22 @@ export class ChartDataManager {
|
|
|
554
568
|
if (data.length === 0) return
|
|
555
569
|
const window = buf.loadedWindow
|
|
556
570
|
if (!window) return
|
|
557
|
-
|
|
558
|
-
|
|
571
|
+
// 左缘扩窗检测必须用 raw(start 可为 -1);数据下标用 clamped
|
|
572
|
+
const rawRange = this.getRawVisibleRangeOrNull()
|
|
573
|
+
const range = this.getVisibleRangeOrNull()
|
|
574
|
+
if (!rawRange || !range) return
|
|
559
575
|
|
|
560
576
|
const MS_PER_DAY = 86_400_000
|
|
561
577
|
const spec = buf.currentSpec
|
|
562
578
|
const gapDays = getPeriodDays(spec?.period)
|
|
563
579
|
let firstVisibleTs: number | undefined
|
|
564
580
|
|
|
565
|
-
if (
|
|
581
|
+
if (rawRange.start < 0 && this._dataFetcher) {
|
|
566
582
|
const earlierThanEarliest = window.earliestTs - gapDays * MS_PER_DAY
|
|
567
583
|
buf.ensureRange(earlierThanEarliest, window.earliestTs)
|
|
568
584
|
firstVisibleTs = data[0]?.timestamp
|
|
569
585
|
} else if (range.start < data.length) {
|
|
570
|
-
firstVisibleTs = data[
|
|
586
|
+
firstVisibleTs = data[range.start]?.timestamp
|
|
571
587
|
if (firstVisibleTs !== undefined && firstVisibleTs < window.earliestTs) {
|
|
572
588
|
buf.ensureRange(firstVisibleTs, window.earliestTs)
|
|
573
589
|
}
|
|
@@ -587,18 +603,18 @@ export class ChartDataManager {
|
|
|
587
603
|
|
|
588
604
|
addComparisonSymbol(spec: SymbolSpec): void {
|
|
589
605
|
const primary = this._dataState.readonly.symbols.peek()[0]
|
|
590
|
-
if (!primary || this.deps.
|
|
606
|
+
if (!primary || this.deps.comparison.readonly.specs.peek().some((item) => item.symbol === spec.symbol))
|
|
591
607
|
return
|
|
592
|
-
this.deps.setSymbols([primary, ...this.deps.
|
|
608
|
+
this.deps.setSymbols([primary, ...this.deps.comparison.readonly.specs.peek(), spec])
|
|
593
609
|
}
|
|
594
610
|
|
|
595
611
|
setComparisonData(symbol: string, data: KLineData[]): void {
|
|
596
612
|
const primary = this._dataState.readonly.symbols.peek()[0]
|
|
597
613
|
if (!primary) return
|
|
598
|
-
if (!this.deps.
|
|
614
|
+
if (!this.deps.comparison.readonly.specs.peek().some((spec) => spec.symbol === symbol)) {
|
|
599
615
|
this.deps.setSymbols([
|
|
600
616
|
primary,
|
|
601
|
-
...this.deps.
|
|
617
|
+
...this.deps.comparison.readonly.specs.peek(),
|
|
602
618
|
{ symbol, period: 'daily' },
|
|
603
619
|
])
|
|
604
620
|
}
|
|
@@ -607,11 +623,11 @@ export class ChartDataManager {
|
|
|
607
623
|
|
|
608
624
|
removeComparisonSymbol(symbol: string): void {
|
|
609
625
|
const primary = this._dataState.readonly.symbols.peek()[0]
|
|
610
|
-
if (!primary || !this.deps.
|
|
626
|
+
if (!primary || !this.deps.comparison.readonly.specs.peek().some((spec) => spec.symbol === symbol))
|
|
611
627
|
return
|
|
612
628
|
this.deps.setSymbols([
|
|
613
629
|
primary,
|
|
614
|
-
...this.deps.
|
|
630
|
+
...this.deps.comparison.readonly.specs.peek().filter((spec) => spec.symbol !== symbol),
|
|
615
631
|
])
|
|
616
632
|
this.deps.scheduleDraw()
|
|
617
633
|
}
|
|
@@ -636,19 +652,8 @@ export class ChartDataManager {
|
|
|
636
652
|
const dataLen = kRaw?.length ?? 0
|
|
637
653
|
let visibleStart = 0
|
|
638
654
|
if (dataLen > 0) {
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
const opt = this.deps.getOption()
|
|
642
|
-
const vRange = getVisibleRange(
|
|
643
|
-
vp.scrollLeft,
|
|
644
|
-
vp.plotWidth,
|
|
645
|
-
opt.kWidth,
|
|
646
|
-
opt.kGap,
|
|
647
|
-
dataLen,
|
|
648
|
-
vp.dpr,
|
|
649
|
-
)
|
|
650
|
-
visibleStart = vRange ? Math.max(0, vRange.start) : 0
|
|
651
|
-
}
|
|
655
|
+
const vRange = this.getVisibleRangeOrNull()
|
|
656
|
+
visibleStart = vRange ? Math.max(0, vRange.start) : 0
|
|
652
657
|
}
|
|
653
658
|
// 双路径守卫:
|
|
654
659
|
// - switchToTimeShareForDate 路径:setTimeShareQueryDate 已在
|
|
@@ -693,7 +698,7 @@ export class ChartDataManager {
|
|
|
693
698
|
return
|
|
694
699
|
}
|
|
695
700
|
const next = { ...current, period }
|
|
696
|
-
this.setSymbols([next, ...this.deps.
|
|
701
|
+
this.setSymbols([next, ...this.deps.comparison.readonly.specs.peek()])
|
|
697
702
|
}
|
|
698
703
|
|
|
699
704
|
/**
|
|
@@ -725,7 +730,7 @@ export class ChartDataManager {
|
|
|
725
730
|
incremental: false,
|
|
726
731
|
source: source.source ?? 'custom',
|
|
727
732
|
}
|
|
728
|
-
this.setSymbols([spec, ...this.deps.
|
|
733
|
+
this.setSymbols([spec, ...this.deps.comparison.readonly.specs.peek()])
|
|
729
734
|
|
|
730
735
|
const symbolCode = spec.symbol
|
|
731
736
|
if (symbolCode) {
|
|
@@ -760,7 +765,7 @@ export class ChartDataManager {
|
|
|
760
765
|
this._dataState.actions.setData([])
|
|
761
766
|
this._dmState.actions.setRangeInitialized(false)
|
|
762
767
|
this._dmState.actions.setSavedScrollTimestamp(null)
|
|
763
|
-
this.setSymbols([spec, ...this.deps.
|
|
768
|
+
this.setSymbols([spec, ...this.deps.comparison.readonly.specs.peek()])
|
|
764
769
|
}
|
|
765
770
|
|
|
766
771
|
getPreCustomSpec(): SymbolSpec | null {
|
|
@@ -872,12 +877,12 @@ export class ChartDataManager {
|
|
|
872
877
|
)
|
|
873
878
|
this._dmState.actions.setSavedScrollTimestamp(null)
|
|
874
879
|
if (idx >= 0) {
|
|
875
|
-
const dpr = this.deps.
|
|
880
|
+
const dpr = this.deps.viewport.readonly.dpr.peek()
|
|
876
881
|
const opt = this.deps.getOption()
|
|
877
882
|
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
878
883
|
const leftBuffer = this.getLeftLoadBufferWidth()
|
|
879
884
|
const scrollLeft = ((idx + 1) * unitPx + startXPx) / dpr + leftBuffer
|
|
880
|
-
this.deps.
|
|
885
|
+
this.deps.viewport.actions.scrollTo(scrollLeft)
|
|
881
886
|
return true
|
|
882
887
|
}
|
|
883
888
|
return false
|
|
@@ -886,7 +891,7 @@ export class ChartDataManager {
|
|
|
886
891
|
// ── Content width ──
|
|
887
892
|
|
|
888
893
|
getContentWidth(): number {
|
|
889
|
-
return this.deps.
|
|
894
|
+
return this.deps.viewport.readonly.contentWidth.peek()
|
|
890
895
|
}
|
|
891
896
|
|
|
892
897
|
scrollToRight(): void {
|
|
@@ -962,12 +967,12 @@ export class ChartDataManager {
|
|
|
962
967
|
}
|
|
963
968
|
|
|
964
969
|
getLogicalIndexAtX(mouseX: number): number | null {
|
|
965
|
-
|
|
966
|
-
|
|
970
|
+
if (this.deps.viewport.readonly.viewWidth.peek() === 0) return null
|
|
971
|
+
const vp = this.deps.viewport.readonly.viewport.peek()
|
|
967
972
|
const buf = this.getActiveDataBuffer()
|
|
968
973
|
const data = buf ? buf.getRawData() : []
|
|
969
974
|
if (data.length === 0) return null
|
|
970
|
-
const dpr = this.deps.
|
|
975
|
+
const dpr = this.deps.viewport.readonly.dpr.peek()
|
|
971
976
|
const opt = this.deps.getOption()
|
|
972
977
|
const { startXPx, unitPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
973
978
|
const worldX = Math.round((vp.scrollLeft + mouseX) * dpr)
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { ChartDom } from '../chartTypes'
|
|
2
2
|
import { getPhysicalKLineConfig } from '../utils/klineConfig'
|
|
3
|
+
import type { ViewportStateModule } from '../state/viewportState'
|
|
3
4
|
|
|
4
5
|
/** 与 theme selectionFill 对齐:light #2D7FF933 / dark #4A9EFF33;fallback 为 light 默认 */
|
|
5
6
|
const INCREMENTAL_LOAD_HINT_BG = 'var(--klc-color-selection-fill, #2D7FF933)'
|
|
6
7
|
|
|
7
8
|
export interface HintDeps {
|
|
8
9
|
getOption: () => { kWidth: number; kGap: number }
|
|
9
|
-
getEffectiveDpr: () => number
|
|
10
10
|
getDom: () => ChartDom
|
|
11
|
-
|
|
11
|
+
viewport: ViewportStateModule
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
interface ActiveHint {
|
|
@@ -86,17 +86,18 @@ export class IncrementalLoadHint {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
private _updateGeometry(hint: HTMLDivElement, count: number, leftBufferWidth: number): void {
|
|
89
|
-
const dpr = this.deps.
|
|
89
|
+
const dpr = this.deps.viewport.readonly.dpr.peek()
|
|
90
90
|
const opt = this.deps.getOption()
|
|
91
91
|
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
92
92
|
|
|
93
93
|
hint.style.left = `${leftBufferWidth}px`
|
|
94
94
|
const width = (startXPx + count * unitPx) / dpr
|
|
95
95
|
hint.style.width = `${Math.max(0, width)}px`
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.deps.
|
|
99
|
-
|
|
96
|
+
const viewHeight =
|
|
97
|
+
this.deps.viewport.readonly.viewHeight.peek() ||
|
|
98
|
+
this.deps.getDom().container?.clientHeight ||
|
|
99
|
+
0
|
|
100
|
+
hint.style.height = `${Math.max(0, viewHeight)}px`
|
|
100
101
|
}
|
|
101
102
|
|
|
102
103
|
private _fadeOutAndRemove(entry: ActiveHint): void {
|