UNPKG

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