UNPKG

4.11 kBTypeScriptView Raw
1import { deepMix, isArray } from '@antv/util';
2import { jsx } from '../../jsx';
3import { LineViewProps } from './types';
4
5function concatPoints(children) {
6 let result = [];
7 for (let i = 0; i < children.length; i++) {
8 const child = children[i];
9 result = result.concat(child.points);
10 }
11 return result;
12}
13
14function formatPoint(point) {
15 const { y } = point;
16 return {
17 x: point.x,
18 y: isArray(y) ? y[1] : y,
19 };
20}
21
22function getPoint(points, t: number) {
23 const formatedPoints = points.map((p) => formatPoint(p));
24 const firstPoint = formatedPoints[0];
25 const lastPoint = formatedPoints[formatedPoints.length - 1];
26 const xOffset = lastPoint.x - firstPoint.x;
27 const x = firstPoint.x + xOffset * t;
28
29 for (let i = 1; i < formatedPoints.length; i++) {
30 const point = formatedPoints[i];
31 const prevPoint = formatedPoints[i - 1];
32 if (x >= prevPoint.x && x <= point.x) {
33 // x 在 2 点之间的比例,根据比例再算出 y 的值
34 const ratio = (x - prevPoint.x) / (point.x - prevPoint.x);
35 return {
36 x,
37 y: prevPoint.y + (point.y - prevPoint.y) * ratio,
38 };
39 }
40 }
41}
42
43function AnimationEndView(props) {
44 const { record, appear, EndView } = props;
45 const { children } = record;
46 const points = concatPoints(children);
47 const { origin } = points[0];
48
49 return (
50 <group
51 animation={{
52 appear: {
53 easing: appear.easing,
54 duration: appear.duration,
55 onFrame: function(t) {
56 // 这段逻辑有点恶心。。
57 const { element } = this;
58 const children = element.get('children');
59 const point = getPoint(points, t);
60 children.forEach((child) => {
61 child.moveTo(point.x, point.y);
62 });
63 },
64 },
65 }}
66 >
67 <EndView origin={origin} />
68 </group>
69 );
70}
71
72export default (props: LineViewProps) => {
73 const { records, coord, animation, endView: EndView, clip } = props;
74
75 const { left, top, width, height, center, startAngle, endAngle, radius } = coord as any;
76
77 const appear = coord.isPolar
78 ? {
79 easing: 'quadraticOut',
80 duration: 450,
81 clip: {
82 type: 'sector',
83 property: ['endAngle'],
84 attrs: {
85 x: center.x,
86 y: center.y,
87 startAngle,
88 r: radius,
89 },
90 start: {
91 endAngle: startAngle,
92 },
93 end: {
94 endAngle,
95 },
96 },
97 }
98 : {
99 easing: 'quadraticOut',
100 duration: 450,
101 clip: {
102 type: 'rect',
103 property: ['width'],
104 attrs: {
105 x: left,
106 y: top,
107 height: height,
108 },
109 start: {
110 width: 0,
111 },
112 end: {
113 width: width,
114 },
115 },
116 };
117 return (
118 <group
119 attrs={{
120 clip,
121 }}
122 >
123 {records.map((record) => {
124 const { key, children } = record;
125 return (
126 <group key={key}>
127 {children.map((child) => {
128 const { points, color, size, shape } = child;
129 return (
130 <polyline
131 attrs={{
132 points: points.map((point) => {
133 return { x: point.x, y: point.y };
134 }),
135 stroke: color,
136 ...shape,
137 lineWidth: size || shape.lineWidth,
138 }}
139 animation={deepMix(
140 {
141 update: {
142 easing: 'linear',
143 duration: 450,
144 property: ['points'],
145 },
146 appear,
147 },
148 animation
149 )}
150 />
151 );
152 })}
153 {EndView ? (
154 <AnimationEndView record={record} EndView={EndView} appear={appear} />
155 ) : null}
156 </group>
157 );
158 })}
159 </group>
160 );
161};