Skip to content

Commit 4a4737d

Browse files
author
xuying.xu
committed
feat: 增加elementLink
1 parent 48b5372 commit 4a4737d

File tree

16 files changed

+506
-19
lines changed

16 files changed

+506
-19
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

@@ -64,7 +65,7 @@ class Chart<
6465

6566
public coordRef: Ref;
6667
constructor(props: IProps, context?: IContext) {
67-
super(props);
68+
super(props, context);
6869

6970
const { theme, px2hd } = context;
7071

@@ -80,6 +81,7 @@ class Chart<
8081
// state
8182
this.state = {
8283
filters: {},
84+
selected: [],
8385
};
8486
}
8587

@@ -111,6 +113,10 @@ class Chart<
111113
coord.create(coordOption);
112114
}
113115

116+
didMount(): void {
117+
super.didMount();
118+
}
119+
114120
// props 更新
115121
willReceiveProps(nextProps: IProps, context) {
116122
const { scale, coord, props: lastProps } = this;
@@ -173,6 +179,7 @@ class Chart<
173179
}
174180

175181
updateCoordFor(component: Component, layout: PositionLayout | PositionLayout[]) {
182+
// console.log('updateCoordFor');
176183
if (!layout) return;
177184
const { componentsPosition } = this;
178185
const componentPosition = { component, layout };
@@ -318,6 +325,7 @@ class Chart<
318325
...filters,
319326
[field]: condition,
320327
},
328+
selected: this.state.selected || [],
321329
});
322330
}
323331

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: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import {
2+
jsx,
3+
Component,
4+
Children,
5+
isEqual,
6+
TextStyleProps,
7+
RectStyleProps,
8+
LineStyleProps,
9+
} from '@antv/f-engine';
10+
import { isArray, flatten, find } from '@antv/util';
11+
import { ChartChildProps } from '../../chart';
12+
import withTooltip from '../tooltip/index';
13+
export interface DataRecord {
14+
origin: any;
15+
[k: string]: any;
16+
}
17+
18+
export interface ElementLinkProps {
19+
[k: string]: any;
20+
}
21+
export interface ElementLinkState {
22+
// records: DataRecord[];
23+
selected: any[];
24+
}
25+
26+
export default (View) => {
27+
return class ElementLink<IProps extends ElementLinkProps & ElementLinkProps> extends Component<
28+
IProps & ChartChildProps,
29+
ElementLinkState
30+
> {
31+
constructor(props: IProps & ChartChildProps) {
32+
super(props);
33+
this.state = {
34+
selected: [],
35+
};
36+
}
37+
38+
// willMount(): void {}
39+
40+
didMount() {
41+
// super.didMount();
42+
}
43+
44+
// willReceiveProps() {}
45+
show(point, _ev?) {
46+
const { props } = this;
47+
const { chart } = props;
48+
const records = chart._getXSnapRecords(point);
49+
const recordsY = chart._getYSnapRecords(point);
50+
console.log(records, recordsY);
51+
if (!records || !records.length) return;
52+
}
53+
findAllShapeNode(vNode, value) {
54+
const { props } = this;
55+
if (!value) return [];
56+
57+
const shapeNodes = [];
58+
Children.map(vNode, (node) => {
59+
if (!node) return;
60+
const { key, children } = node;
61+
if (key === value) {
62+
shapeNodes.push(...children);
63+
}
64+
if (children) {
65+
shapeNodes.push(...this.findAllShapeNode(children, value));
66+
}
67+
});
68+
return shapeNodes;
69+
}
70+
71+
render() {
72+
const { props } = this;
73+
const { chart, field } = props;
74+
const { selected } = chart.state;
75+
const geometry = props.chart.getGeometrys()[0];
76+
console.log(selected);
77+
if (!selected || !selected.length) return null;
78+
const value = selected[0][field];
79+
console.log('value', value);
80+
const elements = this.findAllShapeNode(geometry, value);
81+
82+
const colorController = geometry.getAttr('color');
83+
const color = colorController.mapping(value);
84+
return <View color={color} elements={elements} {...props} />;
85+
}
86+
};
87+
};

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

Lines changed: 16 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
}
@@ -172,6 +175,7 @@ class Geometry<
172175
}
173176

174177
willMount() {
178+
console.log('geo willMount');
175179
this._createAttrs();
176180
if (!this.dataRecords) {
177181
this._processData();
@@ -607,6 +611,9 @@ class Geometry<
607611
return this.getAttr('x').scale;
608612
}
609613

614+
getColorScale(): Scale {
615+
return this.getAttr('color').scale;
616+
}
610617
getYScale(): Scale {
611618
return this.getAttr('y').scale;
612619
}
@@ -772,9 +779,12 @@ class Geometry<
772779
const records = this.flatRecords();
773780
const xScale = this.getXScale();
774781
const yScale = this.getYScale();
782+
const colorScale = this.getColorScale();
775783
const { field: xField } = xScale;
776784
const { field: yField } = yScale;
777-
const value = data[xField];
785+
const { field: colorField } = colorScale;
786+
const fieldValue = field === 'xfield' ? xField : field === 'colorField' ? colorField : yField;
787+
const value = data[fieldValue];
778788
const rst = [];
779789

780790
for (let i = 0, len = records.length; i < len; i++) {
@@ -783,7 +793,7 @@ class Geometry<
783793
xField,
784794
yField,
785795
};
786-
const originValue = record[FIELD_ORIGIN][field === 'xfield' ? xField : yField];
796+
const originValue = record[FIELD_ORIGIN][fieldValue];
787797
if (originValue === value) {
788798
rst.push(record);
789799
}
@@ -821,6 +831,10 @@ class Geometry<
821831
});
822832
return items;
823833
}
834+
835+
getAllElements() {
836+
return this.elements;
837+
}
824838
}
825839

826840
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/guide/withGuide.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export default function<IProps extends GuideProps = GuideProps>(
7777
render() {
7878
const { props, context } = this;
7979
const { coord, records = [], animation, chart, style, onClick, visible = true } = props;
80-
if(!visible) return;
80+
if (!visible) return;
8181
const { width, height } = context;
8282
const points = this.convertPoints(records);
8383
const theme = this.getGuideTheme();

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';

0 commit comments

Comments
 (0)