@baron1996/klinecharts-adapter 0.9.4 → 0.9.7
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 +4 -1
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +488 -67
- package/dist/conversion/id-map.d.ts.map +1 -1
- package/dist/conversion/id-map.js +6 -1
- package/dist/drawing/engine-port.d.ts +15 -0
- package/dist/drawing/engine-port.d.ts.map +1 -1
- package/dist/engine.d.ts +10 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +26 -1
- package/dist/gap-aware-series.d.ts +44 -0
- package/dist/gap-aware-series.d.ts.map +1 -0
- package/dist/gap-aware-series.js +221 -0
- package/dist/interaction/dragging.d.ts.map +1 -1
- package/dist/interaction/dragging.js +149 -44
- package/dist/interaction/hit-testing.d.ts +16 -1
- package/dist/interaction/hit-testing.d.ts.map +1 -1
- package/dist/interaction/hit-testing.js +25 -4
- package/dist/interaction/overlay-geometry.d.ts +15 -0
- package/dist/interaction/overlay-geometry.d.ts.map +1 -0
- package/dist/interaction/overlay-geometry.js +228 -0
- package/dist/interaction/touch-precision-drawing.d.ts +29 -0
- package/dist/interaction/touch-precision-drawing.d.ts.map +1 -0
- package/dist/interaction/touch-precision-drawing.js +273 -0
- package/dist/static-data-loader.d.ts +2 -3
- package/dist/static-data-loader.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
export declare const OVERLAY_BODY_HIT_THRESHOLD_CSS_PX = 12;
|
|
2
2
|
export declare const OVERLAY_ANCHOR_HIT_THRESHOLD_CSS_PX = 14;
|
|
3
|
+
export declare const OVERLAY_TOUCH_BODY_HIT_THRESHOLD_CSS_PX = 22;
|
|
4
|
+
export declare const OVERLAY_TOUCH_ANCHOR_HIT_THRESHOLD_CSS_PX = 24;
|
|
5
|
+
export interface OverlayHitTolerance {
|
|
6
|
+
readonly body: number;
|
|
7
|
+
readonly anchor: number;
|
|
8
|
+
}
|
|
9
|
+
export declare const DEFAULT_OVERLAY_MOUSE_HIT_TOLERANCE: OverlayHitTolerance;
|
|
10
|
+
export declare const DEFAULT_OVERLAY_TOUCH_HIT_TOLERANCE: OverlayHitTolerance;
|
|
3
11
|
export interface PixelCoordinate {
|
|
4
12
|
readonly x: number;
|
|
5
13
|
readonly y: number;
|
|
6
14
|
}
|
|
15
|
+
export interface PixelRectangle {
|
|
16
|
+
readonly left: number;
|
|
17
|
+
readonly top: number;
|
|
18
|
+
readonly right: number;
|
|
19
|
+
readonly bottom: number;
|
|
20
|
+
}
|
|
7
21
|
export interface OverlayPixelGeometry {
|
|
8
22
|
readonly overlayId: string;
|
|
9
23
|
readonly sceneIndex: number;
|
|
@@ -11,6 +25,7 @@ export interface OverlayPixelGeometry {
|
|
|
11
25
|
readonly locked: boolean;
|
|
12
26
|
readonly anchors: readonly PixelCoordinate[];
|
|
13
27
|
readonly bodySegments: readonly (readonly [PixelCoordinate, PixelCoordinate])[];
|
|
28
|
+
readonly bodyRectangles?: readonly PixelRectangle[];
|
|
14
29
|
}
|
|
15
30
|
export interface OverlayHitResult {
|
|
16
31
|
readonly overlayId: string;
|
|
@@ -22,5 +37,5 @@ export interface OverlayHitResult {
|
|
|
22
37
|
* 按冻结契约在 CSS 像素坐标中执行命中测试。
|
|
23
38
|
* 锚点全局优先于主体;同类再按 zLevel、Scene 后序和锚点低索引排序。
|
|
24
39
|
*/
|
|
25
|
-
export declare function hitTestOverlayGeometries(point: PixelCoordinate, geometries: readonly OverlayPixelGeometry[]): OverlayHitResult | null;
|
|
40
|
+
export declare function hitTestOverlayGeometries(point: PixelCoordinate, geometries: readonly OverlayPixelGeometry[], tolerance?: OverlayHitTolerance): OverlayHitResult | null;
|
|
26
41
|
//# sourceMappingURL=hit-testing.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hit-testing.d.ts","sourceRoot":"","sources":["../../src/interaction/hit-testing.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iCAAiC,KAAK,CAAC;AACpD,eAAO,MAAM,mCAAmC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"hit-testing.d.ts","sourceRoot":"","sources":["../../src/interaction/hit-testing.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iCAAiC,KAAK,CAAC;AACpD,eAAO,MAAM,mCAAmC,KAAK,CAAC;AACtD,eAAO,MAAM,uCAAuC,KAAK,CAAC;AAC1D,eAAO,MAAM,yCAAyC,KAAK,CAAC;AAE5D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,mCAAmC,EAAE,mBAGjD,CAAC;AAEF,eAAO,MAAM,mCAAmC,EAAE,mBAGjD,CAAC;AAEF,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,SAAS,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;IAChF,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,cAAc,EAAE,CAAC;CACpD;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;CACzB;AA4DD;;;GAGG;AACH,wBAAgB,wBAAwB,CACvC,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,SAAS,oBAAoB,EAAE,EAC3C,SAAS,GAAE,mBAAyD,GAClE,gBAAgB,GAAG,IAAI,CAmDzB"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
export const OVERLAY_BODY_HIT_THRESHOLD_CSS_PX = 12;
|
|
2
2
|
export const OVERLAY_ANCHOR_HIT_THRESHOLD_CSS_PX = 14;
|
|
3
|
+
export const OVERLAY_TOUCH_BODY_HIT_THRESHOLD_CSS_PX = 22;
|
|
4
|
+
export const OVERLAY_TOUCH_ANCHOR_HIT_THRESHOLD_CSS_PX = 24;
|
|
5
|
+
export const DEFAULT_OVERLAY_MOUSE_HIT_TOLERANCE = {
|
|
6
|
+
body: OVERLAY_BODY_HIT_THRESHOLD_CSS_PX,
|
|
7
|
+
anchor: OVERLAY_ANCHOR_HIT_THRESHOLD_CSS_PX,
|
|
8
|
+
};
|
|
9
|
+
export const DEFAULT_OVERLAY_TOUCH_HIT_TOLERANCE = {
|
|
10
|
+
body: OVERLAY_TOUCH_BODY_HIT_THRESHOLD_CSS_PX,
|
|
11
|
+
anchor: OVERLAY_TOUCH_ANCHOR_HIT_THRESHOLD_CSS_PX,
|
|
12
|
+
};
|
|
3
13
|
function coordinateDistance(left, right) {
|
|
4
14
|
return Math.hypot(left.x - right.x, left.y - right.y);
|
|
5
15
|
}
|
|
@@ -16,7 +26,15 @@ function segmentDistance(point, start, end) {
|
|
|
16
26
|
y: start.y + projection * dy,
|
|
17
27
|
});
|
|
18
28
|
}
|
|
29
|
+
function rectangleDistance(point, rectangle) {
|
|
30
|
+
const horizontal = Math.max(rectangle.left - point.x, 0, point.x - rectangle.right);
|
|
31
|
+
const vertical = Math.max(rectangle.top - point.y, 0, point.y - rectangle.bottom);
|
|
32
|
+
return Math.hypot(horizontal, vertical);
|
|
33
|
+
}
|
|
19
34
|
function compareHits(left, right) {
|
|
35
|
+
if (left.distance !== right.distance) {
|
|
36
|
+
return left.distance - right.distance;
|
|
37
|
+
}
|
|
20
38
|
if (left.zLevel !== right.zLevel) {
|
|
21
39
|
return right.zLevel - left.zLevel;
|
|
22
40
|
}
|
|
@@ -29,13 +47,13 @@ function compareHits(left, right) {
|
|
|
29
47
|
left.anchorIndex !== right.anchorIndex) {
|
|
30
48
|
return left.anchorIndex - right.anchorIndex;
|
|
31
49
|
}
|
|
32
|
-
return
|
|
50
|
+
return 0;
|
|
33
51
|
}
|
|
34
52
|
/**
|
|
35
53
|
* 按冻结契约在 CSS 像素坐标中执行命中测试。
|
|
36
54
|
* 锚点全局优先于主体;同类再按 zLevel、Scene 后序和锚点低索引排序。
|
|
37
55
|
*/
|
|
38
|
-
export function hitTestOverlayGeometries(point, geometries) {
|
|
56
|
+
export function hitTestOverlayGeometries(point, geometries, tolerance = DEFAULT_OVERLAY_MOUSE_HIT_TOLERANCE) {
|
|
39
57
|
const anchorHits = [];
|
|
40
58
|
const bodyHits = [];
|
|
41
59
|
for (const geometry of geometries) {
|
|
@@ -45,7 +63,7 @@ export function hitTestOverlayGeometries(point, geometries) {
|
|
|
45
63
|
continue;
|
|
46
64
|
}
|
|
47
65
|
const distance = coordinateDistance(point, anchor);
|
|
48
|
-
if (distance <=
|
|
66
|
+
if (distance <= tolerance.anchor) {
|
|
49
67
|
anchorHits.push({
|
|
50
68
|
overlayId: geometry.overlayId,
|
|
51
69
|
target: 'anchor',
|
|
@@ -61,7 +79,10 @@ export function hitTestOverlayGeometries(point, geometries) {
|
|
|
61
79
|
for (const [start, end] of geometry.bodySegments) {
|
|
62
80
|
distance = Math.min(distance, segmentDistance(point, start, end));
|
|
63
81
|
}
|
|
64
|
-
|
|
82
|
+
for (const rectangle of geometry.bodyRectangles ?? []) {
|
|
83
|
+
distance = Math.min(distance, rectangleDistance(point, rectangle));
|
|
84
|
+
}
|
|
85
|
+
if (distance <= tolerance.body) {
|
|
65
86
|
bodyHits.push({
|
|
66
87
|
overlayId: geometry.overlayId,
|
|
67
88
|
target: 'body',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SceneOverlay, TimeValueAnchor } from '@baron1996/kline-scene-schema';
|
|
2
|
+
import type { OverlayPixelGeometry, PixelCoordinate, PixelRectangle } from './hit-testing.js';
|
|
3
|
+
export interface OverlayGeometryProjectionContext {
|
|
4
|
+
readonly bounds: PixelRectangle;
|
|
5
|
+
readonly referenceTimestamp: number;
|
|
6
|
+
readonly referenceValue: number;
|
|
7
|
+
readonly project: (point: TimeValueAnchor) => PixelCoordinate;
|
|
8
|
+
readonly measureText: (text: string, overlay: SceneOverlay) => {
|
|
9
|
+
readonly width: number;
|
|
10
|
+
readonly height: number;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
/** 将 Drawing 业务几何投影成与画面一致的 CSS 像素命中几何。 */
|
|
14
|
+
export declare function projectOverlayGeometry(overlay: SceneOverlay, sceneIndex: number, context: OverlayGeometryProjectionContext): OverlayPixelGeometry | null;
|
|
15
|
+
//# sourceMappingURL=overlay-geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay-geometry.d.ts","sourceRoot":"","sources":["../../src/interaction/overlay-geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEnF,OAAO,KAAK,EACX,oBAAoB,EACpB,eAAe,EACf,cAAc,EACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,gCAAgC;IAChD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,eAAe,CAAC;IAC9D,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,KAAK;QAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;KACxB,CAAC;CACF;AAwJD,0CAA0C;AAC1C,wBAAgB,sBAAsB,CACrC,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gCAAgC,GACvC,oBAAoB,GAAG,IAAI,CA0I7B"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
function horizontal(bounds, y) {
|
|
2
|
+
return [{ x: bounds.left, y }, { x: bounds.right, y }];
|
|
3
|
+
}
|
|
4
|
+
function vertical(bounds, x) {
|
|
5
|
+
return [{ x, y: bounds.top }, { x, y: bounds.bottom }];
|
|
6
|
+
}
|
|
7
|
+
function clippedLine(origin, toward, bounds, minimum, maximum) {
|
|
8
|
+
const dx = toward.x - origin.x;
|
|
9
|
+
const dy = toward.y - origin.y;
|
|
10
|
+
if (dx === 0 && dy === 0) {
|
|
11
|
+
return [origin, toward];
|
|
12
|
+
}
|
|
13
|
+
let from = minimum;
|
|
14
|
+
let to = maximum;
|
|
15
|
+
const clipDimension = (coordinate, delta, lower, upper) => {
|
|
16
|
+
if (delta === 0) {
|
|
17
|
+
return coordinate >= lower && coordinate <= upper;
|
|
18
|
+
}
|
|
19
|
+
const first = (lower - coordinate) / delta;
|
|
20
|
+
const second = (upper - coordinate) / delta;
|
|
21
|
+
from = Math.max(from, Math.min(first, second));
|
|
22
|
+
to = Math.min(to, Math.max(first, second));
|
|
23
|
+
return from <= to;
|
|
24
|
+
};
|
|
25
|
+
if (!clipDimension(origin.x, dx, bounds.left, bounds.right) ||
|
|
26
|
+
!clipDimension(origin.y, dy, bounds.top, bounds.bottom)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return [
|
|
30
|
+
{ x: origin.x + dx * from, y: origin.y + dy * from },
|
|
31
|
+
{ x: origin.x + dx * to, y: origin.y + dy * to },
|
|
32
|
+
];
|
|
33
|
+
}
|
|
34
|
+
function infiniteLine(start, end, bounds) {
|
|
35
|
+
return clippedLine(start, end, bounds, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
36
|
+
}
|
|
37
|
+
function ray(start, toward, bounds) {
|
|
38
|
+
return clippedLine(start, toward, bounds, 0, Number.POSITIVE_INFINITY);
|
|
39
|
+
}
|
|
40
|
+
function textRectangle(anchor, text, overlay, context, align, baseline) {
|
|
41
|
+
const measured = context.measureText(text, overlay);
|
|
42
|
+
const left = align === 'center' ? anchor.x - measured.width / 2 : anchor.x;
|
|
43
|
+
const top = baseline === 'middle' ? anchor.y - measured.height / 2 : anchor.y - measured.height;
|
|
44
|
+
return {
|
|
45
|
+
left,
|
|
46
|
+
top,
|
|
47
|
+
right: left + measured.width,
|
|
48
|
+
bottom: top + measured.height,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function projectPoints(overlay, context) {
|
|
52
|
+
return (overlay.points ?? []).map((point) => context.project(point));
|
|
53
|
+
}
|
|
54
|
+
function sequentialSegments(points) {
|
|
55
|
+
const segments = [];
|
|
56
|
+
for (let index = 1; index < points.length; index++) {
|
|
57
|
+
segments.push([points[index - 1], points[index]]);
|
|
58
|
+
}
|
|
59
|
+
return segments;
|
|
60
|
+
}
|
|
61
|
+
function parallelLines(points, bounds, includeMirror) {
|
|
62
|
+
if (points.length < 2)
|
|
63
|
+
return [];
|
|
64
|
+
const segments = [];
|
|
65
|
+
const base = infiniteLine(points[0], points[1], bounds);
|
|
66
|
+
if (base !== null)
|
|
67
|
+
segments.push(base);
|
|
68
|
+
if (points.length < 3)
|
|
69
|
+
return segments;
|
|
70
|
+
const parallelToward = {
|
|
71
|
+
x: points[2].x + points[1].x - points[0].x,
|
|
72
|
+
y: points[2].y + points[1].y - points[0].y,
|
|
73
|
+
};
|
|
74
|
+
const parallel = infiniteLine(points[2], parallelToward, bounds);
|
|
75
|
+
if (parallel !== null)
|
|
76
|
+
segments.push(parallel);
|
|
77
|
+
if (includeMirror) {
|
|
78
|
+
const mirroredOrigin = {
|
|
79
|
+
x: points[0].x * 2 - points[2].x,
|
|
80
|
+
y: points[0].y * 2 - points[2].y,
|
|
81
|
+
};
|
|
82
|
+
const mirroredToward = {
|
|
83
|
+
x: mirroredOrigin.x + points[1].x - points[0].x,
|
|
84
|
+
y: mirroredOrigin.y + points[1].y - points[0].y,
|
|
85
|
+
};
|
|
86
|
+
const mirrored = infiniteLine(mirroredOrigin, mirroredToward, bounds);
|
|
87
|
+
if (mirrored !== null)
|
|
88
|
+
segments.push(mirrored);
|
|
89
|
+
}
|
|
90
|
+
return segments;
|
|
91
|
+
}
|
|
92
|
+
function geometry(overlay, sceneIndex, anchors, bodySegments, bodyRectangles = []) {
|
|
93
|
+
return {
|
|
94
|
+
overlayId: overlay.id,
|
|
95
|
+
sceneIndex,
|
|
96
|
+
zLevel: overlay.zLevel,
|
|
97
|
+
locked: overlay.locked,
|
|
98
|
+
anchors,
|
|
99
|
+
bodySegments,
|
|
100
|
+
bodyRectangles,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/** 将 Drawing 业务几何投影成与画面一致的 CSS 像素命中几何。 */
|
|
104
|
+
export function projectOverlayGeometry(overlay, sceneIndex, context) {
|
|
105
|
+
const { bounds, referenceTimestamp, referenceValue } = context;
|
|
106
|
+
switch (overlay.type) {
|
|
107
|
+
case 'horizontalStraightLine':
|
|
108
|
+
case 'priceLine':
|
|
109
|
+
case 'simpleTag': {
|
|
110
|
+
const anchor = overlay.anchor;
|
|
111
|
+
if (anchor === undefined || !('value' in anchor))
|
|
112
|
+
return null;
|
|
113
|
+
const point = context.project({ timestamp: referenceTimestamp, value: anchor.value });
|
|
114
|
+
return geometry(overlay, sceneIndex, [point], [horizontal(bounds, point.y)]);
|
|
115
|
+
}
|
|
116
|
+
case 'verticalStraightLine': {
|
|
117
|
+
const anchor = overlay.anchor;
|
|
118
|
+
if (anchor === undefined || !('timestamp' in anchor))
|
|
119
|
+
return null;
|
|
120
|
+
const point = context.project({ timestamp: anchor.timestamp, value: referenceValue });
|
|
121
|
+
return geometry(overlay, sceneIndex, [point], [vertical(bounds, point.x)]);
|
|
122
|
+
}
|
|
123
|
+
case 'horizontalRayLine':
|
|
124
|
+
case 'horizontalSegment': {
|
|
125
|
+
if (overlay.value === undefined || overlay.startTimestamp === undefined ||
|
|
126
|
+
overlay.endTimestamp === undefined)
|
|
127
|
+
return null;
|
|
128
|
+
const start = context.project({ timestamp: overlay.startTimestamp, value: overlay.value });
|
|
129
|
+
const end = context.project({ timestamp: overlay.endTimestamp, value: overlay.value });
|
|
130
|
+
const body = overlay.type === 'horizontalRayLine' ? ray(start, end, bounds) : [start, end];
|
|
131
|
+
return geometry(overlay, sceneIndex, [start, end], body === null ? [] : [body]);
|
|
132
|
+
}
|
|
133
|
+
case 'verticalRayLine':
|
|
134
|
+
case 'verticalSegment': {
|
|
135
|
+
if (overlay.timestamp === undefined || overlay.startValue === undefined ||
|
|
136
|
+
overlay.endValue === undefined)
|
|
137
|
+
return null;
|
|
138
|
+
const start = context.project({ timestamp: overlay.timestamp, value: overlay.startValue });
|
|
139
|
+
const end = context.project({ timestamp: overlay.timestamp, value: overlay.endValue });
|
|
140
|
+
const body = overlay.type === 'verticalRayLine' ? ray(start, end, bounds) : [start, end];
|
|
141
|
+
return geometry(overlay, sceneIndex, [start, end], body === null ? [] : [body]);
|
|
142
|
+
}
|
|
143
|
+
case 'segment': {
|
|
144
|
+
const points = projectPoints(overlay, context);
|
|
145
|
+
return points.length < 2 ? null : geometry(overlay, sceneIndex, points, sequentialSegments(points));
|
|
146
|
+
}
|
|
147
|
+
case 'brush': {
|
|
148
|
+
const points = projectPoints(overlay, context);
|
|
149
|
+
return points.length < 2 ? null : geometry(overlay, sceneIndex, [], sequentialSegments(points));
|
|
150
|
+
}
|
|
151
|
+
case 'rayLine':
|
|
152
|
+
case 'straightLine': {
|
|
153
|
+
const points = projectPoints(overlay, context);
|
|
154
|
+
if (points.length < 2)
|
|
155
|
+
return null;
|
|
156
|
+
const body = overlay.type === 'rayLine'
|
|
157
|
+
? ray(points[0], points[1], bounds)
|
|
158
|
+
: infiniteLine(points[0], points[1], bounds);
|
|
159
|
+
return geometry(overlay, sceneIndex, points, body === null ? [] : [body]);
|
|
160
|
+
}
|
|
161
|
+
case 'fibonacciLine': {
|
|
162
|
+
const points = projectPoints(overlay, context);
|
|
163
|
+
if (points.length < 2)
|
|
164
|
+
return null;
|
|
165
|
+
const body = [1, 0.786, 0.618, 0.5, 0.382, 0.236, 0].map((percent) => {
|
|
166
|
+
const y = points[1].y + (points[0].y - points[1].y) * percent;
|
|
167
|
+
return horizontal(bounds, y);
|
|
168
|
+
});
|
|
169
|
+
return geometry(overlay, sceneIndex, points, body);
|
|
170
|
+
}
|
|
171
|
+
case 'parallelStraightLine':
|
|
172
|
+
case 'priceChannelLine': {
|
|
173
|
+
const points = projectPoints(overlay, context);
|
|
174
|
+
if (points.length < 2)
|
|
175
|
+
return null;
|
|
176
|
+
return geometry(overlay, sceneIndex, points, parallelLines(points, bounds, overlay.type === 'priceChannelLine'));
|
|
177
|
+
}
|
|
178
|
+
case 'simpleAnnotation': {
|
|
179
|
+
if (overlay.point === undefined)
|
|
180
|
+
return null;
|
|
181
|
+
const point = context.project(overlay.point);
|
|
182
|
+
const lineStart = { x: point.x, y: point.y - 6 };
|
|
183
|
+
const lineEnd = { x: point.x, y: point.y - 56 };
|
|
184
|
+
const labelAnchor = { x: point.x, y: point.y - 61 };
|
|
185
|
+
return geometry(overlay, sceneIndex, [point], [[lineStart, lineEnd]], [textRectangle(labelAnchor, overlay.text ?? '', overlay, context, 'center', 'bottom')]);
|
|
186
|
+
}
|
|
187
|
+
case 'callout': {
|
|
188
|
+
if (overlay.point === undefined)
|
|
189
|
+
return null;
|
|
190
|
+
const point = context.project(overlay.point);
|
|
191
|
+
const labelAnchor = { x: point.x + 16, y: point.y - 24 };
|
|
192
|
+
return geometry(overlay, sceneIndex, [point], [[point, labelAnchor]], [textRectangle(labelAnchor, overlay.text ?? '', overlay, context, 'left', 'bottom')]);
|
|
193
|
+
}
|
|
194
|
+
case 'text': {
|
|
195
|
+
if (overlay.point === undefined)
|
|
196
|
+
return null;
|
|
197
|
+
const point = context.project(overlay.point);
|
|
198
|
+
return geometry(overlay, sceneIndex, [point], [], [textRectangle(point, overlay.text ?? '', overlay, context, 'left', 'middle')]);
|
|
199
|
+
}
|
|
200
|
+
case 'crossLine': {
|
|
201
|
+
if (overlay.point === undefined)
|
|
202
|
+
return null;
|
|
203
|
+
const point = context.project(overlay.point);
|
|
204
|
+
return geometry(overlay, sceneIndex, [point], [horizontal(bounds, point.y), vertical(bounds, point.x)]);
|
|
205
|
+
}
|
|
206
|
+
case 'rectangle':
|
|
207
|
+
case 'priceMeasurement': {
|
|
208
|
+
if (overlay.start === undefined || overlay.end === undefined)
|
|
209
|
+
return null;
|
|
210
|
+
const start = context.project(overlay.start);
|
|
211
|
+
const end = context.project(overlay.end);
|
|
212
|
+
const rectangle = {
|
|
213
|
+
left: Math.min(start.x, end.x),
|
|
214
|
+
top: Math.min(start.y, end.y),
|
|
215
|
+
right: Math.max(start.x, end.x),
|
|
216
|
+
bottom: Math.max(start.y, end.y),
|
|
217
|
+
};
|
|
218
|
+
return geometry(overlay, sceneIndex, [start, end], [], [rectangle]);
|
|
219
|
+
}
|
|
220
|
+
case 'arrow': {
|
|
221
|
+
if (overlay.start === undefined || overlay.end === undefined)
|
|
222
|
+
return null;
|
|
223
|
+
const start = context.project(overlay.start);
|
|
224
|
+
const end = context.project(overlay.end);
|
|
225
|
+
return geometry(overlay, sceneIndex, [start, end], [[start, end]]);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export interface TouchPrecisionPoint {
|
|
2
|
+
readonly x: number;
|
|
3
|
+
readonly y: number;
|
|
4
|
+
}
|
|
5
|
+
export interface TouchPrecisionBounds {
|
|
6
|
+
readonly left: number;
|
|
7
|
+
readonly top: number;
|
|
8
|
+
readonly right: number;
|
|
9
|
+
readonly bottom: number;
|
|
10
|
+
}
|
|
11
|
+
export type TouchPrecisionDrawingPhase = 'move-start' | 'confirm-start' | 'confirm-end';
|
|
12
|
+
export declare const TOUCH_PRECISION_CURSOR_OFFSET: Readonly<{
|
|
13
|
+
x: -56;
|
|
14
|
+
y: -104;
|
|
15
|
+
}>;
|
|
16
|
+
export declare const TOUCH_PRECISION_TAP_DISTANCE = 8;
|
|
17
|
+
export declare function resolveTouchPrecisionCursor(pointer: TouchPrecisionPoint, bounds: TouchPrecisionBounds, offset?: TouchPrecisionPoint): TouchPrecisionPoint;
|
|
18
|
+
export declare function isTouchPrecisionTap(origin: TouchPrecisionPoint, current: TouchPrecisionPoint, threshold?: number): boolean;
|
|
19
|
+
export declare class TouchPrecisionDrawingGuide {
|
|
20
|
+
#private;
|
|
21
|
+
constructor(container: HTMLElement, onCancel: () => void);
|
|
22
|
+
show(): void;
|
|
23
|
+
hide(): void;
|
|
24
|
+
setPhase(phase: TouchPrecisionDrawingPhase): void;
|
|
25
|
+
updateCursor(point: TouchPrecisionPoint): void;
|
|
26
|
+
ownsCancelTarget(target: EventTarget | null): boolean;
|
|
27
|
+
destroy(): void;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=touch-precision-drawing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"touch-precision-drawing.d.ts","sourceRoot":"","sources":["../../src/interaction/touch-precision-drawing.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,MAAM,0BAA0B,GACnC,YAAY,GACZ,eAAe,GACf,aAAa,CAAC;AAEjB,eAAO,MAAM,6BAA6B;;;EAGxC,CAAC;AAEH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,wBAAgB,2BAA2B,CAC1C,OAAO,EAAE,mBAAmB,EAC5B,MAAM,EAAE,oBAAoB,EAC5B,MAAM,GAAE,mBAAmD,GACzD,mBAAmB,CAKrB;AAED,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,mBAAmB,EAC5B,SAAS,SAA+B,GACtC,OAAO,CAET;AAiLD,qBAAa,0BAA0B;;gBAUnB,SAAS,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI;IAqDxD,IAAI,IAAI,IAAI;IAIZ,IAAI,IAAI,IAAI;IAKZ,QAAQ,CAAC,KAAK,EAAE,0BAA0B,GAAG,IAAI;IAOjD,YAAY,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI;IAQ9C,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO;IAOrD,OAAO,IAAI,IAAI;CAOtB"}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
export const TOUCH_PRECISION_CURSOR_OFFSET = Object.freeze({
|
|
2
|
+
x: -56,
|
|
3
|
+
y: -104,
|
|
4
|
+
});
|
|
5
|
+
export const TOUCH_PRECISION_TAP_DISTANCE = 8;
|
|
6
|
+
export function resolveTouchPrecisionCursor(pointer, bounds, offset = TOUCH_PRECISION_CURSOR_OFFSET) {
|
|
7
|
+
return {
|
|
8
|
+
x: Math.max(bounds.left, Math.min(pointer.x + offset.x, bounds.right)),
|
|
9
|
+
y: Math.max(bounds.top, Math.min(pointer.y + offset.y, bounds.bottom)),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function isTouchPrecisionTap(origin, current, threshold = TOUCH_PRECISION_TAP_DISTANCE) {
|
|
13
|
+
return Math.hypot(current.x - origin.x, current.y - origin.y) < threshold;
|
|
14
|
+
}
|
|
15
|
+
const TOUCH_PRECISION_DRAWING_STYLES = String.raw `
|
|
16
|
+
.baron-touch-drawing-guide,
|
|
17
|
+
.baron-touch-drawing-guide * {
|
|
18
|
+
box-sizing: border-box;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.baron-touch-drawing-guide {
|
|
22
|
+
position: absolute;
|
|
23
|
+
inset: 0;
|
|
24
|
+
z-index: 50;
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
pointer-events: none;
|
|
27
|
+
font-family: inherit;
|
|
28
|
+
font-synthesis: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.baron-touch-drawing-guide[hidden] {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.baron-touch-drawing-guide__prompt {
|
|
36
|
+
position: absolute;
|
|
37
|
+
top: max(8px, env(safe-area-inset-top));
|
|
38
|
+
right: 8px;
|
|
39
|
+
left: 8px;
|
|
40
|
+
display: grid;
|
|
41
|
+
grid-template-columns: auto minmax(0, 1fr) 44px;
|
|
42
|
+
align-items: center;
|
|
43
|
+
min-height: 44px;
|
|
44
|
+
color: rgba(255, 255, 255, 0.96);
|
|
45
|
+
background: rgba(31, 34, 38, 0.94);
|
|
46
|
+
border: 1px solid rgba(255, 255, 255, 0.09);
|
|
47
|
+
border-radius: 12px;
|
|
48
|
+
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);
|
|
49
|
+
backdrop-filter: blur(10px);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.baron-touch-drawing-guide__progress {
|
|
53
|
+
min-width: 44px;
|
|
54
|
+
margin-left: 6px;
|
|
55
|
+
padding: 6px 8px;
|
|
56
|
+
color: rgba(255, 255, 255, 0.8);
|
|
57
|
+
background: rgba(255, 255, 255, 0.1);
|
|
58
|
+
border-radius: 8px;
|
|
59
|
+
font-size: 11px;
|
|
60
|
+
font-variant-numeric: tabular-nums;
|
|
61
|
+
font-weight: 750;
|
|
62
|
+
line-height: 1;
|
|
63
|
+
text-align: center;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.baron-touch-drawing-guide__message {
|
|
67
|
+
min-width: 0;
|
|
68
|
+
padding: 0 10px;
|
|
69
|
+
overflow: hidden;
|
|
70
|
+
font-size: 13px;
|
|
71
|
+
font-weight: 700;
|
|
72
|
+
line-height: 18px;
|
|
73
|
+
text-align: center;
|
|
74
|
+
text-overflow: ellipsis;
|
|
75
|
+
white-space: nowrap;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.baron-touch-drawing-guide__cancel {
|
|
79
|
+
display: grid;
|
|
80
|
+
width: 44px;
|
|
81
|
+
height: 44px;
|
|
82
|
+
padding: 0;
|
|
83
|
+
place-items: center;
|
|
84
|
+
color: rgba(255, 255, 255, 0.82);
|
|
85
|
+
background: transparent;
|
|
86
|
+
border: 0;
|
|
87
|
+
border-radius: 10px;
|
|
88
|
+
cursor: pointer;
|
|
89
|
+
pointer-events: auto;
|
|
90
|
+
touch-action: manipulation;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.baron-touch-drawing-guide__cancel:active {
|
|
94
|
+
color: rgba(255, 255, 255, 1);
|
|
95
|
+
background: rgba(255, 255, 255, 0.12);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.baron-touch-drawing-guide__cancel:focus-visible {
|
|
99
|
+
outline: 2px solid rgba(112, 140, 255, 1);
|
|
100
|
+
outline-offset: -3px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.baron-touch-drawing-guide__cancel svg {
|
|
104
|
+
width: 20px;
|
|
105
|
+
height: 20px;
|
|
106
|
+
fill: none;
|
|
107
|
+
stroke: currentcolor;
|
|
108
|
+
stroke-linecap: round;
|
|
109
|
+
stroke-linejoin: round;
|
|
110
|
+
stroke-width: 1.8;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.baron-touch-drawing-guide__cursor {
|
|
114
|
+
position: absolute;
|
|
115
|
+
top: 0;
|
|
116
|
+
left: 0;
|
|
117
|
+
display: none;
|
|
118
|
+
width: 0;
|
|
119
|
+
height: 0;
|
|
120
|
+
transform: translate3d(
|
|
121
|
+
var(--baron-touch-cursor-x, 0),
|
|
122
|
+
var(--baron-touch-cursor-y, 0),
|
|
123
|
+
0
|
|
124
|
+
);
|
|
125
|
+
transition: opacity 120ms ease;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.baron-touch-drawing-guide[data-has-cursor="true"] .baron-touch-drawing-guide__cursor {
|
|
129
|
+
display: block;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.baron-touch-drawing-guide__cursor::before,
|
|
133
|
+
.baron-touch-drawing-guide__cursor::after {
|
|
134
|
+
position: absolute;
|
|
135
|
+
content: "";
|
|
136
|
+
opacity: 0.72;
|
|
137
|
+
pointer-events: none;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.baron-touch-drawing-guide__cursor::before {
|
|
141
|
+
top: calc(-1 * var(--baron-touch-cursor-y, 0));
|
|
142
|
+
left: 0;
|
|
143
|
+
width: 0;
|
|
144
|
+
height: 100vh;
|
|
145
|
+
border-left: 1px dashed rgba(41, 98, 255, 0.72);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.baron-touch-drawing-guide__cursor::after {
|
|
149
|
+
top: 0;
|
|
150
|
+
left: calc(-1 * var(--baron-touch-cursor-x, 0));
|
|
151
|
+
width: 100vw;
|
|
152
|
+
height: 0;
|
|
153
|
+
border-top: 1px dashed rgba(41, 98, 255, 0.72);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.baron-touch-drawing-guide__cursor-dot {
|
|
157
|
+
position: absolute;
|
|
158
|
+
top: -4px;
|
|
159
|
+
left: -4px;
|
|
160
|
+
z-index: 1;
|
|
161
|
+
width: 9px;
|
|
162
|
+
height: 9px;
|
|
163
|
+
background: rgba(41, 98, 255, 1);
|
|
164
|
+
border: 2px solid rgba(255, 255, 255, 0.98);
|
|
165
|
+
border-radius: 50%;
|
|
166
|
+
box-shadow: 0 1px 5px rgba(17, 24, 39, 0.24);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@media (prefers-reduced-motion: reduce) {
|
|
170
|
+
.baron-touch-drawing-guide__cursor {
|
|
171
|
+
transition: none;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
175
|
+
function promptForPhase(phase) {
|
|
176
|
+
switch (phase) {
|
|
177
|
+
case 'move-start':
|
|
178
|
+
return { progress: '1 / 4', message: '将光标移至起点' };
|
|
179
|
+
case 'confirm-start':
|
|
180
|
+
return { progress: '2 / 4', message: '点击设置第一个点' };
|
|
181
|
+
case 'confirm-end':
|
|
182
|
+
return { progress: '4 / 4', message: '点击即可完成' };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export class TouchPrecisionDrawingGuide {
|
|
186
|
+
#container;
|
|
187
|
+
#root;
|
|
188
|
+
#progress;
|
|
189
|
+
#message;
|
|
190
|
+
#cancel;
|
|
191
|
+
#originalInlinePosition;
|
|
192
|
+
#changedContainerPosition;
|
|
193
|
+
#handleCancel;
|
|
194
|
+
constructor(container, onCancel) {
|
|
195
|
+
this.#container = container;
|
|
196
|
+
this.#originalInlinePosition = container.style.position;
|
|
197
|
+
this.#changedContainerPosition = (container.ownerDocument.defaultView?.getComputedStyle(container).position ??
|
|
198
|
+
container.style.position) === 'static';
|
|
199
|
+
if (this.#changedContainerPosition) {
|
|
200
|
+
container.style.position = 'relative';
|
|
201
|
+
}
|
|
202
|
+
const document = container.ownerDocument;
|
|
203
|
+
const root = document.createElement('div');
|
|
204
|
+
root.className = 'baron-touch-drawing-guide';
|
|
205
|
+
root.dataset.touchDrawingGuide = '';
|
|
206
|
+
root.hidden = true;
|
|
207
|
+
const style = document.createElement('style');
|
|
208
|
+
style.dataset.baronTouchDrawingGuideStyles = '';
|
|
209
|
+
style.textContent = TOUCH_PRECISION_DRAWING_STYLES;
|
|
210
|
+
const prompt = document.createElement('div');
|
|
211
|
+
prompt.className = 'baron-touch-drawing-guide__prompt';
|
|
212
|
+
const progress = document.createElement('span');
|
|
213
|
+
progress.className = 'baron-touch-drawing-guide__progress';
|
|
214
|
+
const message = document.createElement('span');
|
|
215
|
+
message.className = 'baron-touch-drawing-guide__message';
|
|
216
|
+
message.setAttribute('role', 'status');
|
|
217
|
+
message.setAttribute('aria-live', 'polite');
|
|
218
|
+
const cancel = document.createElement('button');
|
|
219
|
+
cancel.type = 'button';
|
|
220
|
+
cancel.className = 'baron-touch-drawing-guide__cancel';
|
|
221
|
+
cancel.dataset.touchDrawingCancel = '';
|
|
222
|
+
cancel.setAttribute('aria-label', '取消绘制线段');
|
|
223
|
+
cancel.innerHTML = '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 7h14M9 7V4h6v3m-8 0 1 13h8l1-13M10 11v5m4-5v5"/></svg>';
|
|
224
|
+
prompt.append(progress, message, cancel);
|
|
225
|
+
const cursor = document.createElement('div');
|
|
226
|
+
cursor.className = 'baron-touch-drawing-guide__cursor';
|
|
227
|
+
const dot = document.createElement('span');
|
|
228
|
+
dot.className = 'baron-touch-drawing-guide__cursor-dot';
|
|
229
|
+
cursor.append(dot);
|
|
230
|
+
root.append(style, prompt, cursor);
|
|
231
|
+
container.append(root);
|
|
232
|
+
this.#root = root;
|
|
233
|
+
this.#progress = progress;
|
|
234
|
+
this.#message = message;
|
|
235
|
+
this.#cancel = cancel;
|
|
236
|
+
this.#handleCancel = () => onCancel();
|
|
237
|
+
cancel.addEventListener('click', this.#handleCancel);
|
|
238
|
+
this.setPhase('move-start');
|
|
239
|
+
}
|
|
240
|
+
show() {
|
|
241
|
+
this.#root.hidden = false;
|
|
242
|
+
}
|
|
243
|
+
hide() {
|
|
244
|
+
this.#root.hidden = true;
|
|
245
|
+
delete this.#root.dataset.hasCursor;
|
|
246
|
+
}
|
|
247
|
+
setPhase(phase) {
|
|
248
|
+
const prompt = promptForPhase(phase);
|
|
249
|
+
this.#root.dataset.phase = phase;
|
|
250
|
+
this.#progress.textContent = prompt.progress;
|
|
251
|
+
this.#message.textContent = prompt.message;
|
|
252
|
+
}
|
|
253
|
+
updateCursor(point) {
|
|
254
|
+
this.#root.dataset.hasCursor = 'true';
|
|
255
|
+
this.#root.dataset.cursorX = String(Math.round(point.x));
|
|
256
|
+
this.#root.dataset.cursorY = String(Math.round(point.y));
|
|
257
|
+
this.#root.style.setProperty('--baron-touch-cursor-x', `${point.x}px`);
|
|
258
|
+
this.#root.style.setProperty('--baron-touch-cursor-y', `${point.y}px`);
|
|
259
|
+
}
|
|
260
|
+
ownsCancelTarget(target) {
|
|
261
|
+
return target !== null &&
|
|
262
|
+
typeof target === 'object' &&
|
|
263
|
+
'nodeType' in target &&
|
|
264
|
+
this.#cancel.contains(target);
|
|
265
|
+
}
|
|
266
|
+
destroy() {
|
|
267
|
+
this.#cancel.removeEventListener('click', this.#handleCancel);
|
|
268
|
+
this.#root.remove();
|
|
269
|
+
if (this.#changedContainerPosition) {
|
|
270
|
+
this.#container.style.position = this.#originalInlinePosition;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DataLoader, DataLoaderGetBarsParams } from 'klinecharts';
|
|
1
|
+
import type { DataLoader, DataLoaderGetBarsParams, KLineData } from 'klinecharts';
|
|
3
2
|
export type StaticDataLoadType = DataLoaderGetBarsParams['type'];
|
|
4
3
|
/** 创建只读取场景内嵌行情的不可变数据加载器。 */
|
|
5
|
-
export declare function createStaticDataLoader(data: readonly
|
|
4
|
+
export declare function createStaticDataLoader(data: readonly KLineData[]): DataLoader;
|
|
6
5
|
//# sourceMappingURL=static-data-loader.d.ts.map
|