@baron1996/klinecharts-adapter 0.9.18 → 0.9.20
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/adapter.d.ts.map +1 -1
- package/dist/adapter.js +46 -2
- package/dist/conversion/indicators.d.ts +4 -1
- package/dist/conversion/indicators.d.ts.map +1 -1
- package/dist/conversion/indicators.js +17 -8
- package/dist/interaction/dragging.d.ts +3 -2
- package/dist/interaction/dragging.d.ts.map +1 -1
- package/dist/interaction/dragging.js +114 -31
- package/dist/interaction/selection-anchors.d.ts +12 -0
- package/dist/interaction/selection-anchors.d.ts.map +1 -0
- package/dist/interaction/selection-anchors.js +73 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,UAAU,EAEV,OAAO,EACP,UAAU,EACV,cAAc,EACd,YAAY,EACZ,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGN,UAAU,EACV,MAAM,+BAA+B,CAAC;AAYvC,OAAO,EAKN,KAAK,oBAAoB,EAGzB,MAAM,0BAA0B,CAAC;AAoBlC,OAAO,KAAK,EACX,yBAAyB,EACzB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,yBAAyB,EACzB,0BAA0B,EAC1B,gCAAgC,EAChC,2BAA2B,EAC3B,qBAAqB,EACrB,qBAAqB,EACrB,wBAAwB,EACxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAKN,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,MAAM,+BAA+B,CAAC;AAKvC,OAAO,EAKN,KAAK,gBAAgB,EAErB,KAAK,eAAe,EACpB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
CHANGED
|
@@ -17,6 +17,7 @@ import { createDragCandidate, } from './interaction/dragging.js';
|
|
|
17
17
|
import { DEFAULT_OVERLAY_MOUSE_HIT_TOLERANCE, DEFAULT_OVERLAY_TOUCH_HIT_TOLERANCE, hitTestOverlayGeometries, } from './interaction/hit-testing.js';
|
|
18
18
|
import { projectOverlayGeometry } from './interaction/overlay-geometry.js';
|
|
19
19
|
import { shouldIgnoreStaleOverlayDeselection } from './interaction/selection-arbitration.js';
|
|
20
|
+
import { SelectionAnchorLayer } from './interaction/selection-anchors.js';
|
|
20
21
|
import { isTouchPrecisionTap, resolveTouchPrecisionCursor, TouchPrecisionDrawingGuide, } from './interaction/touch-precision-drawing.js';
|
|
21
22
|
import { KLINECHARTS_ENGINE_VERSION, KLINECHARTS_RUNTIME_VERSION, } from './version.js';
|
|
22
23
|
function promoteSceneToM2(scene, scale) {
|
|
@@ -145,6 +146,8 @@ export class KLineChartsSceneAdapter {
|
|
|
145
146
|
#drawingInProgressId = null;
|
|
146
147
|
/** 宿主显式开启的 Drawing 输入策略;未配置时保持引擎原生行为。 */
|
|
147
148
|
#drawingInteraction;
|
|
149
|
+
/** 独占交互下由 Baron 持续维护的选中 Drawing 锚点层。 */
|
|
150
|
+
#selectionAnchors;
|
|
148
151
|
/** 触摸精确绘制的通用提示与虚拟光标层。 */
|
|
149
152
|
#touchPrecisionGuide;
|
|
150
153
|
/** 当前允许切换到触摸精确交互的线段绘制。 */
|
|
@@ -195,6 +198,9 @@ export class KLineChartsSceneAdapter {
|
|
|
195
198
|
this.#idMap = idMap;
|
|
196
199
|
this.#originalBackground = originalBackground;
|
|
197
200
|
this.#drawingInteraction = structuredClone(drawingInteraction);
|
|
201
|
+
if (this.#drawingInteraction.exclusiveSelection === true) {
|
|
202
|
+
this.#selectionAnchors = new SelectionAnchorLayer(container, () => this.#renderSelectionAnchors());
|
|
203
|
+
}
|
|
198
204
|
this.#emptyRuntime = emptyRuntime;
|
|
199
205
|
this.#displayTimezone = displayTimezone;
|
|
200
206
|
this.#mutationsEnabled = !emptyRuntime;
|
|
@@ -295,6 +301,7 @@ export class KLineChartsSceneAdapter {
|
|
|
295
301
|
this.#scene = candidate;
|
|
296
302
|
this.#emptyRuntime = false;
|
|
297
303
|
this.#mutationsEnabled = true;
|
|
304
|
+
this.#renderSelectionAnchors();
|
|
298
305
|
return structuredClone(candidate);
|
|
299
306
|
}
|
|
300
307
|
static async create(container, value) {
|
|
@@ -387,12 +394,14 @@ export class KLineChartsSceneAdapter {
|
|
|
387
394
|
if (this.#workspaceMode) {
|
|
388
395
|
this.#workspaceOverlays = structuredClone(next);
|
|
389
396
|
this.#syncWorkspaceSources();
|
|
397
|
+
this.#renderSelectionAnchors();
|
|
390
398
|
return;
|
|
391
399
|
}
|
|
392
400
|
this.#scene = parseChartScene({
|
|
393
401
|
...structuredClone(this.#scene),
|
|
394
402
|
overlays: structuredClone(next),
|
|
395
403
|
});
|
|
404
|
+
this.#renderSelectionAnchors();
|
|
396
405
|
}
|
|
397
406
|
#syncWorkspaceSources() {
|
|
398
407
|
const next = new Map();
|
|
@@ -496,6 +505,7 @@ export class KLineChartsSceneAdapter {
|
|
|
496
505
|
}
|
|
497
506
|
}
|
|
498
507
|
#restoreWorkspaceDrawings(drawings) {
|
|
508
|
+
const selectionBefore = this.#selectedOverlayId;
|
|
499
509
|
for (const overlay of this.#workspaceOverlays) {
|
|
500
510
|
this.#chart.removeOverlay({ id: overlay.id });
|
|
501
511
|
}
|
|
@@ -511,6 +521,13 @@ export class KLineChartsSceneAdapter {
|
|
|
511
521
|
}
|
|
512
522
|
this.#workspaceOverlays.push(structuredClone(overlay));
|
|
513
523
|
}
|
|
524
|
+
if (selectionBefore !== null &&
|
|
525
|
+
this.#workspaceOverlays.some((overlay) => overlay.id === selectionBefore)) {
|
|
526
|
+
this.#selectOverlay(selectionBefore);
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
this.#renderSelectionAnchors();
|
|
530
|
+
}
|
|
514
531
|
}
|
|
515
532
|
#fromPixelToData(point, paneId) {
|
|
516
533
|
const filter = this.#primaryAxisFilter(paneId);
|
|
@@ -532,6 +549,7 @@ export class KLineChartsSceneAdapter {
|
|
|
532
549
|
#selectOverlay(id) {
|
|
533
550
|
const previousId = this.#selectedOverlayId;
|
|
534
551
|
if (previousId === id) {
|
|
552
|
+
this.#renderSelectionAnchors();
|
|
535
553
|
return;
|
|
536
554
|
}
|
|
537
555
|
if (previousId === null && id !== null) {
|
|
@@ -541,6 +559,7 @@ export class KLineChartsSceneAdapter {
|
|
|
541
559
|
this.#leaveExclusiveSelection();
|
|
542
560
|
}
|
|
543
561
|
this.#selectedOverlayId = id;
|
|
562
|
+
this.#renderSelectionAnchors();
|
|
544
563
|
if (this.#workspaceMode) {
|
|
545
564
|
this.#emitPort({
|
|
546
565
|
type: id === null ? 'deselected' : 'selected',
|
|
@@ -953,7 +972,11 @@ export class KLineChartsSceneAdapter {
|
|
|
953
972
|
if (!Number.isFinite(value?.dataIndex) || !Number.isFinite(value?.value)) {
|
|
954
973
|
throw new SceneError('INVALID_REFERENCE', '/overlays', 'Pointer does not map to finite chart data.');
|
|
955
974
|
}
|
|
956
|
-
return {
|
|
975
|
+
return {
|
|
976
|
+
dataIndex: value.dataIndex,
|
|
977
|
+
...(Number.isSafeInteger(value?.timestamp) ? { timestamp: value.timestamp } : {}),
|
|
978
|
+
value: value.value,
|
|
979
|
+
};
|
|
957
980
|
}
|
|
958
981
|
#measurementAnchor(point, paneId, path) {
|
|
959
982
|
const converted = this.#chart.convertFromPixel([point], this.#primaryAxisFilter(paneId));
|
|
@@ -1036,6 +1059,19 @@ export class KLineChartsSceneAdapter {
|
|
|
1036
1059
|
}
|
|
1037
1060
|
return geometries;
|
|
1038
1061
|
}
|
|
1062
|
+
#renderSelectionAnchors() {
|
|
1063
|
+
if (this.#selectionAnchors === undefined || this.#selectedOverlayId === null) {
|
|
1064
|
+
this.#selectionAnchors?.render(null, [], 'rgba(41, 98, 255, 1)', false);
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
const selected = this.#activeOverlays().find((overlay) => overlay.id === this.#selectedOverlayId);
|
|
1068
|
+
const geometry = this.#overlayGeometries().find((candidate) => candidate.overlayId === this.#selectedOverlayId);
|
|
1069
|
+
if (selected === undefined || geometry === undefined) {
|
|
1070
|
+
this.#selectionAnchors.render(null, [], 'rgba(41, 98, 255, 1)', false);
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
this.#selectionAnchors.render(selected.id, geometry.anchors, selected.styles.line.color, selected.locked);
|
|
1074
|
+
}
|
|
1039
1075
|
#interactionIdentity(interaction) {
|
|
1040
1076
|
return {
|
|
1041
1077
|
interactionId: interaction.interactionId,
|
|
@@ -1074,6 +1110,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1074
1110
|
if (reason === 'validation-error' && error !== undefined) {
|
|
1075
1111
|
this.#emit({ type: 'scene-error', issues: structuredClone(error.issues) });
|
|
1076
1112
|
}
|
|
1113
|
+
this.#renderSelectionAnchors();
|
|
1077
1114
|
}
|
|
1078
1115
|
#routeTouchPrecisionPointerDown(event) {
|
|
1079
1116
|
const drawing = this.#touchPrecisionDrawing;
|
|
@@ -1281,7 +1318,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1281
1318
|
});
|
|
1282
1319
|
}
|
|
1283
1320
|
try {
|
|
1284
|
-
const candidate = createDragCandidate(interaction.before, interaction.hit, interaction.originData, this.#fromPixel(coordinate, interaction.before.paneId), this.#scene.data.map((bar) => bar.timestamp), this.#scene.symbol.pricePrecision);
|
|
1321
|
+
const candidate = createDragCandidate(interaction.before, interaction.hit, interaction.originData, this.#fromPixel(coordinate, interaction.before.paneId), this.#scene.data.map((bar) => bar.timestamp), this.#scene.symbol.pricePrecision, this.#scene.period);
|
|
1285
1322
|
const active = this.#activeOverlays();
|
|
1286
1323
|
const index = active.findIndex((overlay) => overlay.id === candidate.id);
|
|
1287
1324
|
const overlays = structuredClone(active);
|
|
@@ -1489,6 +1526,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1489
1526
|
}
|
|
1490
1527
|
this.#displayTimezone = timezone;
|
|
1491
1528
|
this.#applyDatePresentation(this.#scene.chart);
|
|
1529
|
+
this.#renderSelectionAnchors();
|
|
1492
1530
|
}
|
|
1493
1531
|
/** 同结构 Scene 替换时同步主图指标;副图结构仍由更高层单独管理。 */
|
|
1494
1532
|
#replaceMainPaneIndicators(previous, candidate) {
|
|
@@ -1573,6 +1611,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1573
1611
|
this.#scene = candidate;
|
|
1574
1612
|
this.#container.style.backgroundColor =
|
|
1575
1613
|
candidate.chart.layout.backgroundColor;
|
|
1614
|
+
this.#renderSelectionAnchors();
|
|
1576
1615
|
return structuredClone(candidate);
|
|
1577
1616
|
}
|
|
1578
1617
|
catch (error) {
|
|
@@ -1750,6 +1789,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1750
1789
|
this.#workspaceOverlays = this.#workspaceOverlays.map((candidate) => candidate.id === id
|
|
1751
1790
|
? drawingToSceneOverlay(updated, candidate.paneId)
|
|
1752
1791
|
: candidate);
|
|
1792
|
+
this.#renderSelectionAnchors();
|
|
1753
1793
|
this.#emitPort({
|
|
1754
1794
|
type: 'updated',
|
|
1755
1795
|
id,
|
|
@@ -1774,6 +1814,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1774
1814
|
this.#workspaceOverlays = this.#workspaceOverlays.map((candidate) => candidate.id === id
|
|
1775
1815
|
? drawingToSceneOverlay(updated, candidate.paneId)
|
|
1776
1816
|
: candidate);
|
|
1817
|
+
this.#renderSelectionAnchors();
|
|
1777
1818
|
this.#emitPort({
|
|
1778
1819
|
type: 'updated',
|
|
1779
1820
|
id,
|
|
@@ -1800,6 +1841,7 @@ export class KLineChartsSceneAdapter {
|
|
|
1800
1841
|
this.#workspaceOverlays = this.#workspaceOverlays.map((candidate) => candidate.id === id
|
|
1801
1842
|
? drawingToSceneOverlay(updated, candidate.paneId)
|
|
1802
1843
|
: candidate);
|
|
1844
|
+
this.#renderSelectionAnchors();
|
|
1803
1845
|
const snapshot = snapshotOfDrawing(updated);
|
|
1804
1846
|
this.#emitPort({
|
|
1805
1847
|
type: 'updated',
|
|
@@ -2191,6 +2233,8 @@ export class KLineChartsSceneAdapter {
|
|
|
2191
2233
|
this.#cancelTouchPrecisionDrawing(false);
|
|
2192
2234
|
this.#touchPrecisionGuide?.destroy();
|
|
2193
2235
|
this.#touchPrecisionGuide = undefined;
|
|
2236
|
+
this.#selectionAnchors?.destroy();
|
|
2237
|
+
this.#selectionAnchors = undefined;
|
|
2194
2238
|
this.#interactivePriceMeasurement = undefined;
|
|
2195
2239
|
this.#drawingInProgressId = null;
|
|
2196
2240
|
this.#disposed = true;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { SceneIndicator, ScenePane } from '@baron1996/kline-scene-schema';
|
|
2
2
|
import type { Chart, DeepPartial, IndicatorCreate, IndicatorStyle } from 'klinecharts';
|
|
3
3
|
import type { EngineIdMap } from './id-map.js';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* 将协议内指标样式映射为 KLineCharts 的受控样式子集。
|
|
6
|
+
* 空样式通道必须省略,让引擎保留可用的默认项,避免圆点等图形按空数组取样。
|
|
7
|
+
*/
|
|
5
8
|
export declare function toKLineChartsIndicatorStyles(styles: SceneIndicator['styles']): DeepPartial<IndicatorStyle>;
|
|
6
9
|
export declare function toIndicatorCreate(indicator: SceneIndicator, idMap: EngineIdMap, path: string): IndicatorCreate;
|
|
7
10
|
export declare function createPaneIndicators(chart: Chart, pane: ScenePane, paneIndex: number, idMap: EngineIdMap): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indicators.d.ts","sourceRoot":"","sources":["../../src/conversion/indicators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,cAAc,EACd,SAAS,EACT,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EACX,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAc/C
|
|
1
|
+
{"version":3,"file":"indicators.d.ts","sourceRoot":"","sources":["../../src/conversion/indicators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,cAAc,EACd,SAAS,EACT,MAAM,+BAA+B,CAAC;AAEvC,OAAO,KAAK,EACX,KAAK,EACL,WAAW,EACX,eAAe,EACf,cAAc,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAc/C;;;GAGG;AACH,wBAAgB,4BAA4B,CAC3C,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAC9B,WAAW,CAAC,cAAc,CAAC,CAuB7B;AAED,wBAAgB,iBAAiB,CAChC,SAAS,EAAE,cAAc,EACzB,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GACV,eAAe,CAejB;AAED,wBAAgB,oBAAoB,CACnC,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,SAAS,EACf,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,WAAW,GAChB,IAAI,CAqBN"}
|
|
@@ -10,24 +10,33 @@ function lineStyle(style) {
|
|
|
10
10
|
smooth: false,
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* 将协议内指标样式映射为 KLineCharts 的受控样式子集。
|
|
15
|
+
* 空样式通道必须省略,让引擎保留可用的默认项,避免圆点等图形按空数组取样。
|
|
16
|
+
*/
|
|
14
17
|
export function toKLineChartsIndicatorStyles(styles) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const converted = {};
|
|
19
|
+
if (styles.lines.length > 0) {
|
|
20
|
+
converted.lines = styles.lines.map(lineStyle);
|
|
21
|
+
}
|
|
22
|
+
if (styles.bars.length > 0) {
|
|
23
|
+
converted.bars = styles.bars.map((style) => ({
|
|
18
24
|
style: 'fill',
|
|
19
25
|
upColor: style.upColor,
|
|
20
26
|
downColor: style.downColor,
|
|
21
27
|
noChangeColor: style.noChangeColor,
|
|
22
|
-
}))
|
|
23
|
-
|
|
28
|
+
}));
|
|
29
|
+
}
|
|
30
|
+
if (styles.circles.length > 0) {
|
|
31
|
+
converted.circles = styles.circles.map((style) => ({
|
|
24
32
|
style: 'fill',
|
|
25
33
|
upColor: style.color,
|
|
26
34
|
downColor: style.color,
|
|
27
35
|
noChangeColor: style.color,
|
|
28
36
|
borderRadius: style.radius,
|
|
29
|
-
}))
|
|
30
|
-
}
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
return converted;
|
|
31
40
|
}
|
|
32
41
|
export function toIndicatorCreate(indicator, idMap, path) {
|
|
33
42
|
if (!isSupportedIndicator(indicator.name)) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { SceneOverlay } from '@baron1996/kline-scene-schema';
|
|
1
|
+
import type { Period, SceneOverlay } from '@baron1996/kline-scene-schema';
|
|
2
2
|
export interface DragDataPoint {
|
|
3
3
|
readonly dataIndex: number;
|
|
4
|
+
readonly timestamp?: number;
|
|
4
5
|
readonly value: number;
|
|
5
6
|
}
|
|
6
7
|
export interface DragTarget {
|
|
@@ -8,5 +9,5 @@ export interface DragTarget {
|
|
|
8
9
|
readonly anchorIndex: number | null;
|
|
9
10
|
}
|
|
10
11
|
/** 根据冻结的绝对平移语义构造未提交候选,不修改输入 Overlay。 */
|
|
11
|
-
export declare function createDragCandidate(before: SceneOverlay, dragTarget: DragTarget, origin: DragDataPoint, current: DragDataPoint, timestamps: readonly number[], pricePrecision: number): SceneOverlay;
|
|
12
|
+
export declare function createDragCandidate(before: SceneOverlay, dragTarget: DragTarget, origin: DragDataPoint, current: DragDataPoint, timestamps: readonly number[], pricePrecision: number, period?: Period): SceneOverlay;
|
|
12
13
|
//# sourceMappingURL=dragging.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dragging.d.ts","sourceRoot":"","sources":["../../src/interaction/dragging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"dragging.d.ts","sourceRoot":"","sources":["../../src/interaction/dragging.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAK1E,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAgLD,wCAAwC;AACxC,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,cAAc,EAAE,MAAM,EACtB,MAAM,CAAC,EAAE,MAAM,GACb,YAAY,CAiKd"}
|
|
@@ -6,40 +6,123 @@ function requireDataIndex(value, path) {
|
|
|
6
6
|
}
|
|
7
7
|
return Math.round(value);
|
|
8
8
|
}
|
|
9
|
-
function requireTimestamp(timestamps, index, path) {
|
|
9
|
+
function requireTimestamp(timestamps, index, path, period) {
|
|
10
10
|
const timestamp = timestamps[index];
|
|
11
|
-
if (timestamp
|
|
12
|
-
|
|
11
|
+
if (timestamp !== undefined) {
|
|
12
|
+
return timestamp;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
const first = timestamps[0];
|
|
15
|
+
const last = timestamps[timestamps.length - 1];
|
|
16
|
+
if (period !== undefined && first !== undefined && last !== undefined) {
|
|
17
|
+
if (index < 0) {
|
|
18
|
+
return extrapolateTimestamp(first, index, period);
|
|
19
|
+
}
|
|
20
|
+
if (index >= timestamps.length) {
|
|
21
|
+
return extrapolateTimestamp(last, index - (timestamps.length - 1), period);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
throw new SceneError('INVALID_REFERENCE', path, 'Drag candidate must remain on the chart timeline.');
|
|
15
25
|
}
|
|
16
|
-
function
|
|
17
|
-
|
|
26
|
+
function extrapolateTimestamp(reference, diff, period) {
|
|
27
|
+
const { type, span } = period;
|
|
28
|
+
const multiplier = type === 'second'
|
|
29
|
+
? 1000
|
|
30
|
+
: type === 'minute'
|
|
31
|
+
? 60 * 1000
|
|
32
|
+
: type === 'hour'
|
|
33
|
+
? 60 * 60 * 1000
|
|
34
|
+
: type === 'day'
|
|
35
|
+
? 24 * 60 * 60 * 1000
|
|
36
|
+
: type === 'week'
|
|
37
|
+
? 7 * 24 * 60 * 60 * 1000
|
|
38
|
+
: null;
|
|
39
|
+
if (multiplier !== null) {
|
|
40
|
+
return reference + span * multiplier * diff;
|
|
41
|
+
}
|
|
42
|
+
const date = new Date(reference);
|
|
43
|
+
if (type === 'month') {
|
|
44
|
+
const referenceDay = date.getDate();
|
|
45
|
+
date.setDate(1);
|
|
46
|
+
date.setMonth(date.getMonth() + span * diff);
|
|
47
|
+
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
48
|
+
date.setDate(Math.min(referenceDay, lastDay));
|
|
49
|
+
return date.getTime();
|
|
50
|
+
}
|
|
51
|
+
date.setFullYear(date.getFullYear() + span * diff);
|
|
52
|
+
return date.getTime();
|
|
53
|
+
}
|
|
54
|
+
function outsideDataIndex(timestamp, timestamps, period) {
|
|
55
|
+
const first = timestamps[0];
|
|
56
|
+
const last = timestamps[timestamps.length - 1];
|
|
57
|
+
if (first === undefined || last === undefined) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const reference = timestamp > last
|
|
61
|
+
? { timestamp: last, index: timestamps.length - 1 }
|
|
62
|
+
: timestamp < first
|
|
63
|
+
? { timestamp: first, index: 0 }
|
|
64
|
+
: null;
|
|
65
|
+
if (reference === null) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const { type, span } = period;
|
|
69
|
+
const divisor = type === 'second'
|
|
70
|
+
? span * 1000
|
|
71
|
+
: type === 'minute'
|
|
72
|
+
? span * 60 * 1000
|
|
73
|
+
: type === 'hour'
|
|
74
|
+
? span * 60 * 60 * 1000
|
|
75
|
+
: type === 'day'
|
|
76
|
+
? span * 24 * 60 * 60 * 1000
|
|
77
|
+
: type === 'week'
|
|
78
|
+
? span * 7 * 24 * 60 * 60 * 1000
|
|
79
|
+
: null;
|
|
80
|
+
if (divisor !== null) {
|
|
81
|
+
return reference.index + Math.floor((timestamp - reference.timestamp) / divisor);
|
|
82
|
+
}
|
|
83
|
+
const referenceDate = new Date(reference.timestamp);
|
|
84
|
+
const currentDate = new Date(timestamp);
|
|
85
|
+
const units = type === 'month'
|
|
86
|
+
? (currentDate.getFullYear() - referenceDate.getFullYear()) * 12 +
|
|
87
|
+
(currentDate.getMonth() - referenceDate.getMonth())
|
|
88
|
+
: currentDate.getFullYear() - referenceDate.getFullYear();
|
|
89
|
+
return reference.index + Math.floor(units / span);
|
|
18
90
|
}
|
|
19
|
-
function timestampAtCurrentPoint(current, timestamps, path) {
|
|
20
|
-
|
|
91
|
+
function timestampAtCurrentPoint(current, timestamps, path, period) {
|
|
92
|
+
const index = requireDataIndex(current.dataIndex, `${path}/dataIndex`);
|
|
93
|
+
if ((index < 0 || index >= timestamps.length) &&
|
|
94
|
+
Number.isSafeInteger(current.timestamp)) {
|
|
95
|
+
return current.timestamp;
|
|
96
|
+
}
|
|
97
|
+
return requireTimestamp(timestamps, index, path, period);
|
|
21
98
|
}
|
|
22
|
-
function translatedTimestamp(timestamp, deltaIndex, timestamps, path) {
|
|
23
|
-
|
|
99
|
+
function translatedTimestamp(timestamp, deltaIndex, timestamps, path, period) {
|
|
100
|
+
let sourceIndex = timestamps.indexOf(timestamp);
|
|
101
|
+
if (sourceIndex < 0 && period !== undefined) {
|
|
102
|
+
sourceIndex = outsideDataIndex(timestamp, timestamps, period) ?? -1;
|
|
103
|
+
}
|
|
24
104
|
if (sourceIndex < 0) {
|
|
25
|
-
throw new SceneError('INVALID_REFERENCE', path, 'Overlay point must reference
|
|
105
|
+
throw new SceneError('INVALID_REFERENCE', path, 'Overlay point must reference the chart timeline before dragging.');
|
|
26
106
|
}
|
|
27
|
-
return requireTimestamp(timestamps, sourceIndex + deltaIndex, path);
|
|
107
|
+
return requireTimestamp(timestamps, sourceIndex + deltaIndex, path, period);
|
|
108
|
+
}
|
|
109
|
+
function normalizedValue(value, pricePrecision, path) {
|
|
110
|
+
return normalizePriceValue(value, pricePrecision, path);
|
|
28
111
|
}
|
|
29
|
-
function translatedPoint(point, deltaIndex, deltaValue, timestamps, pricePrecision, path) {
|
|
112
|
+
function translatedPoint(point, deltaIndex, deltaValue, timestamps, pricePrecision, path, period) {
|
|
30
113
|
return {
|
|
31
|
-
timestamp: translatedTimestamp(point.timestamp, deltaIndex, timestamps, `${path}/timestamp
|
|
114
|
+
timestamp: translatedTimestamp(point.timestamp, deltaIndex, timestamps, `${path}/timestamp`, period),
|
|
32
115
|
value: normalizedValue(point.value + deltaValue, pricePrecision, `${path}/value`),
|
|
33
116
|
};
|
|
34
117
|
}
|
|
35
|
-
function currentPoint(current, timestamps, pricePrecision, path) {
|
|
118
|
+
function currentPoint(current, timestamps, pricePrecision, path, period) {
|
|
36
119
|
return {
|
|
37
|
-
timestamp: timestampAtCurrentPoint(current, timestamps, `${path}/timestamp
|
|
120
|
+
timestamp: timestampAtCurrentPoint(current, timestamps, `${path}/timestamp`, period),
|
|
38
121
|
value: normalizedValue(current.value, pricePrecision, `${path}/value`),
|
|
39
122
|
};
|
|
40
123
|
}
|
|
41
124
|
/** 根据冻结的绝对平移语义构造未提交候选,不修改输入 Overlay。 */
|
|
42
|
-
export function createDragCandidate(before, dragTarget, origin, current, timestamps, pricePrecision) {
|
|
125
|
+
export function createDragCandidate(before, dragTarget, origin, current, timestamps, pricePrecision, period) {
|
|
43
126
|
const deltaValue = current.value - origin.value;
|
|
44
127
|
if (!Number.isFinite(deltaValue)) {
|
|
45
128
|
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays', 'Drag price delta must be finite.');
|
|
@@ -67,8 +150,8 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
67
150
|
}
|
|
68
151
|
candidate.anchor = {
|
|
69
152
|
timestamp: dragTarget.target === 'anchor'
|
|
70
|
-
? timestampAtCurrentPoint(current, timestamps, '/overlays/anchor')
|
|
71
|
-
: translatedTimestamp(anchor.timestamp, deltaIndex, timestamps, '/overlays/anchor/timestamp'),
|
|
153
|
+
? timestampAtCurrentPoint(current, timestamps, '/overlays/anchor', period)
|
|
154
|
+
: translatedTimestamp(anchor.timestamp, deltaIndex, timestamps, '/overlays/anchor/timestamp', period),
|
|
72
155
|
};
|
|
73
156
|
return candidate;
|
|
74
157
|
}
|
|
@@ -80,7 +163,7 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
80
163
|
}
|
|
81
164
|
candidate.value = normalizedValue(dragTarget.target === 'anchor' ? current.value : before.value + deltaValue, pricePrecision, '/overlays/value');
|
|
82
165
|
if (dragTarget.target === 'anchor') {
|
|
83
|
-
const timestamp = timestampAtCurrentPoint(current, timestamps, '/overlays/anchor');
|
|
166
|
+
const timestamp = timestampAtCurrentPoint(current, timestamps, '/overlays/anchor', period);
|
|
84
167
|
if (dragTarget.anchorIndex === 0)
|
|
85
168
|
candidate.startTimestamp = timestamp;
|
|
86
169
|
else if (dragTarget.anchorIndex === 1)
|
|
@@ -89,8 +172,8 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
89
172
|
throw new SceneError('INVALID_REFERENCE', '/overlays/anchorIndex', 'Invalid anchor index.');
|
|
90
173
|
}
|
|
91
174
|
else {
|
|
92
|
-
candidate.startTimestamp = translatedTimestamp(before.startTimestamp, deltaIndex, timestamps, '/overlays/startTimestamp');
|
|
93
|
-
candidate.endTimestamp = translatedTimestamp(before.endTimestamp, deltaIndex, timestamps, '/overlays/endTimestamp');
|
|
175
|
+
candidate.startTimestamp = translatedTimestamp(before.startTimestamp, deltaIndex, timestamps, '/overlays/startTimestamp', period);
|
|
176
|
+
candidate.endTimestamp = translatedTimestamp(before.endTimestamp, deltaIndex, timestamps, '/overlays/endTimestamp', period);
|
|
94
177
|
}
|
|
95
178
|
return candidate;
|
|
96
179
|
}
|
|
@@ -101,8 +184,8 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
101
184
|
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays', 'Missing vertical line geometry.');
|
|
102
185
|
}
|
|
103
186
|
candidate.timestamp = dragTarget.target === 'anchor'
|
|
104
|
-
? timestampAtCurrentPoint(current, timestamps, '/overlays/anchor')
|
|
105
|
-
: translatedTimestamp(before.timestamp, deltaIndex, timestamps, '/overlays/timestamp');
|
|
187
|
+
? timestampAtCurrentPoint(current, timestamps, '/overlays/anchor', period)
|
|
188
|
+
: translatedTimestamp(before.timestamp, deltaIndex, timestamps, '/overlays/timestamp', period);
|
|
106
189
|
if (dragTarget.target === 'anchor') {
|
|
107
190
|
const value = normalizedValue(current.value, pricePrecision, '/overlays/anchor/value');
|
|
108
191
|
if (dragTarget.anchorIndex === 0)
|
|
@@ -132,10 +215,10 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
132
215
|
if (dragTarget.anchorIndex === null || before.points[dragTarget.anchorIndex] === undefined) {
|
|
133
216
|
throw new SceneError('INVALID_REFERENCE', '/overlays/anchorIndex', 'Invalid anchor index.');
|
|
134
217
|
}
|
|
135
|
-
candidate.points[dragTarget.anchorIndex] = currentPoint(current, timestamps, pricePrecision, `/overlays/points/${dragTarget.anchorIndex}
|
|
218
|
+
candidate.points[dragTarget.anchorIndex] = currentPoint(current, timestamps, pricePrecision, `/overlays/points/${dragTarget.anchorIndex}`, period);
|
|
136
219
|
}
|
|
137
220
|
else {
|
|
138
|
-
candidate.points = before.points.map((point, index) => translatedPoint(point, deltaIndex, deltaValue, timestamps, pricePrecision, `/overlays/points/${index}
|
|
221
|
+
candidate.points = before.points.map((point, index) => translatedPoint(point, deltaIndex, deltaValue, timestamps, pricePrecision, `/overlays/points/${index}`, period));
|
|
139
222
|
}
|
|
140
223
|
return candidate;
|
|
141
224
|
}
|
|
@@ -147,8 +230,8 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
147
230
|
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays/point', 'Missing point geometry.');
|
|
148
231
|
}
|
|
149
232
|
candidate.point = dragTarget.target === 'anchor'
|
|
150
|
-
? currentPoint(current, timestamps, pricePrecision, '/overlays/point')
|
|
151
|
-
: translatedPoint(before.point, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/point');
|
|
233
|
+
? currentPoint(current, timestamps, pricePrecision, '/overlays/point', period)
|
|
234
|
+
: translatedPoint(before.point, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/point', period);
|
|
152
235
|
return candidate;
|
|
153
236
|
}
|
|
154
237
|
case 'rectangle':
|
|
@@ -158,7 +241,7 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
158
241
|
throw new SceneError('SCENE_SCHEMA_INVALID', '/overlays', 'Missing two-point geometry.');
|
|
159
242
|
}
|
|
160
243
|
if (dragTarget.target === 'anchor') {
|
|
161
|
-
const point = currentPoint(current, timestamps, pricePrecision, '/overlays/anchor');
|
|
244
|
+
const point = currentPoint(current, timestamps, pricePrecision, '/overlays/anchor', period);
|
|
162
245
|
if (dragTarget.anchorIndex === 0)
|
|
163
246
|
candidate.start = point;
|
|
164
247
|
else if (dragTarget.anchorIndex === 1)
|
|
@@ -167,8 +250,8 @@ export function createDragCandidate(before, dragTarget, origin, current, timesta
|
|
|
167
250
|
throw new SceneError('INVALID_REFERENCE', '/overlays/anchorIndex', 'Invalid anchor index.');
|
|
168
251
|
}
|
|
169
252
|
else {
|
|
170
|
-
candidate.start = translatedPoint(before.start, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/start');
|
|
171
|
-
candidate.end = translatedPoint(before.end, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/end');
|
|
253
|
+
candidate.start = translatedPoint(before.start, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/start', period);
|
|
254
|
+
candidate.end = translatedPoint(before.end, deltaIndex, deltaValue, timestamps, pricePrecision, '/overlays/end', period);
|
|
172
255
|
}
|
|
173
256
|
return candidate;
|
|
174
257
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PixelCoordinate } from './hit-testing.js';
|
|
2
|
+
/**
|
|
3
|
+
* 独占 Drawing 交互会消费原生点击事件,因此不能依赖 KLineCharts 的临时选中圆点。
|
|
4
|
+
* 该只读覆盖层使用 Baron 权威命中几何持续绘制当前 Drawing 的操作锚点。
|
|
5
|
+
*/
|
|
6
|
+
export declare class SelectionAnchorLayer {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(container: HTMLElement, onResize: () => void);
|
|
9
|
+
render(drawingId: string | null, anchors: readonly PixelCoordinate[], color: string, locked: boolean): void;
|
|
10
|
+
destroy(): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=selection-anchors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection-anchors.d.ts","sourceRoot":"","sources":["../../src/interaction/selection-anchors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAMxD;;;GAGG;AACH,qBAAa,oBAAoB;;gBAOb,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI;IAgCxD,MAAM,CACZ,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,SAAS,eAAe,EAAE,EACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,OAAO,GACb,IAAI;IA0BA,OAAO,IAAI,IAAI;CAOtB"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
|
|
2
|
+
const ANCHOR_RADIUS = 5;
|
|
3
|
+
const ANCHOR_BORDER_SIZE = 2;
|
|
4
|
+
/**
|
|
5
|
+
* 独占 Drawing 交互会消费原生点击事件,因此不能依赖 KLineCharts 的临时选中圆点。
|
|
6
|
+
* 该只读覆盖层使用 Baron 权威命中几何持续绘制当前 Drawing 的操作锚点。
|
|
7
|
+
*/
|
|
8
|
+
export class SelectionAnchorLayer {
|
|
9
|
+
#container;
|
|
10
|
+
#root;
|
|
11
|
+
#originalInlinePosition;
|
|
12
|
+
#changedContainerPosition;
|
|
13
|
+
#resizeObserver;
|
|
14
|
+
constructor(container, onResize) {
|
|
15
|
+
this.#container = container;
|
|
16
|
+
this.#originalInlinePosition = container.style.position;
|
|
17
|
+
this.#changedContainerPosition = (container.ownerDocument.defaultView?.getComputedStyle(container).position ??
|
|
18
|
+
container.style.position) === 'static';
|
|
19
|
+
if (this.#changedContainerPosition) {
|
|
20
|
+
container.style.position = 'relative';
|
|
21
|
+
}
|
|
22
|
+
const root = container.ownerDocument.createElementNS(SVG_NAMESPACE, 'svg');
|
|
23
|
+
root.dataset.drawingSelectionAnchors = '';
|
|
24
|
+
root.setAttribute('aria-hidden', 'true');
|
|
25
|
+
root.style.position = 'absolute';
|
|
26
|
+
root.style.inset = '0';
|
|
27
|
+
root.style.zIndex = '3';
|
|
28
|
+
root.style.width = '100%';
|
|
29
|
+
root.style.height = '100%';
|
|
30
|
+
root.style.overflow = 'hidden';
|
|
31
|
+
root.style.pointerEvents = 'none';
|
|
32
|
+
root.style.display = 'none';
|
|
33
|
+
container.append(root);
|
|
34
|
+
this.#root = root;
|
|
35
|
+
const view = container.ownerDocument.defaultView;
|
|
36
|
+
this.#resizeObserver = view !== null && typeof view.ResizeObserver !== 'undefined'
|
|
37
|
+
? new view.ResizeObserver(() => onResize())
|
|
38
|
+
: null;
|
|
39
|
+
this.#resizeObserver?.observe(container);
|
|
40
|
+
}
|
|
41
|
+
render(drawingId, anchors, color, locked) {
|
|
42
|
+
this.#root.replaceChildren();
|
|
43
|
+
if (drawingId === null || anchors.length === 0) {
|
|
44
|
+
this.#root.style.display = 'none';
|
|
45
|
+
delete this.#root.dataset.drawingId;
|
|
46
|
+
delete this.#root.dataset.locked;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
this.#root.style.display = 'block';
|
|
50
|
+
this.#root.dataset.drawingId = drawingId;
|
|
51
|
+
this.#root.dataset.locked = String(locked);
|
|
52
|
+
for (let index = 0; index < anchors.length; index++) {
|
|
53
|
+
const anchor = anchors[index];
|
|
54
|
+
const circle = this.#container.ownerDocument.createElementNS(SVG_NAMESPACE, 'circle');
|
|
55
|
+
circle.dataset.anchorIndex = String(index);
|
|
56
|
+
circle.setAttribute('cx', String(anchor.x));
|
|
57
|
+
circle.setAttribute('cy', String(anchor.y));
|
|
58
|
+
circle.setAttribute('r', String(ANCHOR_RADIUS));
|
|
59
|
+
circle.setAttribute('fill', 'rgba(255, 255, 255, 0.98)');
|
|
60
|
+
circle.setAttribute('stroke', color);
|
|
61
|
+
circle.setAttribute('stroke-width', String(ANCHOR_BORDER_SIZE));
|
|
62
|
+
circle.setAttribute('vector-effect', 'non-scaling-stroke');
|
|
63
|
+
this.#root.append(circle);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
destroy() {
|
|
67
|
+
this.#resizeObserver?.disconnect();
|
|
68
|
+
this.#root.remove();
|
|
69
|
+
if (this.#changedContainerPosition) {
|
|
70
|
+
this.#container.style.position = this.#originalInlinePosition;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Adapter 包版本。 */
|
|
2
|
-
export declare const ADAPTER_PACKAGE_VERSION: "0.9.
|
|
2
|
+
export declare const ADAPTER_PACKAGE_VERSION: "0.9.20";
|
|
3
3
|
/** 唯一允许加载的 KLineCharts 引擎版本。 */
|
|
4
4
|
export declare const KLINECHARTS_ENGINE_VERSION: "10.0.0";
|
|
5
5
|
/** 与 ChartScene 绑定的 Runtime 协议版本。 */
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baron1996/klinecharts-adapter",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.20",
|
|
4
4
|
"description": "Controlled ChartScene adapter for KLineCharts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@baron1996/kline-scene-schema": "0.9.
|
|
41
|
+
"@baron1996/kline-scene-schema": "0.9.20",
|
|
42
42
|
"klinecharts": "10.0.0"
|
|
43
43
|
}
|
|
44
44
|
}
|