UNPKG

9.76 kBJavaScriptView Raw
1import { __assign, __extends } from "tslib";
2import { jsx, Component } from '@antv/f-engine';
3import { deepMix, isFunction } from '@antv/util';
4var DEFAULT_CONFIG = {
5 anchorOffset: '10px',
6 inflectionOffset: '30px',
7 sidePadding: '15px',
8 height: '64px',
9 adjustOffset: '30',
10 triggerOn: 'click',
11 // activeShape: false, // 当有图形被选中的时候,是否激活图形
12 // activeStyle: {
13 // offset: '1px',
14 // appendRadius: '8px',
15 // fillOpacity: 0.5,
16 // },
17 label1OffsetY: '-4px',
18 label2OffsetY: '4px'
19};
20function getEndPoint(center, angle, r) {
21 return {
22 x: center.x + r * Math.cos(angle),
23 y: center.y + r * Math.sin(angle)
24 };
25}
26// 计算中间角度
27function getMiddleAngle(startAngle, endAngle) {
28 if (endAngle < startAngle) {
29 endAngle += Math.PI * 2;
30 }
31 return (endAngle + startAngle) / 2;
32}
33function move(from, to, count, center) {
34 var x = center.x;
35 var sort = from.sort(function (a, b) {
36 var aDistance = Math.abs(a.x - x);
37 var bDistance = Math.abs(b.x - x);
38 return bDistance - aDistance;
39 });
40 return [sort.slice(0, sort.length - count), sort.slice(sort.length - count).concat(to)];
41}
42// 第一象限
43function isFirstQuadrant(angle) {
44 return angle >= -Math.PI / 2 && angle < 0;
45}
46// 第二象限
47function isSecondQuadrant(angle) {
48 return angle >= 0 && angle < Math.PI / 2;
49}
50function isThirdQuadrant(angle) {
51 return angle >= Math.PI / 2 && angle < Math.PI;
52}
53function isFourthQuadrant(angle) {
54 return angle >= Math.PI && angle < Math.PI * 3 / 2;
55}
56export default (function (View) {
57 return /** @class */function (_super) {
58 __extends(PieLabel, _super);
59 function PieLabel(props) {
60 return _super.call(this, props) || this;
61 }
62 PieLabel.prototype.willMount = function () {};
63 /**
64 * 绑定事件
65 */
66 PieLabel.prototype.didMount = function () {};
67 PieLabel.prototype.getLabels = function (props) {
68 var chart = props.chart,
69 coord = props.coord,
70 anchorOffset = props.anchorOffset,
71 inflectionOffset = props.inflectionOffset,
72 label1 = props.label1,
73 label2 = props.label2,
74 itemHeight = props.height,
75 sidePadding = props.sidePadding;
76 var center = coord.center,
77 radius = coord.radius,
78 coordWidth = coord.width,
79 coordHeight = coord.height,
80 coordLeft = coord.left,
81 coordRight = coord.right,
82 coordTop = coord.top;
83 var maxCountForOneSide = Math.floor(coordHeight / itemHeight);
84 var maxCount = maxCountForOneSide * 2;
85 var geometry = chart.getGeometrys()[0];
86 var records = geometry.flatRecords()
87 // 按角度大到小排序
88 .sort(function (a, b) {
89 var angle1 = a.xMax - a.xMin;
90 var angle2 = b.xMax - b.xMin;
91 return angle2 - angle1;
92 })
93 // 只取前 maxCount 个显示
94 .slice(0, maxCount);
95 // 存储左右 labels
96 var halves = [[], [] // right
97 ];
98
99 records.forEach(function (record) {
100 var xMin = record.xMin,
101 xMax = record.xMax,
102 color = record.color,
103 origin = record.origin;
104 // 锚点角度
105 var anchorAngle = getMiddleAngle(xMin, xMax);
106 // 锚点坐标
107 var anchorPoint = getEndPoint(center, anchorAngle, radius + anchorOffset);
108 // 拐点坐标
109 var inflectionPoint = getEndPoint(center, anchorAngle, radius + inflectionOffset);
110 // 锚点方向
111 var side = anchorPoint.x < center.x ? 'left' : 'right';
112 var label = {
113 origin: origin,
114 angle: anchorAngle,
115 anchor: anchorPoint,
116 inflection: inflectionPoint,
117 side: side,
118 x: inflectionPoint.x,
119 y: inflectionPoint.y,
120 r: radius + inflectionOffset,
121 color: color,
122 label1: isFunction(label1) ? label1(origin, record) : label1,
123 label2: isFunction(label2) ? label2(origin, record) : label2
124 };
125 // 判断文本的方向
126 if (side === 'left') {
127 halves[0].push(label);
128 } else {
129 halves[1].push(label);
130 }
131 });
132 // 判断是有一边超过了显示的最大
133 if (halves[0].length > maxCountForOneSide) {
134 halves = move(halves[0], halves[1], halves[0].length - maxCountForOneSide, center);
135 } else if (halves[1].length > maxCountForOneSide) {
136 var _a = move(halves[1], halves[0], halves[1].length - maxCountForOneSide, center),
137 right = _a[0],
138 left = _a[1];
139 halves = [left, right];
140 }
141 // label 的最大宽度
142 var labelWidth = coordWidth / 2 - radius - anchorOffset - inflectionOffset - 2 * sidePadding;
143 var labels = [];
144 halves.forEach(function (half, index) {
145 var showSide = index === 0 ? 'left' : 'right';
146 // 顺时针方向排序
147 half.sort(function (a, b) {
148 var aAngle = a.angle;
149 var bAngle = b.angle;
150 if (showSide === 'left') {
151 // 是否在第一象限
152 aAngle = isFirstQuadrant(aAngle) ? aAngle + Math.PI * 2 : aAngle;
153 bAngle = isFirstQuadrant(bAngle) ? bAngle + Math.PI * 2 : bAngle;
154 return bAngle - aAngle;
155 } else {
156 // 是否在第四象限
157 aAngle = isFourthQuadrant(aAngle) ? aAngle - Math.PI * 2 : aAngle;
158 bAngle = isFourthQuadrant(bAngle) ? bAngle - Math.PI * 2 : bAngle;
159 return aAngle - bAngle;
160 }
161 });
162 var pointsY = half.map(function (label) {
163 return label.y;
164 });
165 var maxY = Math.max.apply(null, pointsY);
166 var minY = Math.min.apply(null, pointsY);
167 // 每个 label 占用的高度
168 var labelCount = half.length;
169 var labelHeight = coordHeight / labelCount;
170 var halfLabelHeight = labelHeight / 2;
171 // 线之间的间隔
172 var lineInterval = 2;
173 if (showSide === 'left') {
174 half.forEach(function (label, index) {
175 var anchor = label.anchor,
176 inflection = label.inflection,
177 angle = label.angle,
178 x = label.x,
179 y = label.y;
180 var points = [anchor, inflection];
181 var endX = coordLeft + sidePadding;
182 var endY = coordTop + halfLabelHeight + labelHeight * index;
183 // 文本开始点
184 var labelStart = {
185 x: endX + labelWidth + lineInterval * index,
186 y: endY
187 };
188 // 文本结束点
189 var labelEnd = {
190 x: endX,
191 y: endY
192 };
193 // 第四象限
194 if (isFirstQuadrant(angle)) {
195 var pointY = minY - lineInterval * (labelCount - index);
196 points.push({
197 x: x,
198 y: pointY
199 });
200 points.push({
201 x: labelStart.x,
202 y: pointY
203 });
204 } else if (isThirdQuadrant(angle) || isFourthQuadrant(angle)) {
205 points.push({
206 x: labelStart.x,
207 y: y
208 });
209 } else if (isSecondQuadrant(angle)) {
210 var pointY = maxY + lineInterval * index;
211 points.push({
212 x: x,
213 y: pointY
214 });
215 points.push({
216 x: labelStart.x,
217 y: pointY
218 });
219 }
220 points.push(labelStart);
221 points.push(labelEnd);
222 label.points = points;
223 label.side = showSide;
224 labels.push(label);
225 });
226 } else {
227 half.forEach(function (label, index) {
228 var anchor = label.anchor,
229 inflection = label.inflection,
230 angle = label.angle,
231 x = label.x,
232 y = label.y;
233 // 折线的点
234 var points = [anchor, inflection];
235 var endX = coordRight - sidePadding;
236 var endY = coordTop + halfLabelHeight + labelHeight * index;
237 // 文本开始点
238 var labelStart = {
239 x: endX - labelWidth - lineInterval * index,
240 y: endY
241 };
242 // 文本结束点
243 var labelEnd = {
244 x: endX,
245 y: endY
246 };
247 // 第四象限
248 if (isFourthQuadrant(angle)) {
249 var pointY = minY - lineInterval * (labelCount - index);
250 points.push({
251 x: x,
252 y: pointY
253 });
254 points.push({
255 x: labelStart.x,
256 y: pointY
257 });
258 } else if (isFirstQuadrant(angle) || isSecondQuadrant(angle)) {
259 points.push({
260 x: labelStart.x,
261 y: y
262 });
263 } else if (isThirdQuadrant(angle)) {
264 var pointY = maxY + lineInterval * index;
265 points.push({
266 x: x,
267 y: pointY
268 });
269 points.push({
270 x: labelStart.x,
271 y: pointY
272 });
273 }
274 points.push(labelStart);
275 points.push(labelEnd);
276 label.points = points;
277 label.side = showSide;
278 labels.push(label);
279 });
280 }
281 });
282 return labels;
283 };
284 PieLabel.prototype.render = function () {
285 var context = this.context;
286 var props = context.px2hd(deepMix({}, DEFAULT_CONFIG, this.props));
287 var labels = this.getLabels(props);
288 return jsx(View, __assign({
289 labels: labels
290 }, props));
291 };
292 return PieLabel;
293 }(Component);
294});
\No newline at end of file