@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
|
@@ -30,18 +30,13 @@ import { createDrawingRendererPlugin, createDrawingLabelOverlayPlugin } from '..
|
|
|
30
30
|
import { ChartIndicatorManager } from '../indicators/chartIndicatorManager'
|
|
31
31
|
import { UpdateLevel } from '../layout/pane'
|
|
32
32
|
import type { VisibleRange } from '../layout/pane'
|
|
33
|
-
import {
|
|
34
|
-
MarkerManager,
|
|
35
|
-
type CustomMarkerEntity,
|
|
36
|
-
type MarkerManagerDeps,
|
|
37
|
-
} from '../marker/registry'
|
|
33
|
+
import { MarkerManager, type CustomMarkerEntity, type MarkerManagerDeps } from '../marker/registry'
|
|
38
34
|
import type { ChartModeHandler } from '../modes/types'
|
|
39
35
|
import { PaneRenderer } from '../paneRenderer'
|
|
40
36
|
import { createTimeAxisRendererPlugin } from '../renderers/timeAxis'
|
|
41
37
|
import { getPhysicalKLineConfig } from '../utils/klineConfig'
|
|
42
38
|
import { calculateTickCount } from '../utils/tickCount'
|
|
43
|
-
|
|
44
|
-
import { getVisibleRange } from '../viewport/viewport'
|
|
39
|
+
|
|
45
40
|
|
|
46
41
|
import { createCandleLayer } from './layers/candleLayer'
|
|
47
42
|
import { createComparisonLineLayer } from './layers/comparisonLineLayer'
|
|
@@ -51,11 +46,21 @@ import { createExtremaMarkersLayer } from './layers/extremaMarkersLayer'
|
|
|
51
46
|
import { createGridLinesLayer } from './layers/gridLinesLayer'
|
|
52
47
|
import { createLastPriceLabelLayer } from './layers/lastPriceLabelLayer'
|
|
53
48
|
import { createLastPriceLineLayer } from './layers/lastPriceLineLayer'
|
|
54
|
-
import {
|
|
49
|
+
import {
|
|
50
|
+
createLeftYAxisOverlayLayer,
|
|
51
|
+
createLeftYAxisStaticLayer,
|
|
52
|
+
} from './layers/leftYAxisLayer'
|
|
55
53
|
import { createMainIndicatorLegendLayer } from './layers/mainIndicatorLegendLayer'
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
54
|
+
import { createYAxisOverlayLayer, createYAxisStaticLayer } from './layers/yAxisLayer'
|
|
55
|
+
import type { LayerRole } from '../../rendering/scene/types'
|
|
56
|
+
import {
|
|
57
|
+
createFrameTransaction,
|
|
58
|
+
type FrameTransaction,
|
|
59
|
+
} from '../../foundation/reactivity/frameTransaction'
|
|
58
60
|
import type { ReadonlySignal } from '../../foundation/reactivity/signal'
|
|
61
|
+
import type { ViewportStateModule } from '../state/viewportState'
|
|
62
|
+
import type { ZoomStateModule } from '../state/zoomState'
|
|
63
|
+
import type { OptionsStateModule } from '../state/optionsState'
|
|
59
64
|
|
|
60
65
|
type ResolvedChartOptions = Omit<ChartOptions, 'kWidth' | 'kGap'> & {
|
|
61
66
|
kWidth: number
|
|
@@ -89,15 +94,12 @@ type FrameContext = {
|
|
|
89
94
|
zoomLevelCount: number
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
/**
|
|
97
|
+
/** 帧事务输入:合并多次 scheduleDraw 的 level */
|
|
93
98
|
type FrameDrawInput = {
|
|
94
99
|
level: UpdateLevel
|
|
95
100
|
}
|
|
96
101
|
|
|
97
|
-
/**
|
|
98
|
-
* 帧事务快照:单代际绘制契约。
|
|
99
|
-
* generation 由 FrameTransaction 写入;frame 为 null 表示无可画数据。
|
|
100
|
-
*/
|
|
102
|
+
/** 单帧快照,frame 为 null 表示无可画数据 */
|
|
101
103
|
type FrameDrawSnapshot = {
|
|
102
104
|
generation: number
|
|
103
105
|
level: UpdateLevel
|
|
@@ -105,7 +107,7 @@ type FrameDrawSnapshot = {
|
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
/** Main 与 Overlay 合并为 All,其余取更全或后者 */
|
|
108
|
-
function mergeUpdateLevel(current: UpdateLevel, next: UpdateLevel): UpdateLevel {
|
|
110
|
+
export function mergeUpdateLevel(current: UpdateLevel, next: UpdateLevel): UpdateLevel {
|
|
109
111
|
if (current === UpdateLevel.All || next === UpdateLevel.All) return UpdateLevel.All
|
|
110
112
|
if (current === next) return current
|
|
111
113
|
if (
|
|
@@ -125,10 +127,14 @@ export interface RendererDependencies {
|
|
|
125
127
|
getSceneRenderer: () => Renderer
|
|
126
128
|
getPluginHost: () => PluginHostImpl
|
|
127
129
|
getRendererPluginManager: () => RendererPluginManager
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
/** 生效主题 SSOT */
|
|
131
|
+
theme$: ReadonlySignal<'light' | 'dark'>
|
|
132
|
+
/** zoomLevel / kWidth SSOT */
|
|
133
|
+
zoom: ZoomStateModule
|
|
134
|
+
/** zoomLevelCount 等 options SSOT */
|
|
135
|
+
options: OptionsStateModule
|
|
136
|
+
/** scroll / dpr / plot 几何 SSOT */
|
|
137
|
+
viewport: ViewportStateModule
|
|
132
138
|
getDataManager: () => ChartDataManager
|
|
133
139
|
getIndicatorManager: () => ChartIndicatorManager
|
|
134
140
|
getActiveMode: () => ChartModeHandler
|
|
@@ -137,6 +143,10 @@ export interface RendererDependencies {
|
|
|
137
143
|
drawings$: DrawingStoreDeps['drawings$']
|
|
138
144
|
selectedDrawingId$: DrawingStoreDeps['selectedDrawingId$']
|
|
139
145
|
getOverlay?: DrawingStoreDeps['getOverlay']
|
|
146
|
+
/** 主图图例上下文发布(canvas / external 均触发;draw 内回调) */
|
|
147
|
+
onLegendContext?: (
|
|
148
|
+
ctx: import('../renderers/Indicator/mainIndicatorLegendContext').LegendTemplateContext | null,
|
|
149
|
+
) => void
|
|
140
150
|
}
|
|
141
151
|
|
|
142
152
|
export class ChartRenderer {
|
|
@@ -147,14 +157,9 @@ export class ChartRenderer {
|
|
|
147
157
|
* 帧事务:scheduleDraw 只写输入并合并 rAF;flush 内 prepare → seal → paint。
|
|
148
158
|
* 绘制阶段不再反向写 kernel 几何(seal 在 render 回调最前、与 paint 同代)。
|
|
149
159
|
*/
|
|
150
|
-
private readonly frameTx:
|
|
151
|
-
typeof createFrameTransaction<FrameDrawInput, FrameDrawSnapshot>
|
|
152
|
-
>
|
|
160
|
+
private readonly frameTx: FrameTransaction<FrameDrawInput, FrameDrawSnapshot>
|
|
153
161
|
|
|
154
|
-
/**
|
|
155
|
-
* 与 frameTx pending 同步的重绘级别镜像。
|
|
156
|
-
* FrameTransaction 对 level 是浅覆盖,Main/Overlay 升格在此完成。
|
|
157
|
-
*/
|
|
162
|
+
/** 合并多次 scheduleDraw 的 level,合并后写入 frameTx */
|
|
158
163
|
private pendingLevel: UpdateLevel = UpdateLevel.All
|
|
159
164
|
|
|
160
165
|
/** 已排队的 rAF 句柄;null 表示当前没有挂起的帧调度 */
|
|
@@ -207,11 +212,13 @@ export class ChartRenderer {
|
|
|
207
212
|
render: (snapshot) => {
|
|
208
213
|
// generation 0 占位不绘制
|
|
209
214
|
if (snapshot.generation === 0) return
|
|
210
|
-
//
|
|
215
|
+
// 把本帧 K 线信息(kLinePositions,range,kWidthPx,kLineCenters)写入 InteractionController,保证 hover 命中与本帧一致
|
|
211
216
|
if (snapshot.frame) {
|
|
212
217
|
this.sealFrameGeometry(snapshot.frame)
|
|
213
218
|
}
|
|
219
|
+
// 用本帧几何将鼠标坐标吸附到最近 K 线,算出十字线位置
|
|
214
220
|
this.deps.getInteraction().flushPendingHover()
|
|
221
|
+
// 绘制:清 canvas → 构建 RenderContext → 遍历 pane 调 scene.paintPane → endFrame(GPU 一次性 submit 所有 pane)→ 时间轴
|
|
215
222
|
this.drawWithFrame(snapshot.level, snapshot.frame)
|
|
216
223
|
},
|
|
217
224
|
schedule: (run) => {
|
|
@@ -280,11 +287,15 @@ export class ChartRenderer {
|
|
|
280
287
|
this.scene.addLayer(layer)
|
|
281
288
|
}
|
|
282
289
|
{
|
|
283
|
-
const layer = createMainIndicatorLegendLayer(
|
|
284
|
-
{
|
|
290
|
+
const { layer, plugin } = createMainIndicatorLegendLayer(
|
|
291
|
+
{
|
|
292
|
+
yPaddingPx: opt.yPaddingPx,
|
|
293
|
+
onContext: this.deps.onLegendContext,
|
|
294
|
+
},
|
|
285
295
|
getCtx('main'),
|
|
286
|
-
this.deps.getPluginHost(),
|
|
287
296
|
)
|
|
297
|
+
// 注册进 Manager,使 updateRendererConfig('mainIndicatorLegend') 可切换 renderMode
|
|
298
|
+
this.deps.getRendererPluginManager().register(plugin)
|
|
288
299
|
this.scene.addLayer(layer)
|
|
289
300
|
}
|
|
290
301
|
{
|
|
@@ -302,42 +313,38 @@ export class ChartRenderer {
|
|
|
302
313
|
this.scene.addLayer(layer)
|
|
303
314
|
}
|
|
304
315
|
{
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return null
|
|
317
|
-
},
|
|
316
|
+
const yAxisOpts = {
|
|
317
|
+
axisWidth,
|
|
318
|
+
yPaddingPx: opt.yPaddingPx,
|
|
319
|
+
getCrosshair: () => {
|
|
320
|
+
const pos = interaction.crosshairPos
|
|
321
|
+
const price = interaction.crosshairPrice
|
|
322
|
+
const activePaneId = interaction.activePaneId
|
|
323
|
+
if (pos && price !== null) {
|
|
324
|
+
return { y: pos.y, price, activePaneId }
|
|
325
|
+
}
|
|
326
|
+
return null
|
|
318
327
|
},
|
|
319
|
-
|
|
320
|
-
)
|
|
321
|
-
this.scene.addLayer(
|
|
328
|
+
}
|
|
329
|
+
this.scene.addLayer(createYAxisStaticLayer(yAxisOpts, getCtxForCurrentPane))
|
|
330
|
+
this.scene.addLayer(createYAxisOverlayLayer(yAxisOpts, getCtxForCurrentPane))
|
|
322
331
|
}
|
|
323
332
|
{
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return null
|
|
336
|
-
},
|
|
333
|
+
const leftYAxisOpts = {
|
|
334
|
+
axisWidth: opt.leftAxisWidth,
|
|
335
|
+
yPaddingPx: opt.yPaddingPx,
|
|
336
|
+
getCrosshair: () => {
|
|
337
|
+
const pos = interaction.crosshairPos
|
|
338
|
+
const price = interaction.crosshairPrice
|
|
339
|
+
const activePaneId = interaction.activePaneId
|
|
340
|
+
if (pos && price !== null) {
|
|
341
|
+
return { y: pos.y, price, activePaneId }
|
|
342
|
+
}
|
|
343
|
+
return null
|
|
337
344
|
},
|
|
338
|
-
|
|
339
|
-
)
|
|
340
|
-
this.scene.addLayer(
|
|
345
|
+
}
|
|
346
|
+
this.scene.addLayer(createLeftYAxisStaticLayer(leftYAxisOpts, getCtxForCurrentPane))
|
|
347
|
+
this.scene.addLayer(createLeftYAxisOverlayLayer(leftYAxisOpts, getCtxForCurrentPane))
|
|
341
348
|
}
|
|
342
349
|
}
|
|
343
350
|
|
|
@@ -395,6 +402,7 @@ export class ChartRenderer {
|
|
|
395
402
|
* @param level - Main 只画主层,Overlay 只画覆盖层(crosshair 等),All 全画
|
|
396
403
|
*/
|
|
397
404
|
scheduleDraw(level: UpdateLevel = UpdateLevel.All): void {
|
|
405
|
+
// 已经有待执行的下一帧,只合并 level,不重复 scheduleFlush
|
|
398
406
|
if (this.raf !== null) {
|
|
399
407
|
this.pendingLevel = mergeUpdateLevel(this.pendingLevel, level)
|
|
400
408
|
this.frameTx.writeInput({ level: this.pendingLevel })
|
|
@@ -402,16 +410,16 @@ export class ChartRenderer {
|
|
|
402
410
|
}
|
|
403
411
|
this.pendingLevel = level
|
|
404
412
|
this.frameTx.writeInput({ level })
|
|
413
|
+
// 提交帧,下次 rAF 上屏
|
|
405
414
|
this.frameTx.scheduleFlush()
|
|
406
415
|
}
|
|
407
416
|
|
|
408
417
|
/**
|
|
409
|
-
*
|
|
410
|
-
*
|
|
411
|
-
* 若已有 rAF 挂起:与 pendingLevel 合并后同步 flush(消费合并后的 level)。
|
|
412
|
-
* 若正处于帧事务非 idle(render/publish 重入):只写输入并调度下一帧,禁止嵌套 flush。
|
|
418
|
+
* 立即同步重绘一帧,不走 rAF。
|
|
413
419
|
*
|
|
414
|
-
*
|
|
420
|
+
* 若已有 rAF 挂起:合并本次 level 后同步 flush,把挂起的也带走。
|
|
421
|
+
* 若正处于帧事务非 idle(paint 重入中):只写输入,调度下一帧,不嵌套 flush。
|
|
422
|
+
* 与 scheduleDraw 的唯一区别:同步还是异步。
|
|
415
423
|
*/
|
|
416
424
|
draw(level: UpdateLevel = UpdateLevel.All): void {
|
|
417
425
|
if (this.frameTx.phase !== 'idle') {
|
|
@@ -428,10 +436,6 @@ export class ChartRenderer {
|
|
|
428
436
|
}
|
|
429
437
|
this.frameTx.writeInput({ level: this.pendingLevel })
|
|
430
438
|
this.frameTx.flush()
|
|
431
|
-
// 同步 flush 已消费本帧;若 flush 中又 scheduleDraw,raf 非 null,保留 pendingLevel
|
|
432
|
-
if (this.raf === null) {
|
|
433
|
-
this.pendingLevel = UpdateLevel.All
|
|
434
|
-
}
|
|
435
439
|
}
|
|
436
440
|
|
|
437
441
|
/**
|
|
@@ -444,9 +448,11 @@ export class ChartRenderer {
|
|
|
444
448
|
.setKLinePositions(frame.kLinePositions, frame.range, frame.kWidthPx, frame.kLineCenters)
|
|
445
449
|
}
|
|
446
450
|
|
|
451
|
+
/** 将 prepareFrameData 的帧几何按 level 画到 canvas,含所有 pane 的 main/overlay/yAxis 及时间轴 */
|
|
447
452
|
private drawWithFrame(level: UpdateLevel, frame: FrameContext | null): void {
|
|
448
453
|
this.markerManager.clear()
|
|
449
454
|
|
|
455
|
+
// frame 为空(无数据或首帧),清理画布后跳过绘制
|
|
450
456
|
if (!frame) {
|
|
451
457
|
const dataManager = this.deps.getDataManager()
|
|
452
458
|
if (dataManager.getInternalData().length === 0 && dataManager.getTimeShareData().length === 0)
|
|
@@ -459,7 +465,9 @@ export class ChartRenderer {
|
|
|
459
465
|
const dataManager = this.deps.getDataManager()
|
|
460
466
|
const mode = this.deps.getActiveMode()
|
|
461
467
|
if (mode.useIndicatorScheduler) {
|
|
468
|
+
// 获取指标管理器实例(持有 scheduler、状态、reconcile 逻辑)
|
|
462
469
|
const indicatorManager = this.deps.getIndicatorManager()
|
|
470
|
+
// 将主图指标列表(含参数)同步给 scheduler,使其在本帧预计算价格区间
|
|
463
471
|
indicatorManager.indicatorSchedulerAccessor.setActiveMainIndicators(
|
|
464
472
|
[...indicatorManager.mainIndicatorsSignalPeek.entries()].map(([id, entry]) => ({
|
|
465
473
|
id,
|
|
@@ -474,13 +482,13 @@ export class ChartRenderer {
|
|
|
474
482
|
|
|
475
483
|
const renderData = frame.data
|
|
476
484
|
|
|
485
|
+
// 遍历所有 pane,清 canvas → 构建 RenderContext → scene.paintPane
|
|
477
486
|
const { sharedXAxisLabels, sharedXAxisRanges } = this.renderPanes(
|
|
478
487
|
vp,
|
|
479
488
|
range,
|
|
480
489
|
kLinePositions,
|
|
481
490
|
kLineCenters,
|
|
482
491
|
kBarRects,
|
|
483
|
-
kWidthPx,
|
|
484
492
|
mainIndicatorRange,
|
|
485
493
|
hasCrosshair,
|
|
486
494
|
useCachedFrame,
|
|
@@ -489,6 +497,7 @@ export class ChartRenderer {
|
|
|
489
497
|
)
|
|
490
498
|
|
|
491
499
|
this.overlayHadCrosshair = hasCrosshair
|
|
500
|
+
// 画底部时间轴(独立 layer,不进 scene)
|
|
492
501
|
this.renderXAxis(
|
|
493
502
|
vp,
|
|
494
503
|
range,
|
|
@@ -503,42 +512,35 @@ export class ChartRenderer {
|
|
|
503
512
|
}
|
|
504
513
|
|
|
505
514
|
/**
|
|
506
|
-
*
|
|
515
|
+
* 计算一帧的 viewport、可见区间、K 线位置。
|
|
507
516
|
*
|
|
508
|
-
* Overlay
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
* TimeShare 模式按 plotWidth 平分 bar,不走 K 线物理宽度那套。
|
|
512
|
-
*
|
|
513
|
-
* @param level - Overlay 可走缓存,Main/All 强制重算
|
|
514
|
-
* @returns 无 viewport 或无数据时返回 null,调用方自己清屏或跳过
|
|
517
|
+
* Overlay 时复用 cachedDrawFrame 跳过重算,Main/All 强制刷新缓存。
|
|
518
|
+
* range 变化时调 checkVisibleRangeGapWhenIdle 触发空闲补数据。
|
|
519
|
+
* TimeShare 模式按 plotWidth 平分 bar,覆盖 K 线位置。
|
|
515
520
|
*/
|
|
521
|
+
/** viewWidth 为 0 表示尚未完成首帧尺寸 */
|
|
522
|
+
private peekViewport(): Viewport | null {
|
|
523
|
+
if (this.deps.viewport.readonly.viewWidth.peek() === 0) return null
|
|
524
|
+
return this.deps.viewport.readonly.viewport.peek()
|
|
525
|
+
}
|
|
526
|
+
|
|
516
527
|
private prepareFrameData(level: UpdateLevel): FrameContext | null {
|
|
517
528
|
const useCachedFrame = level === UpdateLevel.Overlay && this.cachedDrawFrame !== null
|
|
518
529
|
|
|
519
|
-
const vp = useCachedFrame
|
|
520
|
-
? this.cachedDrawFrame!.viewport
|
|
521
|
-
: this.deps.getViewportManager().computeViewport()
|
|
530
|
+
const vp = useCachedFrame ? this.cachedDrawFrame!.viewport : this.peekViewport()
|
|
522
531
|
if (!vp) return null
|
|
523
532
|
|
|
524
533
|
const internalData = this.deps.getDataManager().getRenderData() as KLineData[]
|
|
525
534
|
if (internalData.length === 0) return null
|
|
526
535
|
|
|
527
536
|
const opt = this.deps.getOption()
|
|
528
|
-
|
|
537
|
+
// 可见区间 SSOT 在 viewportState:clamped 可索引;raw 含扩窗(start 可能为 -1)
|
|
538
|
+
const range = useCachedFrame
|
|
529
539
|
? this.cachedDrawFrame!.range
|
|
530
|
-
: (
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
opt.kWidth,
|
|
535
|
-
opt.kGap,
|
|
536
|
-
internalData.length,
|
|
537
|
-
vp.dpr,
|
|
538
|
-
)
|
|
539
|
-
return { start, end }
|
|
540
|
-
})()
|
|
541
|
-
const range = { start: Math.max(0, rawRange.start), end: rawRange.end }
|
|
540
|
+
: this.deps.viewport.readonly.visibleRange.peek()
|
|
541
|
+
const rawRange = useCachedFrame
|
|
542
|
+
? (this._prevFrameRange?.raw ?? range)
|
|
543
|
+
: this.deps.viewport.readonly.rawVisibleRange.peek()
|
|
542
544
|
|
|
543
545
|
const dataManager = this.deps.getDataManager()
|
|
544
546
|
const mode = this.deps.getActiveMode()
|
|
@@ -568,6 +570,7 @@ export class ChartRenderer {
|
|
|
568
570
|
kWidthPx = this.cachedDrawFrame!.kWidthPx
|
|
569
571
|
} else {
|
|
570
572
|
const physConfig = getPhysicalKLineConfig(opt.kWidth, opt.kGap, vp.dpr)
|
|
573
|
+
// bar 宽度取奇数,保证 center 对齐整数像素
|
|
571
574
|
let barWidthPx = Math.max(1, physConfig.unitPx - 1)
|
|
572
575
|
if (barWidthPx % 2 === 0) barWidthPx -= 1
|
|
573
576
|
|
|
@@ -577,6 +580,7 @@ export class ChartRenderer {
|
|
|
577
580
|
for (let i = 0; i < kLinePositions.length; i++) {
|
|
578
581
|
const x = kLinePositions[i]!
|
|
579
582
|
const leftPx = Math.round(x * vp.dpr)
|
|
583
|
+
// 影线 center = left + 半根物理宽度
|
|
580
584
|
const wickXPx = leftPx + (physConfig.kWidthPx - 1) / 2
|
|
581
585
|
kLineCenters[i] = wickXPx / vp.dpr
|
|
582
586
|
|
|
@@ -584,6 +588,7 @@ export class ChartRenderer {
|
|
|
584
588
|
kBarRects[i] = { x: barLeftPx / vp.dpr, width: barWidthPx / vp.dpr }
|
|
585
589
|
}
|
|
586
590
|
|
|
591
|
+
// TimeShare 按 plotWidth 平分 bar,覆盖 calcKLinePositions 的结果
|
|
587
592
|
if (mode.debugName === 'TimeShare') {
|
|
588
593
|
const totalWidth = vp.plotWidth
|
|
589
594
|
const count = kLineCenters.length
|
|
@@ -600,7 +605,7 @@ export class ChartRenderer {
|
|
|
600
605
|
const barWidthPx = Math.round(logicalBarWidth * dpr)
|
|
601
606
|
const halfBarPx = Math.floor(barWidthPx / 2)
|
|
602
607
|
for (let i = 0; i < count; i++) {
|
|
603
|
-
const centerPx = Math.round(kLineCenters[i] * dpr)
|
|
608
|
+
const centerPx = Math.round(kLineCenters[i]! * dpr)
|
|
604
609
|
kBarRects[i] = {
|
|
605
610
|
x: (centerPx - halfBarPx) / dpr,
|
|
606
611
|
width: barWidthPx / dpr,
|
|
@@ -631,8 +636,8 @@ export class ChartRenderer {
|
|
|
631
636
|
kWidthPx,
|
|
632
637
|
useCachedFrame,
|
|
633
638
|
data: internalData,
|
|
634
|
-
zoomLevel: this.deps.
|
|
635
|
-
zoomLevelCount: this.deps.
|
|
639
|
+
zoomLevel: this.deps.zoom.readonly.zoomLevel.peek(),
|
|
640
|
+
zoomLevelCount: this.deps.options.readonly.options.peek().zoomLevelCount,
|
|
636
641
|
}
|
|
637
642
|
}
|
|
638
643
|
|
|
@@ -648,20 +653,28 @@ export class ChartRenderer {
|
|
|
648
653
|
}
|
|
649
654
|
|
|
650
655
|
clearAllCanvases(): void {
|
|
651
|
-
const vp = this.
|
|
656
|
+
const vp = this.peekViewport()
|
|
652
657
|
if (!vp) return
|
|
653
658
|
for (const r of this.deps.getPaneRenderers()) {
|
|
654
|
-
const { mainCtx, overlayCtx, yAxisCtx, leftAxisCtx } =
|
|
659
|
+
const { mainCtx, overlayCtx, yAxisCtx, yAxisOverlayCtx, leftAxisCtx, leftAxisOverlayCtx } =
|
|
660
|
+
r.getContexts()
|
|
655
661
|
const pane = r.getPane()
|
|
656
662
|
mainCtx?.clearRect(0, 0, vp.plotWidth + 1, pane.height + 2 / vp.dpr)
|
|
657
663
|
overlayCtx?.clearRect(0, 0, vp.plotWidth + 1, pane.height + 2 / vp.dpr)
|
|
658
|
-
yAxisCtx?.clearRect(0, 0, vp.plotWidth + 1, pane.height + 2 / vp.dpr)
|
|
664
|
+
yAxisCtx?.clearRect(0, 0, (yAxisCtx.canvas?.width ?? 0) / vp.dpr || vp.plotWidth + 1, pane.height + 2 / vp.dpr)
|
|
665
|
+
yAxisOverlayCtx?.clearRect(
|
|
666
|
+
0,
|
|
667
|
+
0,
|
|
668
|
+
(yAxisOverlayCtx.canvas?.width ?? 0) / vp.dpr || vp.plotWidth + 1,
|
|
669
|
+
pane.height + 2 / vp.dpr,
|
|
670
|
+
)
|
|
659
671
|
if (leftAxisCtx) {
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
672
|
+
const laW = (leftAxisCtx.canvas?.width ?? 0) / vp.dpr || vp.plotWidth + 1
|
|
673
|
+
leftAxisCtx.clearRect(0, 0, laW, pane.height + 2 / vp.dpr)
|
|
674
|
+
}
|
|
675
|
+
if (leftAxisOverlayCtx) {
|
|
676
|
+
const laW = (leftAxisOverlayCtx.canvas?.width ?? 0) / vp.dpr || vp.plotWidth + 1
|
|
677
|
+
leftAxisOverlayCtx.clearRect(0, 0, laW, pane.height + 2 / vp.dpr)
|
|
665
678
|
}
|
|
666
679
|
}
|
|
667
680
|
const xCtx = this.xAxisCtx
|
|
@@ -683,19 +696,20 @@ export class ChartRenderer {
|
|
|
683
696
|
}
|
|
684
697
|
}
|
|
685
698
|
|
|
699
|
+
/** 遍历所有 pane,逐 pane 清 canvas → 构建 RenderContext → beginFrame → scene.paintPane,所有 pane 结束后 endFrame 统一提交 GPU / 时间轴 */
|
|
686
700
|
private renderPanes(
|
|
687
701
|
vp: Viewport,
|
|
688
702
|
range: VisibleRange,
|
|
689
703
|
kLinePositions: KLinePositions,
|
|
690
704
|
kLineCenters: number[],
|
|
691
705
|
kBarRects: Array<{ x: number; width: number }>,
|
|
692
|
-
kWidthPx: number,
|
|
693
706
|
mainIndicatorRange: { min: number; max: number } | null,
|
|
694
707
|
hasCrosshair: boolean,
|
|
695
708
|
useCachedFrame: boolean,
|
|
696
709
|
level: UpdateLevel,
|
|
697
710
|
renderData: unknown[],
|
|
698
711
|
): { sharedXAxisLabels: XAxisLabel[]; sharedXAxisRanges: XAxisRange[] } {
|
|
712
|
+
// 跨 pane 共享的 Y/X 轴 labels 和 ranges(各 layer 写入,时间轴层读取)
|
|
699
713
|
const sharedYAxisLabels: YAxisLabel[] = []
|
|
700
714
|
const sharedXAxisLabels: XAxisLabel[] = []
|
|
701
715
|
const sharedYAxisRanges: YAxisRange[] = []
|
|
@@ -704,10 +718,28 @@ export class ChartRenderer {
|
|
|
704
718
|
const dataManager = this.deps.getDataManager()
|
|
705
719
|
const mode = this.deps.getActiveMode()
|
|
706
720
|
|
|
721
|
+
// main canvas 只画非 overlay 角色;overlay canvas 只画 overlay 角色
|
|
722
|
+
const MAIN_CANVAS_ROLES: readonly LayerRole[] = [
|
|
723
|
+
'background',
|
|
724
|
+
'primary',
|
|
725
|
+
'indicator',
|
|
726
|
+
'component',
|
|
727
|
+
'drawing',
|
|
728
|
+
]
|
|
729
|
+
|
|
730
|
+
// 遍历主图 pane 和所有子图 pane,每个 pane 有一组独立 canvas 以及对应更新级别(main/overlay/yAxis)
|
|
707
731
|
for (const renderer of this.deps.getPaneRenderers()) {
|
|
708
732
|
const pane = renderer.getPane()
|
|
709
|
-
const {
|
|
710
|
-
|
|
733
|
+
const {
|
|
734
|
+
mainCtx,
|
|
735
|
+
overlayCtx,
|
|
736
|
+
yAxisCtx,
|
|
737
|
+
yAxisOverlayCtx,
|
|
738
|
+
leftAxisCtx,
|
|
739
|
+
leftAxisOverlayCtx,
|
|
740
|
+
} = renderer.getContexts()
|
|
741
|
+
|
|
742
|
+
// 非缓存帧:合并指标与对比标的极值,更新 pane Y 轴范围
|
|
711
743
|
if (!useCachedFrame) {
|
|
712
744
|
const indicatorRange =
|
|
713
745
|
pane.role === 'price' && mode.useIndicatorScheduler ? mainIndicatorRange : null
|
|
@@ -720,17 +752,21 @@ export class ChartRenderer {
|
|
|
720
752
|
}
|
|
721
753
|
}
|
|
722
754
|
|
|
755
|
+
// 根据 UpdateLevel 决定清哪些 canvas
|
|
723
756
|
const shouldUpdateMain = level === UpdateLevel.Main || level === UpdateLevel.All
|
|
757
|
+
// Overlay 单独重绘:有十字线才画;overlayHadCrosshair 保证十字线消失时最后清一次
|
|
724
758
|
const shouldUpdateOverlay =
|
|
725
759
|
level === UpdateLevel.All ||
|
|
726
760
|
(level === UpdateLevel.Overlay && (hasCrosshair || this.overlayHadCrosshair))
|
|
727
761
|
|
|
762
|
+
// 清 main canvas
|
|
728
763
|
if (shouldUpdateMain && mainCtx) {
|
|
729
764
|
mainCtx.setTransform(1, 0, 0, 1, 0, 0)
|
|
730
765
|
mainCtx.scale(vp.dpr, vp.dpr)
|
|
731
766
|
mainCtx.clearRect(0, 0, vp.plotWidth + 1, pane.height + 2 / vp.dpr)
|
|
732
767
|
}
|
|
733
768
|
|
|
769
|
+
// 清 overlay canvas
|
|
734
770
|
if (shouldUpdateOverlay && overlayCtx) {
|
|
735
771
|
const overlayWidth = overlayCtx.canvas.width / vp.dpr
|
|
736
772
|
overlayCtx.setTransform(1, 0, 0, 1, 0, 0)
|
|
@@ -738,15 +774,26 @@ export class ChartRenderer {
|
|
|
738
774
|
overlayCtx.clearRect(0, 0, overlayWidth + 1, pane.height + 2 / vp.dpr)
|
|
739
775
|
}
|
|
740
776
|
|
|
741
|
-
|
|
777
|
+
// 清 Y 轴静态 canvas(Main/All)
|
|
778
|
+
if (shouldUpdateMain && yAxisCtx) {
|
|
742
779
|
const yAxisWidth = yAxisCtx.canvas.width / vp.dpr
|
|
743
780
|
this.clearAxisCtx(yAxisCtx, vp.dpr, yAxisWidth, pane.height)
|
|
744
781
|
}
|
|
745
|
-
if (
|
|
782
|
+
if (shouldUpdateMain && leftAxisCtx) {
|
|
746
783
|
const leftAxisWidth = leftAxisCtx.canvas.width / vp.dpr
|
|
747
784
|
this.clearAxisCtx(leftAxisCtx, vp.dpr, leftAxisWidth, pane.height)
|
|
748
785
|
}
|
|
786
|
+
// 清 Y 轴动态 canvas(Overlay/All)
|
|
787
|
+
if (shouldUpdateOverlay && yAxisOverlayCtx) {
|
|
788
|
+
const yAxisWidth = yAxisOverlayCtx.canvas.width / vp.dpr
|
|
789
|
+
this.clearAxisCtx(yAxisOverlayCtx, vp.dpr, yAxisWidth, pane.height)
|
|
790
|
+
}
|
|
791
|
+
if (shouldUpdateOverlay && leftAxisOverlayCtx) {
|
|
792
|
+
const leftAxisWidth = leftAxisOverlayCtx.canvas.width / vp.dpr
|
|
793
|
+
this.clearAxisCtx(leftAxisOverlayCtx, vp.dpr, leftAxisWidth, pane.height)
|
|
794
|
+
}
|
|
749
795
|
|
|
796
|
+
// 构造本 pane 的 RenderContext,供所有 layer 读取
|
|
750
797
|
const opt = this.deps.getOption()
|
|
751
798
|
const context: RenderContext = {
|
|
752
799
|
ctx: mainCtx!,
|
|
@@ -769,9 +816,11 @@ export class ChartRenderer {
|
|
|
769
816
|
markerManager: this.markerManager,
|
|
770
817
|
crosshairIndex: this.deps.getInteraction().getCrosshairIndex(),
|
|
771
818
|
yAxisCtx: yAxisCtx ?? undefined,
|
|
819
|
+
yAxisOverlayCtx: yAxisOverlayCtx ?? undefined,
|
|
772
820
|
leftAxisCtx: leftAxisCtx ?? undefined,
|
|
773
|
-
|
|
774
|
-
|
|
821
|
+
leftAxisOverlayCtx: leftAxisOverlayCtx ?? undefined,
|
|
822
|
+
zoomLevel: this.deps.zoom.readonly.zoomLevel.peek(),
|
|
823
|
+
zoomLevelCount: this.deps.options.readonly.options.peek().zoomLevelCount,
|
|
775
824
|
viewport: {
|
|
776
825
|
scrollLeft: vp.scrollLeft,
|
|
777
826
|
plotWidth: vp.plotWidth,
|
|
@@ -782,13 +831,14 @@ export class ChartRenderer {
|
|
|
782
831
|
xAxisLabels: sharedXAxisLabels,
|
|
783
832
|
yAxisRanges: sharedYAxisRanges,
|
|
784
833
|
xAxisRanges: sharedXAxisRanges,
|
|
785
|
-
theme: this.deps.
|
|
834
|
+
theme: this.deps.theme$.peek(),
|
|
786
835
|
isAsiaMarket: this.settings.isAsiaMarket as boolean,
|
|
787
836
|
colorPresetSettings: this.settings.colorPresetSettings,
|
|
788
837
|
monthKeys: dataManager.getMonthKeys() ?? undefined,
|
|
789
838
|
dayKeys: dataManager.getDayKeys() ?? undefined,
|
|
790
839
|
}
|
|
791
840
|
|
|
841
|
+
// 计算本 pane 的 Y 轴刻度(等分 + yToPrice 映射)
|
|
792
842
|
{
|
|
793
843
|
const pt = pane.yAxis.getPaddingTop()
|
|
794
844
|
const pb = pane.yAxis.getPaddingBottom()
|
|
@@ -811,24 +861,32 @@ export class ChartRenderer {
|
|
|
811
861
|
|
|
812
862
|
const region = { x: 0, y: pane.top, width: vp.plotWidth, height: pane.height, dpr: vp.dpr }
|
|
813
863
|
const sceneRenderer = this.deps.getSceneRenderer()
|
|
864
|
+
const paneRole = (pane.id === 'main' ? 'main' : 'sub') as PaneRole
|
|
865
|
+
// 画 main canvas(非 overlay 角色 layer)
|
|
814
866
|
if (shouldUpdateMain) {
|
|
867
|
+
// 标记后续 GPU 绘制属于此 region
|
|
815
868
|
sceneRenderer.beginFrame(region)
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
869
|
+
// 遍历 Scene 中该 pane 的可见 layer,逐层 paint
|
|
870
|
+
this.scene.paintPane(
|
|
871
|
+
{
|
|
872
|
+
renderer: sceneRenderer,
|
|
873
|
+
region,
|
|
874
|
+
paneRole,
|
|
875
|
+
paneId: pane.id,
|
|
876
|
+
frameNumber: this.frameCount++,
|
|
877
|
+
deltaMs: 0,
|
|
878
|
+
},
|
|
879
|
+
MAIN_CANVAS_ROLES,
|
|
880
|
+
)
|
|
824
881
|
}
|
|
825
|
-
|
|
882
|
+
// 画 overlay canvas(仅 overlay 角色 layer);All 级也画
|
|
883
|
+
if (shouldUpdateOverlay) {
|
|
826
884
|
sceneRenderer.beginFrame(region)
|
|
827
885
|
this.scene.paintPane(
|
|
828
886
|
{
|
|
829
887
|
renderer: sceneRenderer,
|
|
830
888
|
region,
|
|
831
|
-
paneRole
|
|
889
|
+
paneRole,
|
|
832
890
|
paneId: pane.id,
|
|
833
891
|
frameNumber: this.frameCount++,
|
|
834
892
|
deltaMs: 0,
|
|
@@ -838,7 +896,7 @@ export class ChartRenderer {
|
|
|
838
896
|
}
|
|
839
897
|
}
|
|
840
898
|
|
|
841
|
-
//
|
|
899
|
+
// 所有 pane 绘制完成后统一提交 GPU(WebGPU 单次 queue.submit,WebGL 单次 flush)
|
|
842
900
|
this.deps.getSceneRenderer().endFrame()
|
|
843
901
|
|
|
844
902
|
return { sharedXAxisLabels, sharedXAxisRanges }
|
|
@@ -911,7 +969,7 @@ export class ChartRenderer {
|
|
|
911
969
|
yAxisLabels: [],
|
|
912
970
|
xAxisLabels: sharedXAxisLabels,
|
|
913
971
|
xAxisRanges: sharedXAxisRanges,
|
|
914
|
-
theme: this.deps.
|
|
972
|
+
theme: this.deps.theme$.peek(),
|
|
915
973
|
isAsiaMarket: this.settings.isAsiaMarket as boolean,
|
|
916
974
|
colorPresetSettings: this.settings.colorPresetSettings,
|
|
917
975
|
monthKeys: dataManager.getMonthKeys() ?? undefined,
|
|
@@ -935,7 +993,7 @@ export class ChartRenderer {
|
|
|
935
993
|
|
|
936
994
|
if (count <= 0) return []
|
|
937
995
|
|
|
938
|
-
const dpr = this.deps.
|
|
996
|
+
const dpr = this.deps.viewport.readonly.dpr.peek()
|
|
939
997
|
const opt = this.deps.getOption()
|
|
940
998
|
const { unitPx, startXPx } = getPhysicalKLineConfig(opt.kWidth, opt.kGap, dpr)
|
|
941
999
|
|