1 | import { jsx } from '../../jsx';
|
2 | import Component from '../../base/component';
|
3 | import { isString, isNil, isFunction } from '@antv/util';
|
4 | import { Ref } from '../../types';
|
5 | import Chart from '../../chart';
|
6 | import { renderShape } from '../../base/diff';
|
7 |
|
8 | function isInBBox(bbox, point) {
|
9 | const { minX, maxX, minY, maxY } = bbox;
|
10 | const { x, y } = point;
|
11 | return minX <= x && maxX >= x && minY <= y && maxY >= y;
|
12 | }
|
13 |
|
14 | export default (View) => {
|
15 | return class Guide extends Component {
|
16 | chart: Chart;
|
17 | triggerRef: Ref;
|
18 |
|
19 | constructor(props) {
|
20 | super(props);
|
21 |
|
22 | this.triggerRef = {};
|
23 | this.state = {};
|
24 | }
|
25 |
|
26 | willMount() {
|
27 | super.willMount();
|
28 | this.getGuideBBox();
|
29 | }
|
30 |
|
31 | didMount() {
|
32 | const { context, props } = this;
|
33 | const { canvas } = context;
|
34 | const { onClick } = props;
|
35 |
|
36 | canvas.on('click', (ev) => {
|
37 | const { points } = ev;
|
38 | const shape = this.triggerRef.current;
|
39 | if (!shape || shape.isDestroyed()) return;
|
40 | const bbox = shape.getBBox();
|
41 | if (isInBBox(bbox, points[0])) {
|
42 | ev.shape = shape;
|
43 | onClick && onClick(ev);
|
44 | }
|
45 | });
|
46 | }
|
47 |
|
48 | didUpdate() {
|
49 | super.didUpdate();
|
50 | const shape = this.triggerRef.current;
|
51 | if (!shape || shape.isDestroyed()) return;
|
52 | const { x, y, width, height } = shape.get('attrs');
|
53 | const bbox = {
|
54 | minX: x,
|
55 | minY: y,
|
56 | maxX: x + width,
|
57 | maxY: y + height,
|
58 | width,
|
59 | height,
|
60 | };
|
61 | this.setState({
|
62 | guideBBox: bbox,
|
63 | });
|
64 | }
|
65 |
|
66 | getGuideBBox() {
|
67 | const shape = renderShape(this, this.render(), false);
|
68 | const { x, y, width, height } = shape.get('attrs');
|
69 |
|
70 | const bbox = {
|
71 | minX: x,
|
72 | minY: y,
|
73 | maxX: x + width,
|
74 | maxY: y + height,
|
75 | width,
|
76 | height,
|
77 | };
|
78 | this.setState({
|
79 | guideBBox: bbox,
|
80 | });
|
81 | shape.destroy();
|
82 | }
|
83 |
|
84 |
|
85 | parseReplaceStr(value, scale) {
|
86 | const replaceMap = {
|
87 | min: 0,
|
88 | max: 1,
|
89 | median: 0.5,
|
90 | };
|
91 |
|
92 |
|
93 | if (!isNil(replaceMap[value])) {
|
94 | return replaceMap[value];
|
95 | }
|
96 |
|
97 |
|
98 | if (isString(value) && value.indexOf('%') != -1 && !isNaN(Number(value.slice(0, -1)))) {
|
99 | const rateValue = Number(value.slice(0, -1));
|
100 | const percent = rateValue / 100;
|
101 | return percent;
|
102 | }
|
103 |
|
104 | return scale.scale(value);
|
105 | }
|
106 |
|
107 | parsePoint(record) {
|
108 | const { props } = this;
|
109 | const { chart, coord } = props;
|
110 | const xScale = chart.getXScales()[0];
|
111 |
|
112 | const yScale = chart.getYScales()[0];
|
113 |
|
114 |
|
115 | const x = this.parseReplaceStr(record[xScale.field], xScale);
|
116 | const y = this.parseReplaceStr(record[yScale.field], yScale);
|
117 |
|
118 | return coord.convertPoint({ x, y });
|
119 | }
|
120 |
|
121 | convertPoints(records) {
|
122 | return records.map((record) => this.parsePoint(record));
|
123 | }
|
124 |
|
125 | getGuideTheme() {
|
126 | const { context } = this;
|
127 | const { theme } = context;
|
128 | return theme.guide;
|
129 | }
|
130 |
|
131 | render() {
|
132 | const { props, context } = this;
|
133 | const { coord, records = [], animation, chart } = props;
|
134 | const { width, height } = context;
|
135 | const points = this.convertPoints(records);
|
136 | const theme = this.getGuideTheme();
|
137 | const { guideBBox } = this.state;
|
138 |
|
139 | let animationCfg = animation;
|
140 | if (isFunction(animation)) {
|
141 |
|
142 | animationCfg = animation(points, chart);
|
143 | }
|
144 |
|
145 | return (
|
146 | <View
|
147 | triggerRef={this.triggerRef}
|
148 | points={points}
|
149 | theme={theme}
|
150 | coord={coord}
|
151 | {...props}
|
152 | canvasWidth={width}
|
153 | canvasHeight={height}
|
154 | guideBBox={guideBBox}
|
155 | animation={animationCfg}
|
156 | />
|
157 | );
|
158 | }
|
159 | };
|
160 | };
|