Skip to content

Commit 2c53bb9

Browse files
author
xuying.xu
committed
feat: 增加elementLink
1 parent ce0c8d7 commit 2c53bb9

File tree

12 files changed

+364
-17
lines changed

12 files changed

+364
-17
lines changed

packages/f2/src/chart/index.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Ref,
1010
createRef,
1111
} from '@antv/f-engine';
12+
import Selection, { SelectionProps, SelectionState } from '../components/geometry/selection';
1213
import { ScaleConfig } from '../deps/f2-scale/src';
1314
import { each, findIndex, isArray, deepMix } from '@antv/util';
1415
import CoordController, { Coord } from '../controller/coord';
@@ -19,7 +20,7 @@ import { CoordType, CoordProps } from './Coord';
1920

2021
export { Point } from './types';
2122

22-
export interface ChartProps<TRecord extends DataRecord = DataRecord> {
23+
export interface ChartProps<TRecord extends DataRecord = DataRecord> extends SelectionProps {
2324
data: Data<TRecord>;
2425
scale?: DataRecordScale<TRecord>;
2526
coord?: CoordType | CoordProps;
@@ -54,7 +55,7 @@ export interface ComponentPosition {
5455
class Chart<
5556
TRecord extends DataRecord = DataRecord,
5657
IProps extends ChartProps<TRecord> = ChartProps<TRecord>
57-
> extends Component<IProps, ChartState> {
58+
> extends Selection<IProps, SelectionState & ChartState> {
5859
// 坐标系
5960
private componentsPosition: ComponentPosition[] = [];
6061

@@ -65,7 +66,7 @@ class Chart<
6566
public adjust: any;
6667
public coordRef: Ref;
6768
constructor(props: IProps, context?: IContext) {
68-
super(props);
69+
super(props, context);
6970

7071
const { theme, px2hd } = context;
7172

@@ -81,6 +82,7 @@ class Chart<
8182
// state
8283
this.state = {
8384
filters: {},
85+
selected: [],
8486
};
8587
}
8688

@@ -112,6 +114,10 @@ class Chart<
112114
coord.create(coordOption);
113115
}
114116

117+
didMount(): void {
118+
super.didMount();
119+
}
120+
115121
// props 更新
116122
willReceiveProps(nextProps: IProps, context) {
117123
const { scale, coord, props: lastProps } = this;
@@ -178,6 +184,7 @@ class Chart<
178184
}
179185

180186
updateCoordFor(component: Component, layout: PositionLayout | PositionLayout[]) {
187+
// console.log('updateCoordFor');
181188
if (!layout) return;
182189
const { componentsPosition } = this;
183190
const componentPosition = { component, layout };
@@ -331,6 +338,7 @@ class Chart<
331338
...filters,
332339
[field]: condition,
333340
},
341+
selected: this.state.selected || [],
334342
});
335343
}
336344

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { jsx } from '@antv/f-engine';
2+
3+
export default (props) => {
4+
const { elements, color } = props;
5+
const topPoints = [];
6+
const bottomPoints = [];
7+
8+
elements.map((d) => {
9+
const { min, max } = d.shape.getBounds();
10+
topPoints.push([min[0], min[1]]);
11+
topPoints.push([max[0], min[1]]);
12+
bottomPoints.push([min[0], max[1]]);
13+
bottomPoints.push([max[0], max[1]]);
14+
});
15+
16+
// 将上边的点和下边的点连接起来,形成一个多边形
17+
const points = [...topPoints, ...bottomPoints.reverse()];
18+
19+
return (
20+
<group>
21+
<polygon
22+
style={{
23+
points,
24+
fill: color,
25+
stroke: 'none',
26+
opacity: 0.4,
27+
}}
28+
/>
29+
</group>
30+
);
31+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import withElementLink, { ElementLinkProps } from './withElementLink';
2+
import elementLinkView from './elementLinkView';
3+
4+
export { ElementLinkProps, withElementLink, elementLinkView };
5+
export default withElementLink(elementLinkView);
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { jsx, Component, Children } from '@antv/f-engine';
2+
import { ChartChildProps } from '../../chart';
3+
export interface DataRecord {
4+
origin: any;
5+
[k: string]: any;
6+
}
7+
8+
export interface ElementLinkProps {
9+
[k: string]: any;
10+
}
11+
export interface ElementLinkState {
12+
// records: DataRecord[];
13+
selected: any[];
14+
}
15+
16+
export default (View) => {
17+
return class ElementLink<IProps extends ElementLinkProps & ElementLinkProps> extends Component<
18+
IProps & ChartChildProps,
19+
ElementLinkState
20+
> {
21+
constructor(props: IProps & ChartChildProps) {
22+
super(props);
23+
this.state = {
24+
selected: [],
25+
};
26+
}
27+
28+
findAllShapeNode(vNode, value) {
29+
if (!value) return [];
30+
31+
const shapeNodes = [];
32+
Children.map(vNode, (node) => {
33+
if (!node) return;
34+
const { key, children } = node;
35+
if (key === value) {
36+
shapeNodes.push(...children);
37+
}
38+
if (children) {
39+
shapeNodes.push(...this.findAllShapeNode(children, value));
40+
}
41+
});
42+
return shapeNodes;
43+
}
44+
45+
render() {
46+
const { props } = this;
47+
const { chart, field } = props;
48+
const { selected } = chart.state;
49+
const geometry = props.chart.getGeometrys()[0];
50+
51+
if (!selected || !selected.length) return null;
52+
const value = selected[0][field];
53+
54+
const elements = this.findAllShapeNode(geometry, value);
55+
56+
const colorController = chart.getColorScales()[0];
57+
const color = colorController.mapping(value);
58+
return <View color={color} elements={elements} {...props} />;
59+
}
60+
};
61+
};

packages/f2/src/components/geometry/selection.ts

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isFunction } from '@antv/util';
22
import { Component, isEqual as equal, ShapeStyleProps } from '@antv/f-engine';
3+
import Chart from '../../chart';
34
import { ChartChildProps } from '../../chart';
45

56
function isEqual(origin1, origin2, fields: string[]) {
@@ -26,6 +27,7 @@ export interface SelectionProps {
2627
unSelectedStyle?: ShapeStyleProps | StyleType;
2728
cancelable?: boolean;
2829
onChange?: Function;
30+
mode: 'element-link' | 'element' | 'point';
2931
};
3032
}
3133

@@ -46,21 +48,47 @@ class Selection<
4648
this.state.selected = defaultSelected;
4749
}
4850

