@363045841yyt/klinechart-core 0.9.0-alpha.2 → 0.9.0-alpha.3
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/engine/chart.d.ts +9 -9
- package/dist/engine/chart.d.ts.map +1 -1
- package/dist/engine/chart.js +69 -96
- 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 +12 -18
- package/dist/engine/data/chartDataManager.d.ts.map +1 -1
- package/dist/engine/data/chartDataManager.js +46 -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/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 +117 -69
- 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 +72 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.d.ts.map +1 -0
- package/dist/engine/renderers/Indicator/mainIndicatorLegendContext.js +177 -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/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/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/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/binance.ts +1 -1
- package/src/engine/__tests__/chart.dpr.test.ts +3 -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 +76 -109
- 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 +54 -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/paneRenderer.ts +17 -10
- package/src/engine/render/chartRenderer.ts +187 -129
- 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 +282 -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/yAxis.ts +57 -22
- 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/plugin/rendererPluginManager.test.ts +18 -0
- package/src/foundation/plugin/types.ts +3 -0
- package/src/foundation/reactivity/frameTransaction.ts +20 -6
- 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
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type ReadonlySignal,
|
|
12
12
|
type Computed,
|
|
13
13
|
} from '../../foundation/reactivity/signal'
|
|
14
|
-
import type { MainIndicatorEntry } from '../state/indicatorState'
|
|
14
|
+
import type { IndicatorStateModule, MainIndicatorEntry } from '../state/indicatorState'
|
|
15
15
|
import type { SubPaneSpec } from '../state/subPaneState'
|
|
16
16
|
import type { Layer } from '../../rendering/scene/types'
|
|
17
17
|
import type { KLineData } from '../../foundation/types/price'
|
|
@@ -47,6 +47,24 @@ function mainIndicatorProjectionKey(
|
|
|
47
47
|
.join('|')
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/** 副图业务操作:create/remove/clear 会联动 pane 布局,不能只写 subPane 模块 */
|
|
51
|
+
export interface SubPaneOps {
|
|
52
|
+
readonly entries: ReadonlySignal<ReadonlyArray<SubPaneSpec>>
|
|
53
|
+
create: (
|
|
54
|
+
paneId: string,
|
|
55
|
+
indicatorId: string,
|
|
56
|
+
params: Readonly<Record<string, unknown>>,
|
|
57
|
+
) => void
|
|
58
|
+
remove: (paneId: string) => void
|
|
59
|
+
replace: (
|
|
60
|
+
paneId: string,
|
|
61
|
+
indicatorId: string,
|
|
62
|
+
params: Readonly<Record<string, unknown>>,
|
|
63
|
+
) => void
|
|
64
|
+
setParams: (paneId: string, params: Readonly<Record<string, unknown>>) => void
|
|
65
|
+
clear: () => void
|
|
66
|
+
}
|
|
67
|
+
|
|
50
68
|
export interface IndicatorDependencies {
|
|
51
69
|
getOption: () => ResolvedChartOptions
|
|
52
70
|
getPluginHost: () => PluginHostImpl
|
|
@@ -58,7 +76,8 @@ export interface IndicatorDependencies {
|
|
|
58
76
|
removeRenderer: (name: string) => void
|
|
59
77
|
updateRendererConfig: (name: string, config: Record<string, unknown>) => void
|
|
60
78
|
setRendererEnabled: (name: string, enabled: boolean) => void
|
|
61
|
-
|
|
79
|
+
/** pane ratios SSOT */
|
|
80
|
+
paneRatios$: ReadonlySignal<Readonly<Record<string, number>>>
|
|
62
81
|
paneSpecs$: ReadonlySignal<ReadonlyArray<PaneSpec>>
|
|
63
82
|
projectPaneLayout: (
|
|
64
83
|
specs: ReadonlyArray<PaneSpec>,
|
|
@@ -74,29 +93,10 @@ export interface IndicatorDependencies {
|
|
|
74
93
|
removeLayer: (id: string) => boolean
|
|
75
94
|
getLayer: (id: string) => Layer | null
|
|
76
95
|
setLayerVisibility: (id: string, visible: boolean) => void
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
upsertMainIndicator: (id: string, params: Record<string, number | boolean | string>) => void
|
|
82
|
-
removeMainIndicator: (id: string) => void
|
|
83
|
-
setMainIndicatorParams: (id: string, params: Record<string, number | boolean | string>) => void
|
|
84
|
-
replaceMainIndicators: (entries: ReadonlyMap<string, MainIndicatorEntry>) => void
|
|
85
|
-
clearMainIndicators: () => void
|
|
86
|
-
subPanes$: ReadonlySignal<ReadonlyArray<SubPaneSpec>>
|
|
87
|
-
createSubPaneState: (
|
|
88
|
-
paneId: string,
|
|
89
|
-
indicatorId: string,
|
|
90
|
-
params: Readonly<Record<string, unknown>>,
|
|
91
|
-
) => void
|
|
92
|
-
removeSubPaneState: (paneId: string) => void
|
|
93
|
-
replaceSubPaneState: (
|
|
94
|
-
paneId: string,
|
|
95
|
-
indicatorId: string,
|
|
96
|
-
params: Readonly<Record<string, unknown>>,
|
|
97
|
-
) => void
|
|
98
|
-
updateSubPaneStateParams: (paneId: string, params: Readonly<Record<string, unknown>>) => void
|
|
99
|
-
clearSubPaneState: () => void
|
|
96
|
+
/** 主图指标状态模块 */
|
|
97
|
+
indicator: IndicatorStateModule
|
|
98
|
+
/** 副图状态 + 联动 pane 布局的复合操作 */
|
|
99
|
+
subPaneOps: SubPaneOps
|
|
100
100
|
runRendererTransaction: (run: () => void) => void
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -169,12 +169,12 @@ export class ChartIndicatorManager {
|
|
|
169
169
|
|
|
170
170
|
// 注册副图活跃列表提供者
|
|
171
171
|
this.indicatorScheduler.setActiveSubPaneProvider(() =>
|
|
172
|
-
this.deps.
|
|
172
|
+
this.deps.subPaneOps.entries.peek().map((entry) => entry.paneId),
|
|
173
173
|
)
|
|
174
174
|
|
|
175
175
|
// 派生信号
|
|
176
176
|
this._indicatorsComputed = computed<ReadonlyArray<IndicatorInstance>>(() => {
|
|
177
|
-
const mainIndicators: IndicatorInstance[] = [...this.deps.mainIndicators
|
|
177
|
+
const mainIndicators: IndicatorInstance[] = [...this.deps.indicator.readonly.mainIndicators().entries()].map(
|
|
178
178
|
([id, entry]) => ({
|
|
179
179
|
id,
|
|
180
180
|
definitionId: id,
|
|
@@ -185,7 +185,7 @@ export class ChartIndicatorManager {
|
|
|
185
185
|
}),
|
|
186
186
|
)
|
|
187
187
|
|
|
188
|
-
const subIndicators: IndicatorInstance[] = this.deps.
|
|
188
|
+
const subIndicators: IndicatorInstance[] = this.deps.subPaneOps.entries().map((entry) => ({
|
|
189
189
|
id: entry.paneId,
|
|
190
190
|
definitionId: entry.indicatorId,
|
|
191
191
|
label: entry.indicatorId,
|
|
@@ -198,8 +198,8 @@ export class ChartIndicatorManager {
|
|
|
198
198
|
return [...mainIndicators, ...subIndicators]
|
|
199
199
|
})
|
|
200
200
|
this._subPanesComputed = computed<ReadonlyArray<SubPaneInfo>>(() => {
|
|
201
|
-
const ratios = deps.
|
|
202
|
-
return this.deps.
|
|
201
|
+
const ratios = deps.paneRatios$()
|
|
202
|
+
return this.deps.subPaneOps.entries().map((entry) => ({
|
|
203
203
|
paneId: entry.paneId,
|
|
204
204
|
indicatorId: entry.indicatorId,
|
|
205
205
|
params: { ...entry.params },
|
|
@@ -220,12 +220,12 @@ export class ChartIndicatorManager {
|
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
this.projectedPaneSpecs = this.deps.paneSpecs$.peek()
|
|
223
|
-
this.projectedPaneRatios = this.deps.
|
|
223
|
+
this.projectedPaneRatios = this.deps.paneRatios$.peek()
|
|
224
224
|
this.disposeProjection = effect(() => {
|
|
225
225
|
const paneSpecs = this.deps.paneSpecs$()
|
|
226
|
-
const paneRatios = this.deps.
|
|
227
|
-
const mainIndicators = this.deps.mainIndicators
|
|
228
|
-
const subPanes = this.deps.
|
|
226
|
+
const paneRatios = this.deps.paneRatios$()
|
|
227
|
+
const mainIndicators = this.deps.indicator.readonly.mainIndicators()
|
|
228
|
+
const subPanes = this.deps.subPaneOps.entries()
|
|
229
229
|
this.deps.runRendererTransaction(() => {
|
|
230
230
|
let paneChanged = false
|
|
231
231
|
if (paneSpecs !== this.projectedPaneSpecs || paneRatios !== this.projectedPaneRatios) {
|
|
@@ -250,7 +250,7 @@ export class ChartIndicatorManager {
|
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
get mainIndicatorsSignalPeek(): ReadonlyMap<string, MainIndicatorEntry> {
|
|
253
|
-
return this.deps.mainIndicators
|
|
253
|
+
return this.deps.indicator.readonly.mainIndicators.peek()
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
get indicatorsComputed(): Computed<ReadonlyArray<IndicatorInstance>> {
|
|
@@ -273,26 +273,26 @@ export class ChartIndicatorManager {
|
|
|
273
273
|
return false
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
-
const existing = this.deps.mainIndicators
|
|
276
|
+
const existing = this.deps.indicator.readonly.mainIndicators.peek().get(id)
|
|
277
277
|
|
|
278
278
|
if (existing) {
|
|
279
279
|
if (params) {
|
|
280
|
-
this.deps.
|
|
280
|
+
this.deps.indicator.actions.upsert(id, params)
|
|
281
281
|
}
|
|
282
282
|
return true
|
|
283
283
|
}
|
|
284
284
|
|
|
285
285
|
const defaults = ChartIndicatorManager.DEFAULT_MAIN_PARAMS[id] ?? {}
|
|
286
286
|
const merged = params ? { ...defaults, ...params } : defaults
|
|
287
|
-
this.deps.
|
|
287
|
+
this.deps.indicator.actions.upsert(id, merged)
|
|
288
288
|
return true
|
|
289
289
|
}
|
|
290
290
|
|
|
291
291
|
disableMainIndicator(indicatorId: string): boolean {
|
|
292
292
|
const id = indicatorId.toUpperCase()
|
|
293
|
-
if (!this.deps.mainIndicators
|
|
293
|
+
if (!this.deps.indicator.readonly.mainIndicators.peek().has(id)) return false
|
|
294
294
|
|
|
295
|
-
this.deps.
|
|
295
|
+
this.deps.indicator.actions.remove(id)
|
|
296
296
|
return true
|
|
297
297
|
}
|
|
298
298
|
|
|
@@ -305,11 +305,11 @@ export class ChartIndicatorManager {
|
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
getActiveMainIndicators(): string[] {
|
|
308
|
-
return [...this.deps.mainIndicators
|
|
308
|
+
return [...this.deps.indicator.readonly.mainIndicators.peek().keys()]
|
|
309
309
|
}
|
|
310
310
|
|
|
311
311
|
isMainIndicatorActive(indicatorId: string): boolean {
|
|
312
|
-
return this.deps.mainIndicators
|
|
312
|
+
return this.deps.indicator.readonly.mainIndicators.peek().has(indicatorId.toUpperCase())
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
updateMainIndicatorParams(
|
|
@@ -317,18 +317,18 @@ export class ChartIndicatorManager {
|
|
|
317
317
|
params: Record<string, number | boolean | string>,
|
|
318
318
|
): void {
|
|
319
319
|
const id = indicatorId.toUpperCase()
|
|
320
|
-
if (!this.deps.mainIndicators
|
|
320
|
+
if (!this.deps.indicator.readonly.mainIndicators.peek().has(id)) return
|
|
321
321
|
|
|
322
|
-
this.deps.
|
|
322
|
+
this.deps.indicator.actions.setParams(id, params)
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
getMainIndicatorParams(indicatorId: string): Record<string, number | boolean | string> | null {
|
|
326
|
-
const params = this.deps.mainIndicators
|
|
326
|
+
const params = this.deps.indicator.readonly.mainIndicators.peek().get(indicatorId.toUpperCase())?.params
|
|
327
327
|
return params ? { ...params } : null
|
|
328
328
|
}
|
|
329
329
|
|
|
330
330
|
clearMainIndicators(): void {
|
|
331
|
-
this.deps.
|
|
331
|
+
this.deps.indicator.actions.clear()
|
|
332
332
|
}
|
|
333
333
|
|
|
334
334
|
private reconcileMainIndicators(desired: ReadonlyMap<string, MainIndicatorEntry>): boolean {
|
|
@@ -397,7 +397,7 @@ export class ChartIndicatorManager {
|
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
private updateIndicatorSchedulerConfig(indicatorId: string): void {
|
|
400
|
-
const entry = this.deps.mainIndicators
|
|
400
|
+
const entry = this.deps.indicator.readonly.mainIndicators.peek().get(indicatorId)
|
|
401
401
|
const isActive = entry !== undefined
|
|
402
402
|
const params = entry?.params ?? {}
|
|
403
403
|
|
|
@@ -419,7 +419,7 @@ export class ChartIndicatorManager {
|
|
|
419
419
|
const newIds = indicators
|
|
420
420
|
.map((i) => i.toUpperCase())
|
|
421
421
|
.filter((id) => ChartIndicatorManager.ENABLE_MAIN_INDICATORS.includes(id))
|
|
422
|
-
const prev = this.deps.mainIndicators
|
|
422
|
+
const prev = this.deps.indicator.readonly.mainIndicators.peek()
|
|
423
423
|
|
|
424
424
|
const next = new Map<string, MainIndicatorEntry>()
|
|
425
425
|
for (const id of newIds) {
|
|
@@ -432,7 +432,7 @@ export class ChartIndicatorManager {
|
|
|
432
432
|
})
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
|
-
this.deps.
|
|
435
|
+
this.deps.indicator.actions.replaceAll(next)
|
|
436
436
|
}
|
|
437
437
|
|
|
438
438
|
// ========== 副图管理 API ==========
|
|
@@ -446,7 +446,7 @@ export class ChartIndicatorManager {
|
|
|
446
446
|
if (!definition) {
|
|
447
447
|
throw new KLineChartError('NOT_REGISTERED', `[Chart] Unknown indicator: ${indicatorId}`)
|
|
448
448
|
}
|
|
449
|
-
this.deps.
|
|
449
|
+
this.deps.subPaneOps.create(
|
|
450
450
|
paneId,
|
|
451
451
|
indicatorId,
|
|
452
452
|
params ?? this.getDefaultSubPaneParams(indicatorId),
|
|
@@ -458,13 +458,13 @@ export class ChartIndicatorManager {
|
|
|
458
458
|
indicatorId: SubIndicatorType,
|
|
459
459
|
params?: Record<string, number | boolean | string>,
|
|
460
460
|
): boolean {
|
|
461
|
-
const existing = this.deps.
|
|
461
|
+
const existing = this.deps.subPaneOps.entries.peek().find((entry) => entry.paneId === paneId)
|
|
462
462
|
if (existing) {
|
|
463
463
|
if (
|
|
464
464
|
existing.indicatorId === indicatorId &&
|
|
465
465
|
!this.subPaneManager.getMountedResources(paneId)
|
|
466
466
|
) {
|
|
467
|
-
this.deps.
|
|
467
|
+
this.deps.subPaneOps.replace(
|
|
468
468
|
paneId,
|
|
469
469
|
existing.indicatorId,
|
|
470
470
|
existing.params,
|
|
@@ -475,7 +475,7 @@ export class ChartIndicatorManager {
|
|
|
475
475
|
if (!this.indicatorScheduler.getIndicatorMetadata(indicatorId)) {
|
|
476
476
|
throw new KLineChartError('NOT_REGISTERED', `[Chart] Unknown indicator: ${indicatorId}`)
|
|
477
477
|
}
|
|
478
|
-
this.deps.
|
|
478
|
+
this.deps.subPaneOps.create(
|
|
479
479
|
paneId,
|
|
480
480
|
indicatorId,
|
|
481
481
|
params ?? this.getDefaultSubPaneParams(indicatorId),
|
|
@@ -484,7 +484,7 @@ export class ChartIndicatorManager {
|
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
removeSubPane(paneId: string): void {
|
|
487
|
-
this.deps.
|
|
487
|
+
this.deps.subPaneOps.remove(paneId)
|
|
488
488
|
}
|
|
489
489
|
|
|
490
490
|
replaceSubPaneIndicator(
|
|
@@ -495,7 +495,7 @@ export class ChartIndicatorManager {
|
|
|
495
495
|
if (!this.indicatorScheduler.getIndicatorMetadata(newIndicatorId)) {
|
|
496
496
|
throw new KLineChartError('NOT_REGISTERED', `[Chart] Unknown indicator: ${newIndicatorId}`)
|
|
497
497
|
}
|
|
498
|
-
this.deps.
|
|
498
|
+
this.deps.subPaneOps.replace(
|
|
499
499
|
paneId,
|
|
500
500
|
newIndicatorId,
|
|
501
501
|
params ?? this.getDefaultSubPaneParams(newIndicatorId),
|
|
@@ -503,22 +503,22 @@ export class ChartIndicatorManager {
|
|
|
503
503
|
}
|
|
504
504
|
|
|
505
505
|
updateSubPaneParams(paneId: string, params: Record<string, unknown>): void {
|
|
506
|
-
this.deps.
|
|
506
|
+
this.deps.subPaneOps.setParams(paneId, params)
|
|
507
507
|
}
|
|
508
508
|
|
|
509
509
|
clearSubPanes(): void {
|
|
510
|
-
this.deps.
|
|
510
|
+
this.deps.subPaneOps.clear()
|
|
511
511
|
}
|
|
512
512
|
|
|
513
513
|
/**
|
|
514
514
|
* @deprecated 使用 getSubPaneEntries 获取完整信息
|
|
515
515
|
*/
|
|
516
516
|
getSubPaneIndicators(): SubIndicatorType[] {
|
|
517
|
-
return this.deps.
|
|
517
|
+
return this.deps.subPaneOps.entries.peek().map((entry) => entry.indicatorId)
|
|
518
518
|
}
|
|
519
519
|
|
|
520
520
|
getSubPaneEntries(): SubPaneEntry[] {
|
|
521
|
-
return this.deps.
|
|
521
|
+
return this.deps.subPaneOps.entries.peek().map((entry) => ({
|
|
522
522
|
...entry,
|
|
523
523
|
params: { ...entry.params },
|
|
524
524
|
...this.subPaneManager.getMountedResources(entry.paneId),
|
|
@@ -526,7 +526,7 @@ export class ChartIndicatorManager {
|
|
|
526
526
|
}
|
|
527
527
|
|
|
528
528
|
getSubPaneEntry(paneId: string): SubPaneEntry | undefined {
|
|
529
|
-
const entry = this.deps.
|
|
529
|
+
const entry = this.deps.subPaneOps.entries.peek().find((candidate) => candidate.paneId === paneId)
|
|
530
530
|
if (!entry) return undefined
|
|
531
531
|
return {
|
|
532
532
|
...entry,
|
|
@@ -569,7 +569,7 @@ export class ChartIndicatorManager {
|
|
|
569
569
|
removeIndicator(instanceId: string): boolean {
|
|
570
570
|
const id = instanceId.toUpperCase()
|
|
571
571
|
|
|
572
|
-
if (this.deps.mainIndicators
|
|
572
|
+
if (this.deps.indicator.readonly.mainIndicators.peek().has(id)) {
|
|
573
573
|
return this.disableMainIndicator(instanceId)
|
|
574
574
|
}
|
|
575
575
|
|
|
@@ -585,7 +585,7 @@ export class ChartIndicatorManager {
|
|
|
585
585
|
updateIndicatorParams(instanceId: string, params: Record<string, unknown>): boolean {
|
|
586
586
|
const id = instanceId.toUpperCase()
|
|
587
587
|
|
|
588
|
-
if (this.deps.mainIndicators
|
|
588
|
+
if (this.deps.indicator.readonly.mainIndicators.peek().has(id)) {
|
|
589
589
|
this.updateMainIndicatorParams(
|
|
590
590
|
instanceId,
|
|
591
591
|
params as Record<string, number | boolean | string>,
|
|
@@ -2,6 +2,8 @@ import type { PaneRole } from '../../foundation/plugin/index'
|
|
|
2
2
|
import type { ChartDom, PaneSpec, Viewport } from '../chartTypes'
|
|
3
3
|
import { PaneRenderer } from '../paneRenderer'
|
|
4
4
|
import type { ScaleType } from '../utils/tickPosition'
|
|
5
|
+
import type { PaneStateModule } from '../state/paneState'
|
|
6
|
+
import type { ViewportStateModule } from '../state/viewportState'
|
|
5
7
|
|
|
6
8
|
import { Pane, UpdateLevel } from './pane'
|
|
7
9
|
import { normalizeVisiblePaneRatios as pureNormalizeVisiblePaneRatios } from './paneRatioMath'
|
|
@@ -16,14 +18,15 @@ export interface PaneLayoutDependencies {
|
|
|
16
18
|
paneGap?: number
|
|
17
19
|
defaultPaneMinHeightPx?: number
|
|
18
20
|
}
|
|
19
|
-
|
|
21
|
+
/** scroll / plot 几何 SSOT */
|
|
22
|
+
viewport: ViewportStateModule
|
|
20
23
|
setKnownPaneIds: (ids: string[]) => void
|
|
21
24
|
notifyPaneResize: (paneId: string, pane: Pane) => void
|
|
22
25
|
scheduleDraw: (level?: UpdateLevel) => void
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
/** pane ratios / specs / scaleTypes SSOT */
|
|
27
|
+
pane: PaneStateModule
|
|
28
|
+
/** commitLayout 写入 kernel 后的副作用(如 ensurePaneScaleTypes) */
|
|
29
|
+
afterCommitLayout?: () => void
|
|
27
30
|
}
|
|
28
31
|
|
|
29
32
|
/**
|
|
@@ -63,7 +66,7 @@ export class ChartPaneLayout {
|
|
|
63
66
|
* 公共读:specs 结构来自工作副本定义,ratio 字段取自 kernel(不写工作副本)。
|
|
64
67
|
*/
|
|
65
68
|
getPaneSpecs(): PaneSpec[] {
|
|
66
|
-
const kernelRatios = this.deps.
|
|
69
|
+
const kernelRatios = this.deps.pane.readonly.paneRatios.peek()
|
|
67
70
|
return this._paneSpecs.map((spec) => ({
|
|
68
71
|
...spec,
|
|
69
72
|
ratio: kernelRatios[spec.id] ?? spec.ratio,
|
|
@@ -75,11 +78,11 @@ export class ChartPaneLayout {
|
|
|
75
78
|
* 公共读:直接返回 kernel paneRatios 副本,不触碰算法工作副本。
|
|
76
79
|
*/
|
|
77
80
|
getInternalPaneRatios(): Map<string, number> {
|
|
78
|
-
return new Map(Object.entries(this.deps.
|
|
81
|
+
return new Map(Object.entries(this.deps.pane.readonly.paneRatios.peek()))
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
private syncRatiosFromKernel(): void {
|
|
82
|
-
const kernelRatios = this.deps.
|
|
85
|
+
const kernelRatios = this.deps.pane.readonly.paneRatios.peek()
|
|
83
86
|
this._internalPaneRatios = new Map(Object.entries(kernelRatios))
|
|
84
87
|
}
|
|
85
88
|
|
|
@@ -100,17 +103,36 @@ export class ChartPaneLayout {
|
|
|
100
103
|
return index === 0 ? 'price' : 'indicator'
|
|
101
104
|
}
|
|
102
105
|
|
|
103
|
-
private createAxisCanvas(
|
|
106
|
+
private createAxisCanvas(
|
|
107
|
+
spec: PaneSpec,
|
|
108
|
+
side: 'left' | 'right',
|
|
109
|
+
kind: 'base' | 'overlay' = 'base',
|
|
110
|
+
): HTMLCanvasElement {
|
|
104
111
|
const canvas = document.createElement('canvas')
|
|
105
|
-
|
|
106
|
-
|
|
112
|
+
const isRight = side === 'right'
|
|
113
|
+
const isOverlay = kind === 'overlay'
|
|
114
|
+
canvas.id = `${spec.id}-${side}Axis${isOverlay ? 'Overlay' : ''}`
|
|
115
|
+
canvas.className = isRight
|
|
116
|
+
? isOverlay
|
|
117
|
+
? 'right-axis-overlay'
|
|
118
|
+
: 'right-axis'
|
|
119
|
+
: isOverlay
|
|
120
|
+
? 'left-axis-overlay'
|
|
121
|
+
: 'left-axis'
|
|
107
122
|
canvas.style.position = 'absolute'
|
|
108
123
|
canvas.style.left = '0'
|
|
124
|
+
if (isOverlay) {
|
|
125
|
+
canvas.style.pointerEvents = 'none'
|
|
126
|
+
canvas.style.backgroundColor = 'transparent'
|
|
127
|
+
canvas.style.zIndex = '1'
|
|
128
|
+
} else {
|
|
129
|
+
canvas.style.zIndex = '0'
|
|
130
|
+
}
|
|
109
131
|
return canvas
|
|
110
132
|
}
|
|
111
133
|
|
|
112
134
|
private initPanes() {
|
|
113
|
-
const kernelScaleTypes = this.deps.
|
|
135
|
+
const kernelScaleTypes = this.deps.pane.readonly.paneScaleTypes.peek()
|
|
114
136
|
const prevScaleTypes = new Map<string, ScaleType>()
|
|
115
137
|
for (const r of this.paneRenderers) {
|
|
116
138
|
prevScaleTypes.set(r.getPane().id, r.getPane().yAxis.getScaleType())
|
|
@@ -129,7 +151,8 @@ export class ChartPaneLayout {
|
|
|
129
151
|
|
|
130
152
|
const mainCanvas = document.createElement('canvas')
|
|
131
153
|
const overlayCanvas = document.createElement('canvas')
|
|
132
|
-
const yAxisCanvas = this.createAxisCanvas(spec,
|
|
154
|
+
const yAxisCanvas = this.createAxisCanvas(spec, 'right', 'base')
|
|
155
|
+
const yAxisOverlayCanvas = this.createAxisCanvas(spec, 'right', 'overlay')
|
|
133
156
|
|
|
134
157
|
const isMain = pane.role === 'price'
|
|
135
158
|
|
|
@@ -149,10 +172,18 @@ export class ChartPaneLayout {
|
|
|
149
172
|
overlayCanvas.style.backgroundColor = 'transparent'
|
|
150
173
|
overlayCanvas.style.zIndex = '2'
|
|
151
174
|
|
|
152
|
-
const leftYAxisCanvas = this.createAxisCanvas(spec,
|
|
175
|
+
const leftYAxisCanvas = this.createAxisCanvas(spec, 'left', 'base')
|
|
176
|
+
const leftYAxisOverlayCanvas = this.createAxisCanvas(spec, 'left', 'overlay')
|
|
153
177
|
|
|
154
178
|
const renderer = new PaneRenderer(
|
|
155
|
-
{
|
|
179
|
+
{
|
|
180
|
+
mainCanvas,
|
|
181
|
+
overlayCanvas,
|
|
182
|
+
yAxisCanvas,
|
|
183
|
+
yAxisOverlayCanvas,
|
|
184
|
+
leftYAxisCanvas,
|
|
185
|
+
leftYAxisOverlayCanvas,
|
|
186
|
+
},
|
|
156
187
|
pane,
|
|
157
188
|
{
|
|
158
189
|
rightAxisWidth: this.deps.getOption().rightAxisWidth,
|
|
@@ -177,11 +208,15 @@ export class ChartPaneLayout {
|
|
|
177
208
|
existingCanvases.forEach((canvas) => canvas.remove())
|
|
178
209
|
}
|
|
179
210
|
if (rightAxisLayer) {
|
|
180
|
-
const existingAxisCanvases = rightAxisLayer.querySelectorAll(
|
|
211
|
+
const existingAxisCanvases = rightAxisLayer.querySelectorAll(
|
|
212
|
+
'canvas.right-axis, canvas.right-axis-overlay',
|
|
213
|
+
)
|
|
181
214
|
existingAxisCanvases.forEach((canvas) => canvas.remove())
|
|
182
215
|
}
|
|
183
216
|
if (leftAxisLayer) {
|
|
184
|
-
const existingLeftAxisCanvases = leftAxisLayer.querySelectorAll(
|
|
217
|
+
const existingLeftAxisCanvases = leftAxisLayer.querySelectorAll(
|
|
218
|
+
'canvas.left-axis, canvas.left-axis-overlay',
|
|
219
|
+
)
|
|
185
220
|
existingLeftAxisCanvases.forEach((canvas) => canvas.remove())
|
|
186
221
|
}
|
|
187
222
|
|
|
@@ -190,8 +225,12 @@ export class ChartPaneLayout {
|
|
|
190
225
|
canvasLayer.appendChild(domEls.mainCanvas)
|
|
191
226
|
canvasLayer.appendChild(domEls.overlayCanvas)
|
|
192
227
|
rightAxisLayer.appendChild(domEls.yAxisCanvas)
|
|
228
|
+
rightAxisLayer.appendChild(domEls.yAxisOverlayCanvas)
|
|
193
229
|
if (leftAxisLayer && domEls.leftYAxisCanvas) {
|
|
194
230
|
leftAxisLayer.appendChild(domEls.leftYAxisCanvas)
|
|
231
|
+
if (domEls.leftYAxisOverlayCanvas) {
|
|
232
|
+
leftAxisLayer.appendChild(domEls.leftYAxisOverlayCanvas)
|
|
233
|
+
}
|
|
195
234
|
}
|
|
196
235
|
})
|
|
197
236
|
|
|
@@ -299,10 +338,16 @@ export class ChartPaneLayout {
|
|
|
299
338
|
return heights
|
|
300
339
|
}
|
|
301
340
|
|
|
341
|
+
/** viewWidth 为 0 表示尚未完成首帧尺寸 */
|
|
342
|
+
private peekViewport(): Viewport | null {
|
|
343
|
+
if (this.deps.viewport.readonly.viewWidth.peek() === 0) return null
|
|
344
|
+
return this.deps.viewport.readonly.viewport.peek()
|
|
345
|
+
}
|
|
346
|
+
|
|
302
347
|
layoutPanes(options?: { commit?: boolean }) {
|
|
303
348
|
this.syncRatiosFromKernel()
|
|
304
349
|
|
|
305
|
-
const vp = this.
|
|
350
|
+
const vp = this.peekViewport()
|
|
306
351
|
if (!vp) return
|
|
307
352
|
|
|
308
353
|
const visibleSpecs = this._paneSpecs.filter((p) => p.visible !== false)
|
|
@@ -338,10 +383,16 @@ export class ChartPaneLayout {
|
|
|
338
383
|
domEls.overlayCanvas.style.top = `${y}px`
|
|
339
384
|
domEls.yAxisCanvas.style.top = `${y}px`
|
|
340
385
|
domEls.yAxisCanvas.style.left = '0px'
|
|
386
|
+
domEls.yAxisOverlayCanvas.style.top = `${y}px`
|
|
387
|
+
domEls.yAxisOverlayCanvas.style.left = '0px'
|
|
341
388
|
if (domEls.leftYAxisCanvas) {
|
|
342
389
|
domEls.leftYAxisCanvas.style.top = `${y}px`
|
|
343
390
|
domEls.leftYAxisCanvas.style.left = '0px'
|
|
344
391
|
}
|
|
392
|
+
if (domEls.leftYAxisOverlayCanvas) {
|
|
393
|
+
domEls.leftYAxisOverlayCanvas.style.top = `${y}px`
|
|
394
|
+
domEls.leftYAxisOverlayCanvas.style.left = '0px'
|
|
395
|
+
}
|
|
345
396
|
|
|
346
397
|
y += h + gap
|
|
347
398
|
}
|
|
@@ -388,7 +439,7 @@ export class ChartPaneLayout {
|
|
|
388
439
|
* commitLayout 走 buildLayoutSpecsFromWorkingCopy,避免公共读污染算法中间态。
|
|
389
440
|
*/
|
|
390
441
|
getPaneLayoutSpecs(): PaneSpec[] {
|
|
391
|
-
return this.buildLayoutSpecs(this.deps.
|
|
442
|
+
return this.buildLayoutSpecs(this.deps.pane.readonly.paneRatios.peek())
|
|
392
443
|
}
|
|
393
444
|
|
|
394
445
|
/** 仅算法/commit 使用:读当前工作副本 ratios,不读 kernel */
|
|
@@ -422,7 +473,8 @@ export class ChartPaneLayout {
|
|
|
422
473
|
this._internalPaneRatios.forEach((ratio, id) => {
|
|
423
474
|
ratios[id] = ratio
|
|
424
475
|
})
|
|
425
|
-
this.deps.commitLayout(ratios, this.buildLayoutSpecsFromWorkingCopy())
|
|
476
|
+
this.deps.pane.actions.commitLayout(ratios, this.buildLayoutSpecsFromWorkingCopy())
|
|
477
|
+
this.deps.afterCommitLayout?.()
|
|
426
478
|
}
|
|
427
479
|
|
|
428
480
|
applyPaneLayoutSpecs(panes: PaneSpec[], options?: { preferIncomingRatios?: boolean }): void {
|
|
@@ -499,7 +551,7 @@ export class ChartPaneLayout {
|
|
|
499
551
|
|
|
500
552
|
resizePaneBoundary(upperPaneId: string, deltaY: number): boolean {
|
|
501
553
|
if (!Number.isFinite(deltaY) || deltaY === 0) return false
|
|
502
|
-
const vp = this.
|
|
554
|
+
const vp = this.peekViewport()
|
|
503
555
|
if (!vp) return false
|
|
504
556
|
|
|
505
557
|
this.syncRatiosFromKernel()
|
|
@@ -6,7 +6,9 @@ export type PaneRendererContexts = {
|
|
|
6
6
|
mainCtx: CanvasRenderingContext2D | null
|
|
7
7
|
overlayCtx: CanvasRenderingContext2D | null
|
|
8
8
|
yAxisCtx: CanvasRenderingContext2D | null
|
|
9
|
+
yAxisOverlayCtx: CanvasRenderingContext2D | null
|
|
9
10
|
leftAxisCtx: CanvasRenderingContext2D | null
|
|
11
|
+
leftAxisOverlayCtx: CanvasRenderingContext2D | null
|
|
10
12
|
}
|
|
11
13
|
|
|
12
14
|
export type PaneRendererOptions = {
|
|
@@ -17,7 +19,7 @@ export type PaneRendererOptions = {
|
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
/* PaneRenderer:负责单个 Pane 的 Canvas 管理与运行时状态持有
|
|
20
|
-
创建并管理
|
|
22
|
+
创建并管理 main/overlay/yAxis/yAxisOverlay(及可选 left 轴)canvas
|
|
21
23
|
持有 Pane 实例(布局、Y 轴、价格范围)
|
|
22
24
|
响应 Chart 的 resize / layout 信号
|
|
23
25
|
GPU 绘制经 ChartRenderer.sceneRenderer(SharedWebGLSurface),本类不再持有 per-pane surface */
|
|
@@ -52,7 +54,9 @@ export class PaneRenderer {
|
|
|
52
54
|
mainCtx: this.dom.mainCanvas.getContext('2d'),
|
|
53
55
|
overlayCtx: this.dom.overlayCanvas.getContext('2d'),
|
|
54
56
|
yAxisCtx: this.dom.yAxisCanvas.getContext('2d'),
|
|
57
|
+
yAxisOverlayCtx: this.dom.yAxisOverlayCanvas.getContext('2d'),
|
|
55
58
|
leftAxisCtx: this.dom.leftYAxisCanvas?.getContext('2d') ?? null,
|
|
59
|
+
leftAxisOverlayCtx: this.dom.leftYAxisOverlayCanvas?.getContext('2d') ?? null,
|
|
56
60
|
}
|
|
57
61
|
}
|
|
58
62
|
return this.contexts
|
|
@@ -90,6 +94,7 @@ export class PaneRenderer {
|
|
|
90
94
|
const mainCanvas = this.dom.mainCanvas
|
|
91
95
|
const overlayCanvas = this.dom.overlayCanvas
|
|
92
96
|
const yAxisCanvas = this.dom.yAxisCanvas
|
|
97
|
+
const yAxisOverlayCanvas = this.dom.yAxisOverlayCanvas
|
|
93
98
|
|
|
94
99
|
// 先读取 parentClientWidth,避免在写入样式后读取触发强制回流
|
|
95
100
|
const fallbackYAxisWidth = this.opt.rightAxisWidth + (this.opt.priceLabelWidth || 60)
|
|
@@ -104,22 +109,24 @@ export class PaneRenderer {
|
|
|
104
109
|
// Overlay Canvas - 与 Main Canvas 相同尺寸
|
|
105
110
|
PaneRenderer.resizeCanvas(overlayCanvas, mainWidth, mainHeight, dpr)
|
|
106
111
|
|
|
107
|
-
// YAxis Canvas
|
|
112
|
+
// YAxis Canvas + overlay 轴(同尺寸)
|
|
108
113
|
const yAxisWidth = Math.round(canvasYAxisWidth * dpr)
|
|
109
|
-
|
|
114
|
+
const yAxisHeight = Math.round(height * dpr)
|
|
115
|
+
PaneRenderer.resizeCanvas(yAxisCanvas, yAxisWidth, yAxisHeight, dpr)
|
|
116
|
+
PaneRenderer.resizeCanvas(yAxisOverlayCanvas, yAxisWidth, yAxisHeight, dpr)
|
|
110
117
|
|
|
111
|
-
// Left YAxis Canvas
|
|
118
|
+
// Left YAxis Canvas + overlay
|
|
112
119
|
const leftCanvas = this.dom.leftYAxisCanvas
|
|
120
|
+
const leftOverlayCanvas = this.dom.leftYAxisOverlayCanvas
|
|
113
121
|
if (leftCanvas) {
|
|
114
122
|
const fallbackLeftAxisWidth = this.opt.leftAxisWidth
|
|
115
123
|
const leftParentWidth = leftCanvas.parentElement?.clientWidth ?? 0
|
|
116
124
|
const canvasLeftAxisWidth = leftParentWidth > 0 ? leftParentWidth : fallbackLeftAxisWidth
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
)
|
|
125
|
+
const leftW = Math.round(Math.max(canvasLeftAxisWidth, 0) * dpr)
|
|
126
|
+
PaneRenderer.resizeCanvas(leftCanvas, leftW, yAxisHeight, dpr)
|
|
127
|
+
if (leftOverlayCanvas) {
|
|
128
|
+
PaneRenderer.resizeCanvas(leftOverlayCanvas, leftW, yAxisHeight, dpr)
|
|
129
|
+
}
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
132
|
|