@tradingaction/interactive 2.0.13
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/LICENSE +24 -0
- package/README.md +5 -0
- package/lib/Brush.d.ts +35 -0
- package/lib/Brush.js +103 -0
- package/lib/Brush.js.map +1 -0
- package/lib/ClickCallback.d.ts +18 -0
- package/lib/ClickCallback.js +12 -0
- package/lib/ClickCallback.js.map +1 -0
- package/lib/DrawingObjectSelector.d.ts +18 -0
- package/lib/DrawingObjectSelector.js +73 -0
- package/lib/DrawingObjectSelector.js.map +1 -0
- package/lib/EquidistantChannel.d.ts +74 -0
- package/lib/EquidistantChannel.js +149 -0
- package/lib/EquidistantChannel.js.map +1 -0
- package/lib/FibonacciRetracement.d.ts +89 -0
- package/lib/FibonacciRetracement.js +184 -0
- package/lib/FibonacciRetracement.js.map +1 -0
- package/lib/GannFan.d.ts +78 -0
- package/lib/GannFan.js +128 -0
- package/lib/GannFan.js.map +1 -0
- package/lib/InteractiveText.d.ts +65 -0
- package/lib/InteractiveText.js +83 -0
- package/lib/InteractiveText.js.map +1 -0
- package/lib/InteractiveYCoordinate.d.ts +122 -0
- package/lib/InteractiveYCoordinate.js +100 -0
- package/lib/InteractiveYCoordinate.js.map +1 -0
- package/lib/StandardDeviationChannel.d.ts +74 -0
- package/lib/StandardDeviationChannel.js +125 -0
- package/lib/StandardDeviationChannel.js.map +1 -0
- package/lib/TrendLine.d.ts +84 -0
- package/lib/TrendLine.js +128 -0
- package/lib/TrendLine.js.map +1 -0
- package/lib/ZoomButtons.d.ts +30 -0
- package/lib/ZoomButtons.js +78 -0
- package/lib/ZoomButtons.js.map +1 -0
- package/lib/components/ChannelWithArea.d.ts +30 -0
- package/lib/components/ChannelWithArea.js +126 -0
- package/lib/components/ChannelWithArea.js.map +1 -0
- package/lib/components/ClickableCircle.d.ts +26 -0
- package/lib/components/ClickableCircle.js +48 -0
- package/lib/components/ClickableCircle.js.map +1 -0
- package/lib/components/ClickableShape.d.ts +33 -0
- package/lib/components/ClickableShape.js +64 -0
- package/lib/components/ClickableShape.js.map +1 -0
- package/lib/components/GannFan.d.ts +32 -0
- package/lib/components/GannFan.js +134 -0
- package/lib/components/GannFan.js.map +1 -0
- package/lib/components/HoverTextNearMouse.d.ts +35 -0
- package/lib/components/HoverTextNearMouse.js +113 -0
- package/lib/components/HoverTextNearMouse.js.map +1 -0
- package/lib/components/InteractiveStraightLine.d.ts +61 -0
- package/lib/components/InteractiveStraightLine.js +220 -0
- package/lib/components/InteractiveStraightLine.js.map +1 -0
- package/lib/components/InteractiveText.d.ts +38 -0
- package/lib/components/InteractiveText.js +84 -0
- package/lib/components/InteractiveText.js.map +1 -0
- package/lib/components/InteractiveYCoordinate.d.ts +46 -0
- package/lib/components/InteractiveYCoordinate.js +109 -0
- package/lib/components/InteractiveYCoordinate.js.map +1 -0
- package/lib/components/LinearRegressionChannelWithArea.d.ts +31 -0
- package/lib/components/LinearRegressionChannelWithArea.js +104 -0
- package/lib/components/LinearRegressionChannelWithArea.js.map +1 -0
- package/lib/components/MouseLocationIndicator.d.ts +34 -0
- package/lib/components/MouseLocationIndicator.js +79 -0
- package/lib/components/MouseLocationIndicator.js.map +1 -0
- package/lib/components/Text.d.ts +17 -0
- package/lib/components/Text.js +26 -0
- package/lib/components/Text.js.map +1 -0
- package/lib/components/index.d.ts +11 -0
- package/lib/components/index.js +12 -0
- package/lib/components/index.js.map +1 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -0
- package/lib/utils.d.ts +7 -0
- package/lib/utils.js +84 -0
- package/lib/utils.js.map +1 -0
- package/lib/wrapper/EachEquidistantChannel.d.ts +59 -0
- package/lib/wrapper/EachEquidistantChannel.js +172 -0
- package/lib/wrapper/EachEquidistantChannel.js.map +1 -0
- package/lib/wrapper/EachFibRetracement.d.ts +81 -0
- package/lib/wrapper/EachFibRetracement.js +202 -0
- package/lib/wrapper/EachFibRetracement.js.map +1 -0
- package/lib/wrapper/EachGannFan.d.ts +81 -0
- package/lib/wrapper/EachGannFan.js +161 -0
- package/lib/wrapper/EachGannFan.js.map +1 -0
- package/lib/wrapper/EachInteractiveYCoordinate.d.ts +50 -0
- package/lib/wrapper/EachInteractiveYCoordinate.js +80 -0
- package/lib/wrapper/EachInteractiveYCoordinate.js.map +1 -0
- package/lib/wrapper/EachLinearRegressionChannel.d.ts +75 -0
- package/lib/wrapper/EachLinearRegressionChannel.js +89 -0
- package/lib/wrapper/EachLinearRegressionChannel.js.map +1 -0
- package/lib/wrapper/EachText.d.ts +59 -0
- package/lib/wrapper/EachText.js +83 -0
- package/lib/wrapper/EachText.js.map +1 -0
- package/lib/wrapper/EachTrendLine.d.ts +85 -0
- package/lib/wrapper/EachTrendLine.js +165 -0
- package/lib/wrapper/EachTrendLine.js.map +1 -0
- package/lib/wrapper/index.d.ts +7 -0
- package/lib/wrapper/index.js +8 -0
- package/lib/wrapper/index.js.map +1 -0
- package/package.json +53 -0
- package/src/Brush.tsx +172 -0
- package/src/ClickCallback.tsx +37 -0
- package/src/DrawingObjectSelector.tsx +97 -0
- package/src/EquidistantChannel.tsx +268 -0
- package/src/FibonacciRetracement.tsx +328 -0
- package/src/GannFan.tsx +233 -0
- package/src/InteractiveText.tsx +182 -0
- package/src/InteractiveYCoordinate.tsx +199 -0
- package/src/StandardDeviationChannel.tsx +269 -0
- package/src/TrendLine.tsx +294 -0
- package/src/ZoomButtons.tsx +165 -0
- package/src/components/ChannelWithArea.tsx +199 -0
- package/src/components/ClickableCircle.tsx +91 -0
- package/src/components/ClickableShape.tsx +114 -0
- package/src/components/GannFan.tsx +189 -0
- package/src/components/HoverTextNearMouse.tsx +174 -0
- package/src/components/InteractiveStraightLine.tsx +335 -0
- package/src/components/InteractiveText.tsx +146 -0
- package/src/components/InteractiveYCoordinate.tsx +200 -0
- package/src/components/LinearRegressionChannelWithArea.tsx +169 -0
- package/src/components/MouseLocationIndicator.tsx +128 -0
- package/src/components/Text.tsx +47 -0
- package/src/components/index.ts +11 -0
- package/src/index.ts +12 -0
- package/src/utils.ts +101 -0
- package/src/wrapper/EachEquidistantChannel.tsx +302 -0
- package/src/wrapper/EachFibRetracement.tsx +359 -0
- package/src/wrapper/EachGannFan.tsx +289 -0
- package/src/wrapper/EachInteractiveYCoordinate.tsx +198 -0
- package/src/wrapper/EachLinearRegressionChannel.tsx +202 -0
- package/src/wrapper/EachText.tsx +190 -0
- package/src/wrapper/EachTrendLine.tsx +331 -0
- package/src/wrapper/index.ts +7 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { ChartContext, last } from "@tradingaction/core";
|
|
2
|
+
import { interpolateNumber } from "d3-interpolate";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
|
|
5
|
+
export interface ZoomButtonsProps {
|
|
6
|
+
readonly fill: string;
|
|
7
|
+
readonly fillOpacity: number;
|
|
8
|
+
readonly heightFromBase: number;
|
|
9
|
+
readonly onReset?: () => void;
|
|
10
|
+
readonly r: number;
|
|
11
|
+
readonly stroke: string;
|
|
12
|
+
readonly strokeWidth: number;
|
|
13
|
+
readonly textFill: string;
|
|
14
|
+
readonly zoomMultiplier: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class ZoomButtons extends React.Component<ZoomButtonsProps> {
|
|
18
|
+
public static defaultProps = {
|
|
19
|
+
fill: "#ffffff",
|
|
20
|
+
fillOpacity: 0.75,
|
|
21
|
+
heightFromBase: 32,
|
|
22
|
+
r: 16,
|
|
23
|
+
stroke: "#e0e3eb",
|
|
24
|
+
strokeWidth: 1,
|
|
25
|
+
textFill: "#000000",
|
|
26
|
+
zoomMultiplier: 1.5,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
public static contextType = ChartContext;
|
|
30
|
+
|
|
31
|
+
private interval?: number;
|
|
32
|
+
|
|
33
|
+
public render() {
|
|
34
|
+
const { chartConfig } = this.context;
|
|
35
|
+
|
|
36
|
+
const { width, height } = chartConfig;
|
|
37
|
+
|
|
38
|
+
const { heightFromBase, r, fill, fillOpacity, onReset, stroke, strokeWidth, textFill } = this.props;
|
|
39
|
+
|
|
40
|
+
const centerX = Math.round(width / 2);
|
|
41
|
+
const y = height - heightFromBase;
|
|
42
|
+
|
|
43
|
+
const zoomOutX = centerX - 16 - r * 2;
|
|
44
|
+
const zoomInX = centerX - 8;
|
|
45
|
+
const resetX = centerX + 16 + r * 2;
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<g className="react-financial-charts-zoom-buttons">
|
|
49
|
+
<circle
|
|
50
|
+
className="react-financial-charts-button"
|
|
51
|
+
cx={zoomOutX - r / 2}
|
|
52
|
+
cy={y + r / 2}
|
|
53
|
+
fill={fill}
|
|
54
|
+
fillOpacity={fillOpacity}
|
|
55
|
+
stroke={stroke}
|
|
56
|
+
strokeWidth={strokeWidth}
|
|
57
|
+
r={r}
|
|
58
|
+
/>
|
|
59
|
+
<g transform={`translate (${zoomOutX - 20}, ${y - 8 + r / 4})`}>
|
|
60
|
+
<path d="M19,13H5V11H19V13Z" fill={textFill} />
|
|
61
|
+
</g>
|
|
62
|
+
<circle
|
|
63
|
+
className="react-financial-charts-button"
|
|
64
|
+
cx={zoomInX - r / 2}
|
|
65
|
+
cy={y + r / 2}
|
|
66
|
+
fill={fill}
|
|
67
|
+
fillOpacity={fillOpacity}
|
|
68
|
+
stroke={stroke}
|
|
69
|
+
strokeWidth={strokeWidth}
|
|
70
|
+
r={r}
|
|
71
|
+
/>
|
|
72
|
+
<g transform={`translate (${zoomInX - 20}, ${y - 8 + r / 4})`}>
|
|
73
|
+
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z" fill={textFill} />
|
|
74
|
+
</g>
|
|
75
|
+
<circle
|
|
76
|
+
className="react-financial-charts-button"
|
|
77
|
+
cx={resetX - r / 2}
|
|
78
|
+
cy={y + r / 2}
|
|
79
|
+
fill={fill}
|
|
80
|
+
fillOpacity={fillOpacity}
|
|
81
|
+
stroke={stroke}
|
|
82
|
+
strokeWidth={strokeWidth}
|
|
83
|
+
r={r}
|
|
84
|
+
/>
|
|
85
|
+
<g transform={`translate (${resetX - r}, ${y - 4 + r / 4})`}>
|
|
86
|
+
<path
|
|
87
|
+
d="M2.35 2.35A7.958 7.958 0 018 0a8 8 0 110 16c-3.73 0-6.84-2.55-7.73-6h2.08c.82 2.33 3.04 4 5.65 4A6 6 0 108 2c-1.66 0-3.14.69-4.22 1.78L7 7H0V0l2.35 2.35z"
|
|
88
|
+
fill={textFill}
|
|
89
|
+
/>
|
|
90
|
+
</g>
|
|
91
|
+
<circle
|
|
92
|
+
className="react-financial-charts-enable-interaction out"
|
|
93
|
+
onClick={this.handleZoomOut}
|
|
94
|
+
cx={zoomOutX - r / 2}
|
|
95
|
+
cy={y + r / 2}
|
|
96
|
+
r={r}
|
|
97
|
+
fill="none"
|
|
98
|
+
/>
|
|
99
|
+
<circle
|
|
100
|
+
className="react-financial-charts-enable-interaction in"
|
|
101
|
+
onClick={this.handleZoomIn}
|
|
102
|
+
cx={zoomInX - r / 2}
|
|
103
|
+
cy={y + r / 2}
|
|
104
|
+
r={r}
|
|
105
|
+
fill="none"
|
|
106
|
+
/>
|
|
107
|
+
<circle
|
|
108
|
+
className="react-financial-charts-enable-interaction reset"
|
|
109
|
+
onClick={onReset}
|
|
110
|
+
cx={resetX - r / 2}
|
|
111
|
+
cy={y + r / 2}
|
|
112
|
+
r={r}
|
|
113
|
+
fill="none"
|
|
114
|
+
/>
|
|
115
|
+
</g>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private readonly handleZoomIn = () => {
|
|
120
|
+
if (this.interval) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.zoom(-1);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
private readonly handleZoomOut = () => {
|
|
128
|
+
if (this.interval) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.zoom(1);
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
private readonly zoom = (direction: number) => {
|
|
136
|
+
const { xAxisZoom, xScale, plotData, xAccessor } = this.context;
|
|
137
|
+
|
|
138
|
+
const cx = xScale(xAccessor(last(plotData)));
|
|
139
|
+
|
|
140
|
+
const { zoomMultiplier } = this.props;
|
|
141
|
+
|
|
142
|
+
const c = direction > 0 ? 1 * zoomMultiplier : 1 / zoomMultiplier;
|
|
143
|
+
|
|
144
|
+
const [start, end] = xScale.domain();
|
|
145
|
+
const [newStart, newEnd] = xScale
|
|
146
|
+
.range()
|
|
147
|
+
.map((x: number) => cx + (x - cx) * c)
|
|
148
|
+
.map(xScale.invert);
|
|
149
|
+
|
|
150
|
+
const left = interpolateNumber(start, newStart);
|
|
151
|
+
const right = interpolateNumber(end, newEnd);
|
|
152
|
+
|
|
153
|
+
const foo = [0.25, 0.3, 0.5, 0.6, 0.75, 1].map((i) => {
|
|
154
|
+
return [left(i), right(i)];
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
this.interval = window.setInterval(() => {
|
|
158
|
+
xAxisZoom(foo.shift());
|
|
159
|
+
if (foo.length === 0) {
|
|
160
|
+
clearInterval(this.interval);
|
|
161
|
+
delete this.interval;
|
|
162
|
+
}
|
|
163
|
+
}, 10);
|
|
164
|
+
};
|
|
165
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { isDefined, isNotDefined, getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
|
|
3
|
+
import { generateLine, isHovering } from "./InteractiveStraightLine";
|
|
4
|
+
|
|
5
|
+
export interface ChannelWithAreaProps {
|
|
6
|
+
readonly startXY?: number[];
|
|
7
|
+
readonly endXY?: number[];
|
|
8
|
+
readonly dy?: number;
|
|
9
|
+
readonly interactiveCursorClass?: string;
|
|
10
|
+
readonly strokeStyle: string;
|
|
11
|
+
readonly strokeWidth: number;
|
|
12
|
+
readonly fillStyle: string;
|
|
13
|
+
readonly type:
|
|
14
|
+
| "XLINE" // extends from -Infinity to +Infinity
|
|
15
|
+
| "RAY" // extends to +/-Infinity in one direction
|
|
16
|
+
| "LINE"; // extends between the set bounds
|
|
17
|
+
readonly onDragStart?: (e: React.MouseEvent, moreProps: any) => void;
|
|
18
|
+
readonly onDrag?: (e: React.MouseEvent, moreProps: any) => void;
|
|
19
|
+
readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
|
|
20
|
+
readonly onHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
21
|
+
readonly onUnHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
22
|
+
readonly defaultClassName?: string;
|
|
23
|
+
readonly tolerance: number;
|
|
24
|
+
readonly selected: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class ChannelWithArea extends React.Component<ChannelWithAreaProps> {
|
|
28
|
+
public static defaultProps = {
|
|
29
|
+
type: "LINE",
|
|
30
|
+
strokeWidth: 1,
|
|
31
|
+
tolerance: 4,
|
|
32
|
+
selected: false,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
public render() {
|
|
36
|
+
const { selected, interactiveCursorClass } = this.props;
|
|
37
|
+
const { onDragStart, onDrag, onDragComplete, onHover, onUnHover } = this.props;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<GenericChartComponent
|
|
41
|
+
isHover={this.isHover}
|
|
42
|
+
canvasToDraw={getMouseCanvas}
|
|
43
|
+
canvasDraw={this.drawOnCanvas}
|
|
44
|
+
interactiveCursorClass={interactiveCursorClass}
|
|
45
|
+
selected={selected}
|
|
46
|
+
onDragStart={onDragStart}
|
|
47
|
+
onDrag={onDrag}
|
|
48
|
+
onDragComplete={onDragComplete}
|
|
49
|
+
onHover={onHover}
|
|
50
|
+
onUnHover={onUnHover}
|
|
51
|
+
drawOn={["mousemove", "mouseleave", "pan", "drag"]}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
|
|
57
|
+
const { strokeStyle, strokeWidth, fillStyle } = this.props;
|
|
58
|
+
const { line1, line2 } = helper(this.props, moreProps);
|
|
59
|
+
|
|
60
|
+
if (line1 !== undefined) {
|
|
61
|
+
const { x1, y1, x2, y2 } = line1;
|
|
62
|
+
|
|
63
|
+
ctx.lineWidth = strokeWidth;
|
|
64
|
+
ctx.strokeStyle = strokeStyle;
|
|
65
|
+
|
|
66
|
+
ctx.beginPath();
|
|
67
|
+
ctx.moveTo(x1, y1);
|
|
68
|
+
ctx.lineTo(x2, y2);
|
|
69
|
+
ctx.stroke();
|
|
70
|
+
|
|
71
|
+
if (line2 !== undefined) {
|
|
72
|
+
const { y1: line2Y1, y2: line2Y2 } = line2;
|
|
73
|
+
|
|
74
|
+
ctx.beginPath();
|
|
75
|
+
ctx.moveTo(x1, line2Y1);
|
|
76
|
+
ctx.lineTo(x2, line2Y2);
|
|
77
|
+
ctx.stroke();
|
|
78
|
+
|
|
79
|
+
ctx.fillStyle = fillStyle;
|
|
80
|
+
ctx.beginPath();
|
|
81
|
+
ctx.moveTo(x1, y1);
|
|
82
|
+
|
|
83
|
+
ctx.lineTo(x2, y2);
|
|
84
|
+
ctx.lineTo(x2, line2Y2);
|
|
85
|
+
ctx.lineTo(x1, line2Y1);
|
|
86
|
+
|
|
87
|
+
ctx.closePath();
|
|
88
|
+
ctx.fill();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
private readonly isHover = (moreProps: any) => {
|
|
94
|
+
const { tolerance, onHover } = this.props;
|
|
95
|
+
|
|
96
|
+
if (onHover !== undefined) {
|
|
97
|
+
const { line1, line2 } = helper(this.props, moreProps);
|
|
98
|
+
|
|
99
|
+
if (line1 !== undefined && line2 !== undefined) {
|
|
100
|
+
const {
|
|
101
|
+
mouseXY,
|
|
102
|
+
xScale,
|
|
103
|
+
chartConfig: { yScale },
|
|
104
|
+
} = moreProps;
|
|
105
|
+
|
|
106
|
+
const line1Hovering = isHovering({
|
|
107
|
+
x1Value: line1.x1,
|
|
108
|
+
y1Value: line1.y1,
|
|
109
|
+
x2Value: line1.x2,
|
|
110
|
+
y2Value: line1.y2,
|
|
111
|
+
type: "LINE",
|
|
112
|
+
mouseXY,
|
|
113
|
+
tolerance,
|
|
114
|
+
xScale,
|
|
115
|
+
yScale,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const line2Hovering = isHovering({
|
|
119
|
+
x1Value: line2.x1,
|
|
120
|
+
y1Value: line2.y1,
|
|
121
|
+
x2Value: line2.x2,
|
|
122
|
+
y2Value: line2.y2,
|
|
123
|
+
type: "LINE",
|
|
124
|
+
mouseXY,
|
|
125
|
+
tolerance,
|
|
126
|
+
xScale,
|
|
127
|
+
yScale,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return line1Hovering || line2Hovering;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return false;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function getLines(props: ChannelWithAreaProps, moreProps: any) {
|
|
138
|
+
const { startXY, endXY, dy, type } = props;
|
|
139
|
+
const { xScale } = moreProps;
|
|
140
|
+
|
|
141
|
+
if (isNotDefined(startXY) || isNotDefined(endXY)) {
|
|
142
|
+
return {};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const line1 = generateLine({
|
|
146
|
+
type,
|
|
147
|
+
start: startXY,
|
|
148
|
+
end: endXY,
|
|
149
|
+
xScale,
|
|
150
|
+
yScale: undefined,
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const line2 = isDefined(dy)
|
|
154
|
+
? {
|
|
155
|
+
...line1,
|
|
156
|
+
y1: line1.y1 + dy,
|
|
157
|
+
y2: line1.y2 + dy,
|
|
158
|
+
}
|
|
159
|
+
: undefined;
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
line1,
|
|
163
|
+
line2,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function helper(props: ChannelWithAreaProps, moreProps: any) {
|
|
168
|
+
const lines = getLines(props, moreProps);
|
|
169
|
+
const {
|
|
170
|
+
xScale,
|
|
171
|
+
chartConfig: { yScale },
|
|
172
|
+
} = moreProps;
|
|
173
|
+
|
|
174
|
+
const line1 =
|
|
175
|
+
lines.line1 !== undefined
|
|
176
|
+
? {
|
|
177
|
+
x1: xScale(lines.line1.x1),
|
|
178
|
+
y1: yScale(lines.line1.y1),
|
|
179
|
+
x2: xScale(lines.line1.x2),
|
|
180
|
+
y2: yScale(lines.line1.y2),
|
|
181
|
+
}
|
|
182
|
+
: undefined;
|
|
183
|
+
|
|
184
|
+
const line2 =
|
|
185
|
+
lines.line2 !== undefined
|
|
186
|
+
? {
|
|
187
|
+
x1: line1!.x1,
|
|
188
|
+
y1: yScale(lines.line2.y1),
|
|
189
|
+
x2: line1!.x2,
|
|
190
|
+
y2: yScale(lines.line2.y2),
|
|
191
|
+
}
|
|
192
|
+
: undefined;
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
lines,
|
|
196
|
+
line1,
|
|
197
|
+
line2,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
|
|
4
|
+
|
|
5
|
+
export interface ClickableCircleProps {
|
|
6
|
+
readonly onDragStart?: (e: React.MouseEvent, moreProps: any) => void;
|
|
7
|
+
readonly onDrag?: (e: React.MouseEvent, moreProps: any) => void;
|
|
8
|
+
readonly onDragComplete?: (e: React.MouseEvent, moreProps: any) => void;
|
|
9
|
+
readonly strokeWidth: number;
|
|
10
|
+
readonly strokeStyle: string;
|
|
11
|
+
readonly fillStyle: string;
|
|
12
|
+
readonly r: number;
|
|
13
|
+
readonly cx?: number;
|
|
14
|
+
readonly cy?: number;
|
|
15
|
+
readonly className: string;
|
|
16
|
+
readonly show: boolean;
|
|
17
|
+
readonly interactiveCursorClass?: string;
|
|
18
|
+
readonly xyProvider?: (moreProps: any) => number[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class ClickableCircle extends React.Component<ClickableCircleProps> {
|
|
22
|
+
public static defaultProps = {
|
|
23
|
+
className: "react-financial-charts-interactive-line-edge",
|
|
24
|
+
show: false,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
public render() {
|
|
28
|
+
const { interactiveCursorClass, onDragStart, onDrag, onDragComplete, show } = this.props;
|
|
29
|
+
|
|
30
|
+
if (!show) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<GenericChartComponent
|
|
36
|
+
interactiveCursorClass={interactiveCursorClass}
|
|
37
|
+
selected
|
|
38
|
+
isHover={this.isHover}
|
|
39
|
+
onDragStart={onDragStart}
|
|
40
|
+
onDrag={onDrag}
|
|
41
|
+
onDragComplete={onDragComplete}
|
|
42
|
+
canvasDraw={this.drawOnCanvas}
|
|
43
|
+
canvasToDraw={getMouseCanvas}
|
|
44
|
+
drawOn={["pan", "mousemove", "drag"]}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
|
|
50
|
+
const { strokeStyle, strokeWidth, fillStyle, r } = this.props;
|
|
51
|
+
|
|
52
|
+
ctx.lineWidth = strokeWidth;
|
|
53
|
+
ctx.fillStyle = fillStyle;
|
|
54
|
+
ctx.strokeStyle = strokeStyle;
|
|
55
|
+
|
|
56
|
+
const [x, y] = this.helper(moreProps);
|
|
57
|
+
|
|
58
|
+
ctx.beginPath();
|
|
59
|
+
ctx.arc(x, y, r, 0, 2 * Math.PI, false);
|
|
60
|
+
ctx.fill();
|
|
61
|
+
ctx.stroke();
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
private readonly isHover = (moreProps: any) => {
|
|
65
|
+
const { mouseXY } = moreProps;
|
|
66
|
+
const r = this.props.r + 7;
|
|
67
|
+
const [x, y] = this.helper(moreProps);
|
|
68
|
+
|
|
69
|
+
const [mx, my] = mouseXY;
|
|
70
|
+
const hover = x - r < mx && mx < x + r && y - r < my && my < y + r;
|
|
71
|
+
|
|
72
|
+
return hover;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
private readonly helper = (moreProps: any) => {
|
|
76
|
+
const { xyProvider, cx, cy } = this.props;
|
|
77
|
+
|
|
78
|
+
if (xyProvider !== undefined) {
|
|
79
|
+
return xyProvider(moreProps);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const {
|
|
83
|
+
xScale,
|
|
84
|
+
chartConfig: { yScale },
|
|
85
|
+
} = moreProps;
|
|
86
|
+
|
|
87
|
+
const x = xScale(cx);
|
|
88
|
+
const y = yScale(cy);
|
|
89
|
+
return [x, y];
|
|
90
|
+
};
|
|
91
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { getMouseCanvas, GenericChartComponent } from "@tradingaction/core";
|
|
3
|
+
import { isHovering2 } from "./InteractiveStraightLine";
|
|
4
|
+
|
|
5
|
+
export interface ClickableShapeProps {
|
|
6
|
+
readonly fontWeight: string;
|
|
7
|
+
readonly fontFamily: string;
|
|
8
|
+
readonly fontStyle: string;
|
|
9
|
+
readonly fontSize: number;
|
|
10
|
+
readonly strokeStyle: string;
|
|
11
|
+
readonly strokeWidth: number;
|
|
12
|
+
readonly text: string;
|
|
13
|
+
readonly textBox: {
|
|
14
|
+
readonly closeIcon: any;
|
|
15
|
+
readonly left: number;
|
|
16
|
+
readonly padding: any;
|
|
17
|
+
};
|
|
18
|
+
readonly hovering?: boolean;
|
|
19
|
+
readonly interactiveCursorClass?: string;
|
|
20
|
+
readonly show?: boolean;
|
|
21
|
+
readonly onHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
22
|
+
readonly onUnHover?: (e: React.MouseEvent, moreProps: any) => void;
|
|
23
|
+
readonly onClick?: (e: React.MouseEvent, moreProps: any) => void;
|
|
24
|
+
readonly yValue: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class ClickableShape extends React.Component<ClickableShapeProps> {
|
|
28
|
+
public static defaultProps = {
|
|
29
|
+
show: false,
|
|
30
|
+
strokeWidth: 1,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
private closeIcon: any;
|
|
34
|
+
|
|
35
|
+
public render() {
|
|
36
|
+
const { interactiveCursorClass, onHover, onUnHover, onClick, show } = this.props;
|
|
37
|
+
|
|
38
|
+
if (!show) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<GenericChartComponent
|
|
44
|
+
interactiveCursorClass={interactiveCursorClass}
|
|
45
|
+
isHover={this.isHover}
|
|
46
|
+
onClickWhenHover={onClick}
|
|
47
|
+
canvasDraw={this.drawOnCanvas}
|
|
48
|
+
canvasToDraw={getMouseCanvas}
|
|
49
|
+
onHover={onHover}
|
|
50
|
+
onUnHover={onUnHover}
|
|
51
|
+
drawOn={["pan", "mousemove", "drag"]}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private readonly drawOnCanvas = (ctx: CanvasRenderingContext2D, moreProps: any) => {
|
|
57
|
+
const { strokeStyle, strokeWidth, hovering, textBox } = this.props;
|
|
58
|
+
|
|
59
|
+
const [x, y] = this.helper(this.props, moreProps, ctx);
|
|
60
|
+
|
|
61
|
+
this.closeIcon = { x, y };
|
|
62
|
+
ctx.beginPath();
|
|
63
|
+
|
|
64
|
+
ctx.lineWidth = hovering ? strokeWidth + 1 : strokeWidth;
|
|
65
|
+
ctx.strokeStyle = strokeStyle;
|
|
66
|
+
const halfWidth = textBox.closeIcon.width / 2;
|
|
67
|
+
ctx.moveTo(x - halfWidth, y - halfWidth);
|
|
68
|
+
ctx.lineTo(x + halfWidth, y + halfWidth);
|
|
69
|
+
ctx.moveTo(x - halfWidth, y + halfWidth);
|
|
70
|
+
ctx.lineTo(x + halfWidth, y - halfWidth);
|
|
71
|
+
ctx.stroke();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
private readonly isHover = (moreProps: any) => {
|
|
75
|
+
const { mouseXY } = moreProps;
|
|
76
|
+
if (this.closeIcon) {
|
|
77
|
+
const { textBox } = this.props;
|
|
78
|
+
const { x, y } = this.closeIcon;
|
|
79
|
+
const halfWidth = textBox.closeIcon.width / 2;
|
|
80
|
+
|
|
81
|
+
const start1 = [x - halfWidth, y - halfWidth];
|
|
82
|
+
const end1 = [x + halfWidth, y + halfWidth];
|
|
83
|
+
const start2 = [x - halfWidth, y + halfWidth];
|
|
84
|
+
const end2 = [x + halfWidth, y - halfWidth];
|
|
85
|
+
|
|
86
|
+
if (isHovering2(start1, end1, mouseXY, 3) || isHovering2(start2, end2, mouseXY, 3)) {
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
private readonly helper = (props: ClickableShapeProps, moreProps: any, ctx: CanvasRenderingContext2D) => {
|
|
94
|
+
const { yValue, text, textBox } = props;
|
|
95
|
+
const { fontFamily, fontStyle, fontWeight, fontSize } = props;
|
|
96
|
+
ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`;
|
|
97
|
+
|
|
98
|
+
const {
|
|
99
|
+
chartConfig: { yScale },
|
|
100
|
+
} = moreProps;
|
|
101
|
+
|
|
102
|
+
const x =
|
|
103
|
+
textBox.left +
|
|
104
|
+
textBox.padding.left +
|
|
105
|
+
ctx.measureText(text).width +
|
|
106
|
+
textBox.padding.right +
|
|
107
|
+
textBox.closeIcon.padding.left +
|
|
108
|
+
textBox.closeIcon.width / 2;
|
|
109
|
+
|
|
110
|
+
const y = yScale(yValue);
|
|
111
|
+
|
|
112
|
+
return [x, y];
|
|
113
|
+
};
|
|
114
|
+
}
|