UNPKG

9.75 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 records.forEach(function (record) {
99 var xMin = record.xMin,
100 xMax = record.xMax,
101 color = record.color,
102 origin = record.origin;
103 // 锚点角度
104 var anchorAngle = getMiddleAngle(xMin, xMax);
105 // 锚点坐标
106 var anchorPoint = getEndPoint(center, anchorAngle, radius + anchorOffset);
107 // 拐点坐标
108 var inflectionPoint = getEndPoint(center, anchorAngle, radius + inflectionOffset);
109 // 锚点方向
110 var side = anchorPoint.x < center.x ? 'left' : 'right';
111 var label = {
112 origin: origin,
113 angle: anchorAngle,
114 anchor: anchorPoint,
115 inflection: inflectionPoint,
116 side: side,
117 x: inflectionPoint.x,
118 y: inflectionPoint.y,
119 r: radius + inflectionOffset,
120 color: color,
121 label1: isFunction(label1) ? label1(origin, record) : label1,
122 label2: isFunction(label2) ? label2(origin, record) : label2
123 };
124 // 判断文本的方向
125 if (side === 'left') {
126 halves[0].push(label);
127 } else {
128 halves[1].push(label);
129 }
130 });
131 // 判断是有一边超过了显示的最大
132 if (halves[0].length > maxCountForOneSide) {
133 halves = move(halves[0], halves[1], halves[0].length - maxCountForOneSide, center);
134 } else if (halves[1].length > maxCountForOneSide) {
135 var _a = move(halves[1], halves[0], halves[1].length - maxCountForOneSide, center),
136 right = _a[0],
137 left = _a[1];
138 halves = [left, right];
139 }
140 // label 的最大宽度
141 var labelWidth = coordWidth / 2 - radius - anchorOffset - inflectionOffset - 2 * sidePadding;
142 var labels = [];
143 halves.forEach(function (half, index) {
144 var showSide = index === 0 ? 'left' : 'right';
145 // 顺时针方向排序
146 half.sort(function (a, b) {
147 var aAngle = a.angle;
148 var bAngle = b.angle;
149 if (showSide === 'left') {
150 // 是否在第一象限
151 aAngle = isFirstQuadrant(aAngle) ? aAngle + Math.PI * 2 : aAngle;
152 bAngle = isFirstQuadrant(bAngle) ? bAngle + Math.PI * 2 : bAngle;
153 return bAngle - aAngle;
154 } else {
155 // 是否在第四象限
156 aAngle = isFourthQuadrant(aAngle) ? aAngle - Math.PI * 2 : aAngle;
157 bAngle = isFourthQuadrant(bAngle) ? bAngle - Math.PI * 2 : bAngle;
158 return aAngle - bAngle;
159 }
160 });
161 var pointsY = half.map(function (label) {
162 return label.y;
163 });
164 var maxY = Math.max.apply(null, pointsY);
165 var minY = Math.min.apply(null, pointsY);
166 // 每个 label 占用的高度
167 var labelCount = half.length;
168 var labelHeight = coordHeight / labelCount;
169 var halfLabelHeight = labelHeight / 2;
170 // 线之间的间隔
171 var lineInterval = 2;
172 if (showSide === 'left') {
173 half.forEach(function (label, index) {
174 var anchor = label.anchor,
175 inflection = label.inflection,
176 angle = label.angle,
177 x = label.x,
178 y = label.y;
179 var points = [anchor, inflection];
180 var endX = coordLeft + sidePadding;
181 var endY = coordTop + halfLabelHeight + labelHeight * index;
182 // 文本开始点
183 var labelStart = {
184 x: endX + labelWidth + lineInterval * index,
185 y: endY
186 };
187 // 文本结束点
188 var labelEnd = {
189 x: endX,
190 y: endY
191 };
192 // 第四象限
193 if (isFirstQuadrant(angle)) {
194 var pointY = minY - lineInterval * (labelCount - index);
195 points.push({
196 x: x,
197 y: pointY
198 });
199 points.push({
200 x: labelStart.x,
201 y: pointY
202 });
203 } else if (isThirdQuadrant(angle) || isFourthQuadrant(angle)) {
204 points.push({
205 x: labelStart.x,
206 y: y
207 });
208 } else if (isSecondQuadrant(angle)) {
209 var pointY = maxY + lineInterval * index;
210 points.push({
211 x: x,
212 y: pointY
213 });
214 points.push({
215 x: labelStart.x,
216 y: pointY
217 });
218 }
219 points.push(labelStart);
220 points.push(labelEnd);
221 label.points = points;
222 label.side = showSide;
223 labels.push(label);
224 });
225 } else {
226 half.forEach(function (label, index) {
227 var anchor = label.anchor,
228 inflection = label.inflection,
229 angle = label.angle,
230 x = label.x,
231 y = label.y;
232 // 折线的点
233 var points = [anchor, inflection];
234 var endX = coordRight - sidePadding;
235 var endY = coordTop + halfLabelHeight + labelHeight * index;
236 // 文本开始点
237 var labelStart = {
238 x: endX - labelWidth - lineInterval * index,
239 y: endY
240 };
241 // 文本结束点
242 var labelEnd = {
243 x: endX,
244 y: endY
245 };
246 // 第四象限
247 if (isFourthQuadrant(angle)) {
248 var pointY = minY - lineInterval * (labelCount - index);
249 points.push({
250 x: x,
251 y: pointY
252 });
253 points.push({
254 x: labelStart.x,
255 y: pointY
256 });
257 } else if (isFirstQuadrant(angle) || isSecondQuadrant(angle)) {
258 points.push({
259 x: labelStart.x,
260 y: y
261 });
262 } else if (isThirdQuadrant(angle)) {
263 var pointY = maxY + lineInterval * index;
264 points.push({
265 x: x,
266 y: pointY
267 });
268 points.push({
269 x: labelStart.x,
270 y: pointY
271 });
272 }
273 points.push(labelStart);
274 points.push(labelEnd);
275 label.points = points;
276 label.side = showSide;
277 labels.push(label);
278 });
279 }
280 });
281 return labels;
282 };
283 PieLabel.prototype.render = function () {
284 var context = this.context;
285 var props = context.px2hd(deepMix({}, DEFAULT_CONFIG, this.props));
286 var labels = this.getLabels(props);
287 return jsx(View, __assign({
288 labels: labels
289 }, props));
290 };
291 return PieLabel;
292 }(Component);
293});
\No newline at end of file