51+
getElementRecord(shape) {
52+
const origin = shape.get('data') || {};
53+
return [
54+
{
55+
origin,
56+
},
57+
];
58+
}
59+
60+
getLinkRecord(shape, chart) {
61+
const origin = shape.get('data') || {};
62+
63+
const records = chart.getRecords(origin, 'colorField');
64+
65+
return records;
66+
}
67+
68+
getSelectRecords(ev, triggerOn, mode: string, chart) {
69+
const { points, canvasX: x, canvasY: y } = ev;
70+
const point = triggerOn === 'click' ? { x, y } : points[0];
71+
if (mode === 'element') return this.getElementRecord(ev.target);
72+
if (mode === 'element-link') return this.getLinkRecord(ev.target, chart);
73+
return this.getSnapRecords(point);
74+
}
75+
4976
didMount() {
5077
const { props, state } = this;
51-
const { selection, chart } = props;
78+
const { selection } = props;
5279
if (!selection) return;
5380
// 默认为 click
54-
const { triggerOn = 'click', onChange } = selection;
81+
const { triggerOn = 'click', onChange, mode } = selection;
82+
// 监听在整个画布上,适用于折线图。
83+
const chart = (props.chart || this) as Chart; // 添加类型断言
5584
chart.on(triggerOn, (ev) => {
56-
const { points, canvasX: x, canvasY: y } = ev;
57-
const point = triggerOn === 'click' ? { x, y } : points[0];
58-
const records = this.getSnapRecords(point);
85+
const records = this.getSelectRecords(ev, triggerOn, mode, chart);
86+
5987
const { type = 'single', cancelable = true } = selection;
6088

6189
if (!records || !records.length) {
6290
if (cancelable) {
63-
onChange && onChange({ selected: null })
91+
onChange && onChange({ selected: null });
6492
this.setState({
6593
selected: null,
6694
} as S);
@@ -71,15 +99,15 @@ class Selection<
7199
const { selected } = state;
72100
const origins = records.map((record) => record.origin);
73101
if (!selected || !selected.length) {
74-
onChange && onChange({ selected: origins })
102+
onChange && onChange({ selected: origins });
75103
this.setState({
76104
selected: origins,
77105
} as S);
78106
}
79107

80108
if (type === 'single') {
81109
if (!cancelable) {
82-
onChange && onChange({ selected: origins })
110+
onChange && onChange({ selected: origins });
83111
this.setState({
84112
selected: origins,
85113
} as S);
@@ -91,7 +119,7 @@ class Selection<
91119
newSelected.push(record.origin);
92120
}
93121
});
94-
onChange && onChange({ selected: newSelected })
122+
onChange && onChange({ selected: newSelected });
95123
this.setState({
96124
selected: newSelected,
97125
} as S);
@@ -116,14 +144,14 @@ class Selection<
116144
.map((key) => selectedMap[key])
117145
.filter(Boolean);
118146

119-
onChange && onChange({ selected: newSelected })
147+
onChange && onChange({ selected: newSelected });
120148
this.setState({
121149
selected: newSelected,
122150
} as S);
123151
});
124152
}
125153

126-
willReceiveProps(nextProps: P): void {
154+
willReceiveProps(nextProps: P, context?): void {
127155
const { selection: nextSelection } = nextProps;
128156
const { selection: lastSelection } = this.props;
129157
if (!nextSelection || !lastSelection) {
@@ -146,7 +174,7 @@ class Selection<
146174
if (!selected || !selected.length) {
147175
return false;
148176
}
149-
const { chart } = props;
177+
const chart = (props.chart || this) as Chart;
150178
const scales = chart.getScales();
151179
const fields = Object.keys(scales);
152180
for (let i = 0, len = selected.length; i < len; i++) {

packages/f2/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ export {
3333
CandlestickView,
3434
} from './candlestick';
3535
export { default as Pictorial, PictorialProps } from './pictorial';
36+
export { default as ElementLink } from './elementLink';

packages/f2/src/components/interval/view/rect.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ export default (props) => {
1414
return (
1515
<group key={key}>
1616
{children.map((item) => {
17-
const { key, xMin, xMax, yMin, yMax, color, shape } = item;
17+
const { key, xMin, xMax, yMin, yMax, color, shape, origin } = item;
1818
if (isNaN(xMin) || isNaN(xMax) || isNaN(yMin) || isNaN(yMax)) {
1919
return null;
2020
}
2121
return (
2222
<rect
2323
key={key}
24+
data={origin}
2425
attrs={{
2526
x: xMin,
2627
y: yMin,

packages/f2/src/components/interval/withInterval.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export default (Views) => {
9898
mix(child, coord.transformToRect(rect));
9999
}
100100

101-
mix(child.shape, this.getSelectionStyle(child));
101+
mix(child.shape, this.props.chart.getSelectionStyle(child));
102102
}
103103
}
104104
return records;
14 KB
Loading
12 KB
Loading

0 commit comments

Comments
 (0)