Skip to content

Commit 91f4422

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

File tree

14 files changed

+378
-18
lines changed

14 files changed

+378
-18
lines changed

packages/f2/src/chart/index.tsx

Lines changed: 10 additions & 2 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';
@@ -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 & SelectionProps, 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

packages/f2/src/components/axis/withAxis.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export default (View) => {
4848
}
4949

5050
willMount() {
51+
console.log('axis willMount');
5152
this.updateCoord();
5253
}
5354

@@ -282,6 +283,7 @@ export default (View) => {
282283

283284
const ticks = this.getTicks();
284285
const position = this._getPosition();
286+
// console.log('axis position', position, props.chart.scale);
285287
const dimType = this._getDimType();
286288

287289
return (
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 = geometry.getAttr('color');
57+
const color = colorController.mapping(value);
58+
return <View color={color} elements={elements} {...props} />;
59+
}
60+
};
61+
};

packages/f2/src/components/geometry/index.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ class Geometry<
108108
// 动画配置
109109
animation: AnimationProps;
110110

111+
// 主图形元素
112+
elements: any[];
113+
111114
getDefaultCfg() {
112115
return {};
113116
}
@@ -173,6 +176,7 @@ class Geometry<
173176
}
174177

175178
willMount() {
179+
console.log('geo willMount');
176180
this._createAttrs();
177181
if (!this.dataRecords) {
178182
this._processData();
@@ -778,9 +782,12 @@ class Geometry<
778782
const records = this.flatRecords();
779783
const xScale = this.getXScale();
780784
const yScale = this.getYScale();
785+
const colorScale = this.getColorScale();
781786
const { field: xField } = xScale;
782787
const { field: yField } = yScale;
783-
const value = data[xField];
788+
const { field: colorField } = colorScale;
789+
const fieldValue = field === 'xfield' ? xField : field === 'colorField' ? colorField : yField;
790+
const value = data[fieldValue];
784791
const rst = [];
785792

786793
for (let i = 0, len = records.length; i < len; i++) {
@@ -789,7 +796,7 @@ class Geometry<
789796
xField,
790797
yField,
791798
};
792-
const originValue = record[FIELD_ORIGIN][field === 'xfield' ? xField : yField];
799+
const originValue = record[FIELD_ORIGIN][fieldValue];
793800
if (originValue === value) {
794801
rst.push(record);
795802
}
@@ -827,6 +834,10 @@ class Geometry<
827834
});
828835
return items;
829836
}
837+
838+
getAllElements() {
839+
return this.elements;
840+
}
830841
}
831842

832843
export default Geometry;

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

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

55
function isEqual(origin1, origin2, fields: string[]) {
66
if (origin1 === origin2) {
@@ -26,6 +26,7 @@ export interface SelectionProps {
2626
unSelectedStyle?: ShapeStyleProps | StyleType;
2727
cancelable?: boolean;
2828
onChange?: Function;
29+
mode: 'element-link' | 'element' | 'point';
2930
};
3031
}
3132

@@ -46,21 +47,47 @@ class Selection<
4647
this.state.selected = defaultSelected;
4748
}
4849

50+
getElementRecord(shape) {
51+
const origin = shape.get('data') || {};
52+
return [
53+
{
54+
origin,
55+
},
56+
];
57+
}
58+
59+
getLinkRecord(shape, chart) {
60+
const origin = shape.get('data') || {};
61+
62+
const records = chart.getRecords(origin, 'colorField');
63+
64+
return records;
65+
}
66+
67+
getSelectRecords(ev, triggerOn, mode: string, chart) {
68+
const { points, canvasX: x, canvasY: y } = ev;
69+
const point = triggerOn === 'click' ? { x, y } : points[0];
70+
if (mode === 'element') return this.getElementRecord(ev.target);
71+
if (mode === 'element-link') return this.getLinkRecord(ev.target, chart);
72+
return this.getSnapRecords(point);
73+
}
74+
4975
didMount() {
5076
const { props, state } = this;
51-
const { selection, chart } = props;
77+
const { selection } = props;
5278
if (!selection) return;
5379
// 默认为 click
54-
const { triggerOn = 'click', onChange } = selection;
80+
const { triggerOn = 'click', onChange, mode } = selection;
81+
// 监听在整个画布上,适用于折线图。
82+
const chart = props.chart || (this as Chart);
5583
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);
84+
const records = this.getSelectRecords(ev, triggerOn, mode, chart);
85+
5986
const { type = 'single', cancelable = true } = selection;
6087

6188
if (!records || !records.length) {
6289
if (cancelable) {
63-
onChange && onChange({ selected: null })
90+
onChange && onChange({ selected: null });
6491
this.setState({
6592
selected: null,
6693
} as S);
@@ -71,15 +98,15 @@ class Selection<
7198
const { selected } = state;
7299
const origins = records.map((record) => record.origin);
73100
if (!selected || !selected.length) {
74-
onChange && onChange({ selected: origins })
101+
onChange && onChange({ selected: origins });
75102
this.setState({
76103
selected: origins,
77104
} as S);
78105
}
79106

80107
if (type === 'single') {
81108
if (!cancelable) {
82-
onChange && onChange({ selected: origins })
109+
onChange && onChange({ selected: origins });
83110
this.setState({
84111
selected: origins,
85112
} as S);
@@ -91,7 +118,7 @@ class Selection<
91118
newSelected.push(record.origin);
92119
}
93120
});
94-
onChange && onChange({ selected: newSelected })
121+
onChange && onChange({ selected: newSelected });
95122
this.setState({
96123
selected: newSelected,
97124
} as S);
@@ -116,7 +143,7 @@ class Selection<
116143
.map((key) => selectedMap[key])
117144
.filter(Boolean);
118145

119-
onChange && onChange({ selected: newSelected })
146+
onChange && onChange({ selected: newSelected });
120147
this.setState({
121148
selected: newSelected,
122149
} as S);
@@ -146,7 +173,7 @@ class Selection<
146173
if (!selected || !selected.length) {
147174
return false;
148175
}
149-
const { chart } = props;
176+
const chart = props.chart || (this as Chart);
150177
const scales = chart.getScales();
151178
const fields = Object.keys(scales);
152179
for (let i = 0, len = selected.length; i < len; i++) {

packages/f2/src/components/index.ts

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

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;

0 commit comments

Comments
 (0)