UNPKG

12 kBJavaScriptView Raw
1import { __assign, __rest } from "tslib";
2import { deepMix, each, get, isArray, isNull } from '@antv/util';
3import { doAnimate } from '../animate';
4import { getGeometryLabelLayout } from '../geometry/label';
5import { getlLabelBackgroundInfo } from '../geometry/label/util';
6import { polarToCartesian } from '../util/graphics';
7import { rotate, translate } from '../util/transform';
8import { FIELD_ORIGIN } from '../constant';
9import { updateLabel } from './update-label';
10/**
11 * Geometry labels 渲染组件
12 */
13var Labels = /** @class */ (function () {
14 function Labels(cfg) {
15 /** 存储当前 shape 的映射表,键值为 shape id */
16 this.shapesMap = {};
17 this.lastShapesMap = {};
18 var layout = cfg.layout, container = cfg.container;
19 this.layout = layout;
20 this.container = container;
21 }
22 /**
23 * 渲染文本
24 */
25 Labels.prototype.render = function (items, shapes, isUpdate) {
26 var _this = this;
27 if (isUpdate === void 0) { isUpdate = false; }
28 this.shapesMap = {};
29 var container = this.container;
30 var offscreenGroup = this.createOffscreenGroup(); // 创建虚拟分组
31 if (items.length) {
32 // 如果 items 空的话就不进行绘制调整操作
33 // step 1: 在虚拟 group 中创建 shapes
34 for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
35 var item = items_1[_i];
36 if (item) {
37 this.renderLabel(item, offscreenGroup);
38 }
39 }
40 // step 2: 根据布局,调整 labels
41 this.doLayout(items, shapes);
42 // step 3.1: 绘制 labelLine
43 this.renderLabelLine(items);
44 // step 3.2: 绘制 labelBackground
45 this.renderLabelBackground(items);
46 // step 4: 根据用户设置的偏移量调整 label
47 this.adjustLabel(items);
48 }
49 // 进行添加、更新、销毁操作
50 var lastShapesMap = this.lastShapesMap;
51 var shapesMap = this.shapesMap;
52 each(shapesMap, function (shape, id) {
53 if (shape.destroyed) {
54 // label 在布局调整环节被删除了(doLayout)
55 delete shapesMap[id];
56 }
57 else {
58 if (lastShapesMap[id]) {
59 // 图形发生更新
60 var data = shape.get('data');
61 var origin_1 = shape.get('origin');
62 var coordinate = shape.get('coordinate');
63 var currentAnimateCfg = shape.get('animateCfg');
64 var currentShape = lastShapesMap[id]; // 已经在渲染树上的 shape
65 updateLabel(currentShape, shapesMap[id], {
66 data: data,
67 origin: origin_1,
68 animateCfg: currentAnimateCfg,
69 coordinate: coordinate,
70 });
71 _this.shapesMap[id] = currentShape; // 保存引用
72 }
73 else {
74 // 新生成的 shape
75 container.add(shape);
76 var animateCfg = get(shape.get('animateCfg'), isUpdate ? 'enter' : 'appear');
77 if (animateCfg) {
78 doAnimate(shape, animateCfg, {
79 toAttrs: __assign({}, shape.attr()),
80 coordinate: shape.get('coordinate'),
81 });
82 }
83 }
84 delete lastShapesMap[id];
85 }
86 });
87 // 移除
88 each(lastShapesMap, function (deleteShape) {
89 var animateCfg = get(deleteShape.get('animateCfg'), 'leave');
90 if (animateCfg) {
91 doAnimate(deleteShape, animateCfg, {
92 toAttrs: null,
93 coordinate: deleteShape.get('coordinate'),
94 });
95 }
96 else {
97 deleteShape.remove(true); // 移除
98 }
99 });
100 this.lastShapesMap = shapesMap;
101 offscreenGroup.destroy();
102 };
103 /** 清除当前 labels */
104 Labels.prototype.clear = function () {
105 this.container.clear();
106 this.shapesMap = {};
107 this.lastShapesMap = {};
108 };
109 /** 销毁 */
110 Labels.prototype.destroy = function () {
111 this.container.destroy();
112 this.shapesMap = null;
113 this.lastShapesMap = null;
114 };
115 Labels.prototype.renderLabel = function (cfg, container) {
116 var id = cfg.id, elementId = cfg.elementId, data = cfg.data, mappingData = cfg.mappingData, coordinate = cfg.coordinate, animate = cfg.animate, content = cfg.content;
117 var shapeAppendCfg = {
118 id: id,
119 elementId: elementId,
120 data: data,
121 origin: __assign(__assign({}, mappingData), { data: mappingData[FIELD_ORIGIN] }),
122 coordinate: coordinate,
123 };
124 var labelGroup = container.addGroup(__assign({ name: 'label',
125 // 如果 this.animate === false 或者 cfg.animate === false/null 则不进行动画,否则进行动画配置的合并
126 animateCfg: this.animate === false || animate === null || animate === false ? false : deepMix({}, this.animate, animate) }, shapeAppendCfg));
127 var labelShape;
128 if ((content.isGroup && content.isGroup()) || (content.isShape && content.isShape())) {
129 // 如果 content 是 Group 或者 Shape,根据 textAlign 调整位置后,直接将其加入 labelGroup
130 var _a = content.getCanvasBBox(), width = _a.width, height = _a.height;
131 var textAlign = get(cfg, 'textAlign', 'left');
132 var x = cfg.x;
133 var y = cfg.y - height / 2;
134 if (textAlign === 'center') {
135 x = x - width / 2;
136 }
137 else if (textAlign === 'right' || textAlign === 'end') {
138 x = x - width;
139 }
140 translate(content, x, y); // 将 label 平移至 x, y 指定的位置
141 labelShape = content;
142 labelGroup.add(content);
143 }
144 else {
145 var fill = get(cfg, ['style', 'fill']);
146 labelShape = labelGroup.addShape('text', __assign({ attrs: __assign(__assign({ x: cfg.x, y: cfg.y, textAlign: cfg.textAlign, textBaseline: get(cfg, 'textBaseline', 'middle'), text: cfg.content }, cfg.style), { fill: isNull(fill) ? cfg.color : fill }) }, shapeAppendCfg));
147 }
148 if (cfg.rotate) {
149 rotate(labelShape, cfg.rotate);
150 }
151 this.shapesMap[id] = labelGroup;
152 };
153 // 根据type对label布局
154 Labels.prototype.doLayout = function (items, shapes) {
155 var _this = this;
156 if (this.layout) {
157 var layouts = isArray(this.layout) ? this.layout : [this.layout];
158 each(layouts, function (layout) {
159 var layoutFn = getGeometryLabelLayout(get(layout, 'type', ''));
160 if (layoutFn) {
161 var labelShapes_1 = [];
162 var geometryShapes_1 = [];
163 each(_this.shapesMap, function (labelShape, id) {
164 labelShapes_1.push(labelShape);
165 geometryShapes_1.push(shapes[labelShape.get('elementId')]);
166 });
167 layoutFn(items, labelShapes_1, geometryShapes_1, _this.region, layout.cfg);
168 }
169 });
170 }
171 };
172 Labels.prototype.renderLabelLine = function (labelItems) {
173 var _this = this;
174 each(labelItems, function (labelItem) {
175 var coordinate = get(labelItem, 'coordinate');
176 if (!labelItem || !coordinate) {
177 return;
178 }
179 var center = coordinate.getCenter();
180 var radius = coordinate.getRadius();
181 if (!labelItem.labelLine) {
182 // labelLine: null | false,关闭 label 对应的 labelLine
183 return;
184 }
185 var labelLineCfg = get(labelItem, 'labelLine', {});
186 var id = labelItem.id;
187 var path = labelLineCfg.path;
188 if (!path) {
189 var start = polarToCartesian(center.x, center.y, radius, labelItem.angle);
190 path = [
191 ['M', start.x, start.y],
192 ['L', labelItem.x, labelItem.y],
193 ];
194 }
195 var labelGroup = _this.shapesMap[id];
196 if (!labelGroup.destroyed) {
197 labelGroup.addShape('path', {
198 capture: false,
199 attrs: __assign({ path: path, stroke: labelItem.color ? labelItem.color : get(labelItem, ['style', 'fill'], '#000'), fill: null }, labelLineCfg.style),
200 id: id,
201 origin: labelItem.mappingData,
202 data: labelItem.data,
203 coordinate: labelItem.coordinate,
204 });
205 }
206 });
207 };
208 /**
209 * 绘制标签背景
210 * @param labelItems
211 */
212 Labels.prototype.renderLabelBackground = function (labelItems) {
213 var _this = this;
214 each(labelItems, function (labelItem) {
215 var coordinate = get(labelItem, 'coordinate');
216 var background = get(labelItem, 'background');
217 if (!background || !coordinate) {
218 return;
219 }
220 var id = labelItem.id;
221 var labelGroup = _this.shapesMap[id];
222 if (!labelGroup.destroyed) {
223 var labelContentShape = labelGroup.getChildren()[0];
224 if (labelContentShape) {
225 var _a = getlLabelBackgroundInfo(labelGroup, labelItem, background.padding), rotation = _a.rotation, box = __rest(_a, ["rotation"]);
226 var backgroundShape = labelGroup.addShape('rect', {
227 attrs: __assign(__assign({}, box), (background.style || {})),
228 id: id,
229 origin: labelItem.mappingData,
230 data: labelItem.data,
231 coordinate: labelItem.coordinate,
232 });
233 backgroundShape.setZIndex(-1);
234 if (rotation) {
235 var matrix = labelContentShape.getMatrix();
236 backgroundShape.setMatrix(matrix);
237 }
238 }
239 }
240 });
241 };
242 Labels.prototype.createOffscreenGroup = function () {
243 var container = this.container;
244 var GroupClass = container.getGroupBase(); // 获取分组的构造函数
245 var newGroup = new GroupClass({});
246 return newGroup;
247 };
248 Labels.prototype.adjustLabel = function (items) {
249 var _this = this;
250 each(items, function (item) {
251 if (item) {
252 var id = item.id;
253 var labelGroup = _this.shapesMap[id];
254 if (!labelGroup.destroyed) {
255 // fix: 如果说开发者的 label content 是一个 group,此处的偏移无法对 整个 content group 生效;场景类似 饼图 spider label 是一个含 2 个 textShape 的 gorup
256 var labelShapes = labelGroup.findAll(function (ele) { return ele.get('type') !== 'path'; });
257 each(labelShapes, function (labelShape) {
258 if (labelShape) {
259 if (item.offsetX) {
260 labelShape.attr('x', labelShape.attr('x') + item.offsetX);
261 }
262 if (item.offsetY) {
263 labelShape.attr('y', labelShape.attr('y') + item.offsetY);
264 }
265 }
266 });
267 }
268 }
269 });
270 };
271 return Labels;
272}());
273export default Labels;
274//# sourceMappingURL=labels.js.map
\No newline at end of file