-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy patharc.ts
More file actions
101 lines (91 loc) · 2.66 KB
/
Copy patharc.ts
File metadata and controls
101 lines (91 loc) · 2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import { Path, deg2rad, BaseStyleProps } from '@antv/g-lite';
import { isNumberEqual, PathArray, isNil } from '@antv/util';
import { polarToCartesian } from './util/util';
export interface ArcStyleProps extends BaseStyleProps {
/**
* @title 起始角度/弧度
*/
startAngle: string | number;
/**
* @title 结束角度/弧度
*/
endAngle: string | number;
/**
* @title 半径
*/
r: string | number;
/**
* @title 圆心 x 坐标
*/
cx?: string | number;
/**
* @title 圆心 y 坐标
*/
cy?: string | number;
/**
* @title 逆时针绘制
*/
anticlockwise?: boolean;
}
function computeArcSweep(startAngle: number, endAngle: number, anticlockwise: boolean) {
// 顺时针方向
if (!anticlockwise) {
if (endAngle >= startAngle) {
return endAngle - startAngle <= Math.PI ? 0 : 1;
}
return endAngle - startAngle <= -Math.PI ? 0 : 1;
}
// 逆时针方向
if (endAngle >= startAngle) {
return endAngle - startAngle <= Math.PI ? 1 : 0;
}
return endAngle - startAngle <= -Math.PI ? 1 : 0;
}
export class Arc extends Path {
parsedStyle: any;
constructor(config) {
super(config);
this.updatePath();
}
setAttribute(name, value, force?: boolean) {
super.setAttribute(name, value, force);
if (['cx', 'cy', 'startAngle', 'endAngle', 'r', 'anticlockwise'].indexOf(name) > -1) {
this.updatePath();
}
}
private updatePath() {
const { cx = 0, cy = 0, startAngle, endAngle, r, anticlockwise } = this.parsedStyle;
if (isNil(startAngle) || isNil(endAngle) || startAngle === endAngle || isNil(r) || r <= 0) {
super.setAttribute('d', '');
return;
}
const path = this.createPath(cx, cy, deg2rad(startAngle), deg2rad(endAngle), r, anticlockwise);
super.setAttribute('d', path);
}
private createPath(
x: number,
y: number,
startAngle: number,
endAngle: number,
r: number,
anticlockwise: boolean,
): PathArray {
const start = polarToCartesian(x, y, r, startAngle);
const end = polarToCartesian(x, y, r, endAngle);
const angle = Math.abs(endAngle - startAngle);
if (angle >= Math.PI * 2 || isNumberEqual(angle, Math.PI * 2)) {
const middlePoint = polarToCartesian(x, y, r, startAngle + Math.PI);
return [
['M', start.x, start.y],
['A', r, r, 0, 1, anticlockwise ? 0 : 1, middlePoint.x, middlePoint.y],
['A', r, r, 0, 1, anticlockwise ? 0 : 1, start.x, start.y],
['Z'],
];
}
const arcSweep = computeArcSweep(startAngle, endAngle, anticlockwise);
return [
['M', start.x, start.y],
['A', r, r, 0, arcSweep, anticlockwise ? 0 : 1, end.x, end.y],
];
}
}