UNPKG

61.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var adjust_1 = require("@antv/adjust");
5var attr_1 = require("@antv/attr");
6var util_1 = require("@antv/util");
7var animate_1 = require("../animate");
8var base_1 = tslib_1.__importDefault(require("../base"));
9var constant_1 = require("../constant");
10var helper_1 = require("../util/helper");
11var element_1 = tslib_1.__importDefault(require("./element"));
12var label_1 = require("./label");
13var base_2 = require("./shape/base");
14var group_data_1 = require("./util/group-data");
15var is_model_change_1 = require("./util/is-model-change");
16var parse_fields_1 = require("./util/parse-fields");
17var diff_1 = require("./util/diff");
18var scale_1 = require("../util/scale");
19var coordinate_1 = require("../util/coordinate");
20/**
21 * Geometry 几何标记基类,主要负责数据到图形属性的映射以及绘制逻辑。
22 */
23var Geometry = /** @class */ (function (_super) {
24 tslib_1.__extends(Geometry, _super);
25 /**
26 * 创建 Geometry 实例。
27 * @param cfg
28 */
29 function Geometry(cfg) {
30 var _this = _super.call(this, cfg) || this;
31 /** Geometry 几何标记类型。 */
32 _this.type = 'base';
33 // 内部产生的属性
34 /** Attribute map */
35 _this.attributes = {};
36 /** Element map */
37 _this.elements = [];
38 /** 使用 key-value 结构存储 Element,key 为每个 Element 实例对应的唯一 ID */
39 _this.elementsMap = {};
40 /** animate 配置项 */
41 _this.animateOption = true;
42 /** 图形属性映射配置 */
43 _this.attributeOption = {};
44 /** 存储上一次渲染时的 element 映射表,用于更新逻辑 */
45 _this.lastElementsMap = {};
46 /** 是否生成多个点来绘制图形。 */
47 _this.generatePoints = false;
48 /** 存储发生图形属性映射前的数据 */
49 _this.beforeMappingData = null;
50 _this.adjusts = {};
51 _this.idFields = [];
52 _this.hasSorted = false;
53 _this.isCoordinateChanged = false;
54 var container = cfg.container, labelsContainer = cfg.labelsContainer, coordinate = cfg.coordinate, data = cfg.data, _a = cfg.sortable, sortable = _a === void 0 ? false : _a, _b = cfg.visible, visible = _b === void 0 ? true : _b, theme = cfg.theme, _c = cfg.scales, scales = _c === void 0 ? {} : _c, _d = cfg.scaleDefs, scaleDefs = _d === void 0 ? {} : _d,
55 // 柱状图间隔与宽度相关配置
56 intervalPadding = cfg.intervalPadding, dodgePadding = cfg.dodgePadding, maxColumnWidth = cfg.maxColumnWidth, minColumnWidth = cfg.minColumnWidth, columnWidthRatio = cfg.columnWidthRatio, roseWidthRatio = cfg.roseWidthRatio, multiplePieWidthRatio = cfg.multiplePieWidthRatio, zIndexReversed = cfg.zIndexReversed, sortZIndex = cfg.sortZIndex, useDeferredLabel = cfg.useDeferredLabel;
57 _this.container = container;
58 _this.labelsContainer = labelsContainer;
59 _this.coordinate = coordinate;
60 _this.data = data;
61 _this.sortable = sortable;
62 _this.visible = visible;
63 _this.userTheme = theme;
64 _this.scales = scales;
65 _this.scaleDefs = scaleDefs;
66 // 柱状图间隔与宽度相关配置
67 _this.intervalPadding = intervalPadding;
68 _this.dodgePadding = dodgePadding;
69 _this.maxColumnWidth = maxColumnWidth;
70 _this.minColumnWidth = minColumnWidth;
71 _this.columnWidthRatio = columnWidthRatio;
72 _this.roseWidthRatio = roseWidthRatio;
73 _this.multiplePieWidthRatio = multiplePieWidthRatio;
74 _this.zIndexReversed = zIndexReversed;
75 _this.sortZIndex = sortZIndex;
76 _this.useDeferredLabel = useDeferredLabel ? (typeof useDeferredLabel === 'number' ? useDeferredLabel : Infinity) : null;
77 return _this;
78 }
79 /**
80 * 配置 position 通道映射规则。
81 *
82 * @example
83 * ```typescript
84 * // 数据结构: [{ x: 'A', y: 10, color: 'red' }]
85 * geometry.position('x*y');
86 * geometry.position([ 'x', 'y' ]);
87 * geometry.position({
88 * fields: [ 'x', 'y' ],
89 * });
90 * ```
91 *
92 * @param cfg 映射规则
93 * @returns
94 */
95 Geometry.prototype.position = function (cfg) {
96 var positionCfg = cfg;
97 if (!(0, util_1.isPlainObject)(cfg)) {
98 // 字符串字段或者数组字段
99 positionCfg = {
100 fields: (0, parse_fields_1.parseFields)(cfg),
101 };
102 }
103 var fields = (0, util_1.get)(positionCfg, 'fields');
104 if (fields.length === 1) {
105 // 默认填充一维 1*xx
106 fields.unshift('1');
107 (0, util_1.set)(positionCfg, 'fields', fields);
108 }
109 (0, util_1.set)(this.attributeOption, 'position', positionCfg);
110 return this;
111 };
112 Geometry.prototype.color = function (field, cfg) {
113 this.createAttrOption('color', field, cfg);
114 return this;
115 };
116 Geometry.prototype.shape = function (field, cfg) {
117 this.createAttrOption('shape', field, cfg);
118 return this;
119 };
120 Geometry.prototype.size = function (field, cfg) {
121 this.createAttrOption('size', field, cfg);
122 return this;
123 };
124 /**
125 * 设置数据调整方式。G2 目前内置了四种类型:
126 * 1. dodge
127 * 2. stack
128 * 3. symmetric
129 * 4. jitter
130 *
131 *
132 * **Tip**
133 * + 对于 'dodge' 类型,可以额外进行如下属性的配置:
134 * ```typescript
135 * geometry.adjust('dodge', {
136 * marginRatio: 0, // 取 0 到 1 范围的值(相对于每个柱子宽度),用于控制一个分组中柱子之间的间距
137 * dodgeBy: 'x', // 该属性只对 'dodge' 类型生效,声明以哪个数据字段为分组依据
138 * });
139 * ```
140 *
141 * + 对于 'stack' 类型,可以额外进行如下属性的配置:
142 * ```typescript
143 * geometry.adjust('stack', {
144 * reverseOrder: false, // 用于控制是否对数据进行反序操作
145 * });
146 * ```
147 *
148 * @example
149 * ```typescript
150 * geometry.adjust('stack');
151 *
152 * geometry.adjust({
153 * type: 'stack',
154 * reverseOrder: false,
155 * });
156 *
157 * // 组合使用 adjust
158 * geometry.adjust([ 'stack', 'dodge' ]);
159 *
160 * geometry.adjust([
161 * { type: 'stack' },
162 * { type: 'dodge', dodgeBy: 'x' },
163 * ]);
164 * ```
165 *
166 * @param adjustCfg 数据调整配置
167 * @returns
168 */
169 Geometry.prototype.adjust = function (adjustCfg) {
170 var adjusts = adjustCfg;
171 if ((0, util_1.isString)(adjustCfg) || (0, util_1.isPlainObject)(adjustCfg)) {
172 adjusts = [adjustCfg];
173 }
174 (0, util_1.each)(adjusts, function (adjust, index) {
175 if (!(0, util_1.isObject)(adjust)) {
176 adjusts[index] = { type: adjust };
177 }
178 });
179 this.adjustOption = adjusts;
180 return this;
181 };
182 Geometry.prototype.style = function (field, styleFunc) {
183 if ((0, util_1.isString)(field)) {
184 var fields = (0, parse_fields_1.parseFields)(field);
185 this.styleOption = {
186 fields: fields,
187 callback: styleFunc,
188 };
189 }
190 else {
191 var _a = field, fields = _a.fields, callback = _a.callback, cfg = _a.cfg;
192 if (fields || callback || cfg) {
193 this.styleOption = field;
194 }
195 else {
196 this.styleOption = {
197 cfg: field,
198 };
199 }
200 }
201 return this;
202 };
203 Geometry.prototype.tooltip = function (field, cfg) {
204 if ((0, util_1.isString)(field)) {
205 var fields = (0, parse_fields_1.parseFields)(field);
206 this.tooltipOption = {
207 fields: fields,
208 callback: cfg,
209 };
210 }
211 else {
212 this.tooltipOption = field;
213 }
214 return this;
215 };
216 /**
217 * Geometry 动画配置。
218 *
219 * + `animate(false)` 关闭动画
220 * + `animate(true)` 开启动画,默认开启。
221 *
222 * 我们将动画分为四个场景:
223 * 1. appear: 图表第一次加载时的入场动画;
224 * 2. enter: 图表绘制完成,发生更新后,产生的新图形的进场动画;
225 * 3. update: 图表绘制完成,数据发生变更后,有状态变更的图形的更新动画;
226 * 4. leave: 图表绘制完成,数据发生变更后,被销毁图形的销毁动画。
227 *
228 * @example
229 * ```typescript
230 * animate({
231 * enter: {
232 * duration: 1000, // enter 动画执行时间
233 * },
234 * leave: false, // 关闭 leave 销毁动画
235 * });
236 * ```
237 *
238 * @param cfg 动画配置
239 * @returns
240 */
241 Geometry.prototype.animate = function (cfg) {
242 this.animateOption = cfg;
243 return this;
244 };
245 Geometry.prototype.label = function (field, secondParam, thirdParam) {
246 if ((0, util_1.isString)(field)) {
247 var labelOption = {};
248 var fields = (0, parse_fields_1.parseFields)(field);
249 labelOption.fields = fields;
250 if ((0, util_1.isFunction)(secondParam)) {
251 labelOption.callback = secondParam;
252 }
253 else if ((0, util_1.isPlainObject)(secondParam)) {
254 labelOption.cfg = secondParam;
255 }
256 if (thirdParam) {
257 labelOption.cfg = thirdParam;
258 }
259 this.labelOption = labelOption;
260 }
261 else {
262 this.labelOption = field;
263 }
264 return this;
265 };
266 /**
267 * 设置状态对应的样式。
268 *
269 * @example
270 * ```ts
271 * chart.interval().state({
272 * selected: {
273 * animate: { duration: 100, easing: 'easeLinear' },
274 * style: {
275 * lineWidth: 2,
276 * stroke: '#000',
277 * },
278 * },
279 * });
280 * ```
281 *
282 * 如果图形 shape 是由多个 shape 组成,即为一个 G.Group 对象,那么针对 group 中的每个 shape,我们需要使用下列方式进行状态样式设置:
283 * 如果我们为 group 中的每个 shape 设置了 'name' 属性(shape.set('name', 'xx')),则以 'name' 作为 key,否则默认以索引值(即 shape 的 添加顺序)为 key。
284 *
285 * ```ts
286 * chart.interval().shape('groupShape').state({
287 * selected: {
288 * style: {
289 * 0: { lineWidth: 2 },
290 * 1: { fillOpacity: 1 },
291 * }
292 * }
293 * });
294 * ```
295 *
296 * @param cfg 状态样式
297 */
298 Geometry.prototype.state = function (cfg) {
299 this.stateOption = cfg;
300 return this;
301 };
302 /**
303 * 用于向 shape 中传入自定义的数据。目前可能仅仅可能用于在自定义 shape 的时候,像自定义 shape 中传入自定义的数据,方便实现自定义 shape 的配置能力。
304 *
305 * @example
306 * ```ts
307 * chart.interval().customInfo({ yourData: 'hello, g2!' });
308 * ```
309 *
310 * 然后在自定义 shape 的时候,可以拿到这个信息。
311 *
312 * ```ts
313 * registerShape('interval', 'your-shape', {
314 * draw(shapeInfo, container) {
315 * const { customInfo } = shapeInfo;
316 * console.log(customInfo); // will log { yourData: 'hello, g2!' }.
317 * }
318 * });
319 * ```
320 *
321 * @param cfg
322 */
323 Geometry.prototype.customInfo = function (cfg) {
324 this.customOption = cfg;
325 return this;
326 };
327 /**
328 * 初始化 Geomtry 实例:
329 * 创建 [[Attribute]] and [[Scale]] 实例,进行数据处理,包括分组、数值化以及数据调整。
330 */
331 Geometry.prototype.init = function (cfg) {
332 if (cfg === void 0) { cfg = {}; }
333 this.setCfg(cfg);
334 this.initAttributes(); // 创建图形属性
335 // 数据加工:分组 -> 数字化 -> adjust
336 this.processData(this.data);
337 // 调整 scale
338 this.adjustScale();
339 };
340 /**
341 * Geometry 更新。
342 * @param [cfg] 更新的配置
343 */
344 Geometry.prototype.update = function (cfg) {
345 if (cfg === void 0) { cfg = {}; }
346 var data = cfg.data, isDataChanged = cfg.isDataChanged, isCoordinateChanged = cfg.isCoordinateChanged;
347 var _a = this, attributeOption = _a.attributeOption, lastAttributeOption = _a.lastAttributeOption;
348 if (!(0, util_1.isEqual)(attributeOption, lastAttributeOption)) {
349 // 映射发生改变,则重新创建图形属性
350 this.init(cfg);
351 }
352 else if (data && (isDataChanged || !(0, util_1.isEqual)(data, this.data))) {
353 // 数据发生变化
354 this.setCfg(cfg);
355 this.initAttributes(); // 创建图形属性
356 this.processData(data); // 数据加工:分组 -> 数字化 -> adjust
357 }
358 else {
359 // 有可能 coordinate 变化
360 this.setCfg(cfg);
361 }
362 // 调整 scale
363 this.adjustScale();
364 this.isCoordinateChanged = isCoordinateChanged;
365 };
366 /**
367 * 将原始数据映射至图形空间,同时创建图形对象。
368 */
369 Geometry.prototype.paint = function (isUpdate) {
370 var _this = this;
371 if (isUpdate === void 0) { isUpdate = false; }
372 if (this.animateOption) {
373 this.animateOption = (0, util_1.deepMix)({}, (0, animate_1.getDefaultAnimateCfg)(this.type, this.coordinate), this.animateOption);
374 }
375 this.defaultSize = undefined;
376 this.elementsMap = {};
377 this.elements = [];
378 var offscreenGroup = this.getOffscreenGroup();
379 offscreenGroup.clear();
380 var beforeMappingData = this.beforeMappingData;
381 var dataArray = this.beforeMapping(beforeMappingData);
382 this.dataArray = new Array(dataArray.length);
383 for (var i = 0; i < dataArray.length; i++) {
384 var data = dataArray[i];
385 this.dataArray[i] = this.mapping(data);
386 }
387 this.updateElements(this.dataArray, isUpdate);
388 this.lastElementsMap = this.elementsMap;
389 if (this.canDoGroupAnimation(isUpdate)) {
390 // 如果用户没有配置 appear.animation,就默认走整体动画
391 var container = this.container;
392 var type = this.type;
393 var coordinate = this.coordinate;
394 var animateCfg = (0, util_1.get)(this.animateOption, 'appear');
395 var yScale = this.getYScale();
396 var yMinPoint = coordinate.convert({
397 x: 0,
398 y: yScale.scale(this.getYMinValue()),
399 });
400 (0, animate_1.doGroupAppearAnimate)(container, animateCfg, type, coordinate, yMinPoint);
401 }
402 // 添加 label
403 if (this.labelOption) {
404 var deferred = this.useDeferredLabel;
405 var callback = (function () { return _this.renderLabels((0, util_1.flatten)(_this.dataArray), isUpdate); }).bind(this);
406 if (typeof deferred === 'number') {
407 // Use `requestIdleCallback` to render labels in idle time (like react fiber)
408 var timeout = (typeof deferred === 'number' && deferred !== Infinity) ? deferred : 0;
409 if (!window.requestIdleCallback) {
410 setTimeout(callback, timeout);
411 }
412 else {
413 var options = timeout && timeout !== Infinity ? { timeout: timeout } : undefined;
414 window.requestIdleCallback(callback, options);
415 }
416 }
417 else {
418 callback();
419 }
420 }
421 // 缓存,用于更新
422 this.lastAttributeOption = tslib_1.__assign({}, this.attributeOption);
423 if (this.visible === false) {
424 // 用户在初始化的时候声明 visible: false
425 this.changeVisible(false);
426 }
427 };
428 /**
429 * 清空当前 Geometry,配置项仍保留,但是内部创建的对象全部清空。
430 * @override
431 */
432 Geometry.prototype.clear = function () {
433 var _a = this, container = _a.container, geometryLabel = _a.geometryLabel, offscreenGroup = _a.offscreenGroup;
434 if (container) {
435 container.clear();
436 }
437 if (geometryLabel) {
438 geometryLabel.clear();
439 }
440 if (offscreenGroup) {
441 offscreenGroup.clear();
442 }
443 // 属性恢复至出厂状态
444 this.scaleDefs = undefined;
445 this.attributes = {};
446 this.scales = {};
447 this.elementsMap = {};
448 this.lastElementsMap = {};
449 this.elements = [];
450 this.adjusts = {};
451 this.dataArray = null;
452 this.beforeMappingData = null;
453 this.lastAttributeOption = undefined;
454 this.defaultSize = undefined;
455 this.idFields = [];
456 this.groupScales = undefined;
457 this.hasSorted = false;
458 this.isCoordinateChanged = false;
459 };
460 /**
461 * 销毁 Geometry 实例。
462 */
463 Geometry.prototype.destroy = function () {
464 this.clear();
465 var container = this.container;
466 container.remove(true);
467 if (this.offscreenGroup) {
468 this.offscreenGroup.remove(true);
469 this.offscreenGroup = null;
470 }
471 if (this.geometryLabel) {
472 this.geometryLabel.destroy();
473 this.geometryLabel = null;
474 }
475 this.theme = undefined;
476 this.shapeFactory = undefined;
477 _super.prototype.destroy.call(this);
478 };
479 /**
480 * 获取决定分组的图形属性对应的 scale 实例。
481 * @returns
482 */
483 Geometry.prototype.getGroupScales = function () {
484 return this.groupScales;
485 };
486 /**
487 * 根据名字获取图形属性实例。
488 */
489 Geometry.prototype.getAttribute = function (name) {
490 return this.attributes[name];
491 };
492 /** 获取 x 轴对应的 scale 实例。 */
493 Geometry.prototype.getXScale = function () {
494 return this.getAttribute('position').scales[0];
495 };
496 /** 获取 y 轴对应的 scale 实例。 */
497 Geometry.prototype.getYScale = function () {
498 return this.getAttribute('position').scales[1];
499 };
500 /**
501 * 获取决定分组的图形属性实例。
502 */
503 Geometry.prototype.getGroupAttributes = function () {
504 var rst = [];
505 (0, util_1.each)(this.attributes, function (attr) {
506 if (constant_1.GROUP_ATTRS.includes(attr.type)) {
507 rst.push(attr);
508 }
509 });
510 return rst;
511 };
512 /** 获取图形属性默认的映射值。 */
513 Geometry.prototype.getDefaultValue = function (attrName) {
514 var value;
515 var attr = this.getAttribute(attrName);
516 if (attr && (0, util_1.isEmpty)(attr.scales)) {
517 // 获取映射至常量的值
518 value = attr.values[0];
519 }
520 return value;
521 };
522 /**
523 * 获取该数据发生图形映射后对应的 Attribute 图形空间数据。
524 * @param attr Attribute 图形属性实例。
525 * @param obj 需要进行映射的原始数据。
526 * @returns
527 */
528 Geometry.prototype.getAttributeValues = function (attr, obj) {
529 var params = [];
530 var scales = attr.scales;
531 for (var index = 0, length_1 = scales.length; index < length_1; index++) {
532 var scale = scales[index];
533 var field = scale.field;
534 if (scale.isIdentity) {
535 params.push(scale.values);
536 }
537 else {
538 params.push(obj[field]);
539 }
540 }
541 return attr.mapping.apply(attr, tslib_1.__spreadArray([], tslib_1.__read(params), false));
542 };
543 /**
544 * 获取对应的 adjust 实例
545 * @param adjustType
546 * @returns
547 */
548 Geometry.prototype.getAdjust = function (adjustType) {
549 return this.adjusts[adjustType];
550 };
551 /**
552 * 获得 coordinate 实例
553 * @returns
554 */
555 Geometry.prototype.getCoordinate = function () {
556 return this.coordinate;
557 };
558 Geometry.prototype.getData = function () {
559 return this.data;
560 };
561 /**
562 * 获取 shape 对应的 marker 样式。
563 * @param shapeName shape 具体名字
564 * @param cfg marker 信息
565 * @returns
566 */
567 Geometry.prototype.getShapeMarker = function (shapeName, cfg) {
568 var shapeFactory = this.getShapeFactory();
569 return shapeFactory.getMarker(shapeName, cfg);
570 };
571 /**
572 * 根据一定的规则查找 Geometry 的 Elements。
573 *
574 * ```typescript
575 * getElementsBy((element) => {
576 * const data = element.getData();
577 *
578 * return data.a === 'a';
579 * });
580 * ```
581 *
582 * @param condition 定义查找规则的回调函数。
583 * @returns
584 */
585 Geometry.prototype.getElementsBy = function (condition) {
586 return this.elements.filter(function (element) { return condition(element); });
587 };
588 /**
589 * 获取 Geometry 的所有 Elements。
590 *
591 * ```typescript
592 * getElements();
593 * ```
594 */
595 Geometry.prototype.getElements = function () {
596 return this.elements;
597 };
598 /**
599 * 获取数据对应的唯一 id。
600 * @param data Element 对应的绘制数据
601 * @returns
602 */
603 Geometry.prototype.getElementId = function (data) {
604 data = (0, util_1.isArray)(data) ? data[0] : data;
605 var originData = data[constant_1.FIELD_ORIGIN];
606 // 如果用户声明了使用哪些字段作为 id 值
607 if (this.idFields.length) {
608 var elementId = originData[this.idFields[0]];
609 for (var index = 1; index < this.idFields.length; index++) {
610 elementId += '-' + originData[this.idFields[index]];
611 }
612 return elementId;
613 }
614 var type = this.type;
615 var xScale = this.getXScale();
616 var yScale = this.getYScale();
617 var xField = xScale.field || 'x';
618 var yField = yScale.field || 'y';
619 var yVal = originData[yField];
620 var xVal;
621 if (xScale.type === 'identity') {
622 xVal = xScale.values[0];
623 }
624 else {
625 xVal = originData[xField];
626 }
627 var id;
628 if (type === 'interval' || type === 'schema') {
629 id = "".concat(xVal);
630 }
631 else if (type === 'line' || type === 'area' || type === 'path') {
632 id = type;
633 }
634 else {
635 id = "".concat(xVal, "-").concat(yVal);
636 }
637 var groupScales = this.groupScales;
638 for (var index = 0, length_2 = groupScales.length; index < length_2; index++) {
639 var groupScale = groupScales[index];
640 var field = groupScale.field;
641 id = "".concat(id, "-").concat(originData[field]);
642 }
643 // 用户在进行 dodge 类型的 adjust 调整的时候设置了 dodgeBy 属性
644 var dodgeAdjust = this.getAdjust('dodge');
645 if (dodgeAdjust) {
646 var dodgeBy = dodgeAdjust.dodgeBy;
647 if (dodgeBy) {
648 id = "".concat(id, "-").concat(originData[dodgeBy]);
649 }
650 }
651 if (this.getAdjust('jitter')) {
652 id = "".concat(id, "-").concat(data.x, "-").concat(data.y);
653 }
654 return id;
655 };
656 /**
657 * 获取所有需要创建 scale 的字段名称。
658 */
659 Geometry.prototype.getScaleFields = function () {
660 var fields = [];
661 var tmpMap = new Map();
662 var _a = this, attributeOption = _a.attributeOption, labelOption = _a.labelOption, tooltipOption = _a.tooltipOption;
663 // 获取图形属性上的 fields
664 for (var attributeType in attributeOption) {
665 if (attributeOption.hasOwnProperty(attributeType)) {
666 var eachOpt = attributeOption[attributeType];
667 if (eachOpt.fields) {
668 (0, helper_1.uniq)(eachOpt.fields, fields, tmpMap);
669 }
670 else if (eachOpt.values) {
671 // 考虑 size(10), shape('circle') 等场景
672 (0, helper_1.uniq)(eachOpt.values, fields, tmpMap);
673 }
674 }
675 }
676 // 获取 label 上的字段
677 if (labelOption && labelOption.fields) {
678 (0, helper_1.uniq)(labelOption.fields, fields, tmpMap);
679 }
680 // 获取 tooltip 上的字段
681 if ((0, util_1.isObject)(tooltipOption) && tooltipOption.fields) {
682 (0, helper_1.uniq)(tooltipOption.fields, fields, tmpMap);
683 }
684 return fields;
685 };
686 /**
687 * 显示或者隐藏 geometry。
688 * @param visible
689 */
690 Geometry.prototype.changeVisible = function (visible) {
691 _super.prototype.changeVisible.call(this, visible);
692 var elements = this.elements;
693 for (var index = 0, length_3 = elements.length; index < length_3; index++) {
694 var element = elements[index];
695 element.changeVisible(visible);
696 }
697 if (visible) {
698 if (this.container) {
699 this.container.show();
700 }
701 if (this.labelsContainer) {
702 this.labelsContainer.show();
703 }
704 }
705 else {
706 if (this.container) {
707 this.container.hide();
708 }
709 if (this.labelsContainer) {
710 this.labelsContainer.hide();
711 }
712 }
713 };
714 /**
715 * 获得所有的字段
716 */
717 Geometry.prototype.getFields = function () {
718 var uniqMap = new Map();
719 var fields = [];
720 Object.values(this.attributeOption).forEach(function (cfg) {
721 var fs = (cfg === null || cfg === void 0 ? void 0 : cfg.fields) || [];
722 fs.forEach(function (f) {
723 if (!uniqMap.has(f)) {
724 fields.push(f);
725 }
726 uniqMap.set(f, true);
727 });
728 }, []);
729 return fields;
730 };
731 /**
732 * 获取当前配置中的所有分组 & 分类的字段。
733 * @return fields string[]
734 */
735 Geometry.prototype.getGroupFields = function () {
736 var groupFields = [];
737 var tmpMap = new Map(); // 用于去重过滤
738 for (var index = 0, length_4 = constant_1.GROUP_ATTRS.length; index < length_4; index++) {
739 var attributeName = constant_1.GROUP_ATTRS[index];
740 var cfg = this.attributeOption[attributeName];
741 if (cfg && cfg.fields) {
742 (0, helper_1.uniq)(cfg.fields, groupFields, tmpMap);
743 }
744 }
745 return groupFields;
746 };
747 /**
748 * 获得图形的 x y 字段。
749 */
750 Geometry.prototype.getXYFields = function () {
751 var _a = tslib_1.__read(this.attributeOption.position.fields, 2), x = _a[0], y = _a[1];
752 return [x, y];
753 };
754 /**
755 * x 字段
756 * @returns
757 */
758 Geometry.prototype.getXField = function () {
759 return (0, util_1.get)(this.getXYFields(), [0]);
760 };
761 /**
762 * y 字段
763 * @returns
764 */
765 Geometry.prototype.getYField = function () {
766 return (0, util_1.get)(this.getXYFields(), [1]);
767 };
768 /**
769 * 获取该 Geometry 下所有生成的 shapes。
770 * @returns shapes
771 */
772 Geometry.prototype.getShapes = function () {
773 return this.elements.map(function (element) { return element.shape; });
774 };
775 /**
776 * 获取虚拟 Group。
777 * @returns
778 */
779 Geometry.prototype.getOffscreenGroup = function () {
780 if (!this.offscreenGroup) {
781 var GroupCtor = this.container.getGroupBase(); // 获取分组的构造函数
782 this.offscreenGroup = new GroupCtor({});
783 }
784 return this.offscreenGroup;
785 };
786 // 对数据进行排序
787 Geometry.prototype.sort = function (mappingArray) {
788 if (!this.hasSorted) {
789 // 未发生过排序
790 var xScale_1 = this.getXScale();
791 var xField_1 = xScale_1.field;
792 for (var index = 0; index < mappingArray.length; index++) {
793 var itemArr = mappingArray[index];
794 itemArr.sort(function (obj1, obj2) {
795 return xScale_1.translate(obj1[constant_1.FIELD_ORIGIN][xField_1]) - xScale_1.translate(obj2[constant_1.FIELD_ORIGIN][xField_1]);
796 });
797 }
798 }
799 this.hasSorted = true;
800 };
801 /**
802 * 调整度量范围。主要针对发生层叠以及一些特殊需求的 Geometry,比如 Interval 下的柱状图 Y 轴默认从 0 开始。
803 */
804 Geometry.prototype.adjustScale = function () {
805 var yScale = this.getYScale();
806 // 如果数据发生过 stack adjust,需要调整下 yScale 的数据范围
807 if (yScale && this.getAdjust('stack')) {
808 this.updateStackRange(yScale, this.beforeMappingData);
809 }
810 };
811 /**
812 * 获取当前 Geometry 对应的 Shape 工厂实例。
813 */
814 Geometry.prototype.getShapeFactory = function () {
815 var shapeType = this.shapeType;
816 if (!(0, base_2.getShapeFactory)(shapeType)) {
817 return;
818 }
819 if (!this.shapeFactory) {
820 this.shapeFactory = (0, util_1.clone)((0, base_2.getShapeFactory)(shapeType)); // 防止多个 view 共享一个 shapeFactory 实例,导致 coordinate 被篡改
821 }
822 // 因为这里缓存了 shapeFactory,但是外部可能会变更 coordinate,导致无法重新设置到 shapeFactory 中
823 this.shapeFactory.coordinate = this.coordinate;
824 // theme 原因同上
825 this.shapeFactory.theme = this.theme.geometries[shapeType] || {};
826 return this.shapeFactory;
827 };
828 /**
829 * 获取每个 Shape 对应的关键点数据。
830 * @param obj 经过分组 -> 数字化 -> adjust 调整后的数据记录
831 * @returns
832 */
833 Geometry.prototype.createShapePointsCfg = function (obj) {
834 var xScale = this.getXScale();
835 var yScale = this.getYScale();
836 var x = this.normalizeValues(obj[xScale.field], xScale);
837 var y; // 存在没有 y 的情况
838 if (yScale) {
839 y = this.normalizeValues(obj[yScale.field], yScale);
840 }
841 else {
842 y = obj.y ? obj.y : 0.1;
843 }
844 return {
845 x: x,
846 y: y,
847 y0: yScale ? yScale.scale(this.getYMinValue()) : undefined,
848 };
849 };
850 /**
851 * 创建 Element 实例。
852 * @param mappingDatum Element 对应的绘制数据
853 * @param [isUpdate] 是否处于更新阶段
854 * @returns element 返回创建的 Element 实例
855 */
856 Geometry.prototype.createElement = function (mappingDatum, index, isUpdate) {
857 if (isUpdate === void 0) { isUpdate = false; }
858 var container = this.container;
859 var shapeCfg = this.getDrawCfg(mappingDatum); // 获取绘制图形的配置信息
860 var shapeFactory = this.getShapeFactory();
861 var element = new element_1.default({
862 shapeFactory: shapeFactory,
863 container: container,
864 offscreenGroup: this.getOffscreenGroup(),
865 elementIndex: index,
866 });
867 element.animate = this.animateOption;
868 element.geometry = this;
869 element.draw(shapeCfg, isUpdate); // 绘制
870 return element;
871 };
872 /**
873 * 获取每条数据对应的图形绘制数据。
874 * @param mappingDatum 映射后的数据
875 * @returns draw cfg
876 */
877 Geometry.prototype.getDrawCfg = function (mappingDatum) {
878 var originData = mappingDatum[constant_1.FIELD_ORIGIN]; // 原始数据
879 var cfg = {
880 mappingData: mappingDatum,
881 data: originData,
882 x: mappingDatum.x,
883 y: mappingDatum.y,
884 color: mappingDatum.color,
885 size: mappingDatum.size,
886 isInCircle: this.coordinate.isPolar,
887 customInfo: this.customOption,
888 };
889 var shapeName = mappingDatum.shape;
890 if (!shapeName && this.getShapeFactory()) {
891 shapeName = this.getShapeFactory().defaultShapeType;
892 }
893 cfg.shape = shapeName;
894 // 获取默认样式
895 var theme = this.theme.geometries[this.shapeType];
896 cfg.defaultStyle = (0, util_1.get)(theme, [shapeName, 'default'], {}).style;
897 if (!cfg.defaultStyle && this.getShapeFactory()) {
898 cfg.defaultStyle = this.getShapeFactory().getDefaultStyle(theme);
899 }
900 var styleOption = this.styleOption;
901 if (styleOption) {
902 cfg.style = this.getStyleCfg(styleOption, originData);
903 }
904 if (this.generatePoints) {
905 cfg.points = mappingDatum.points;
906 cfg.nextPoints = mappingDatum.nextPoints;
907 }
908 return cfg;
909 };
910 Geometry.prototype.updateElements = function (mappingDataArray, isUpdate) {
911 var e_1, _a, e_2, _b, e_3, _c;
912 if (isUpdate === void 0) { isUpdate = false; }
913 var keyDatum = new Map();
914 var keys = [];
915 // 用来保持 diff 元素之后 added, updated 的相对顺序
916 var keyIndex = new Map();
917 var index = 0;
918 // 获得更新数据所有的 keys
919 // 将更新的数据用 key 索引
920 for (var i = 0; i < mappingDataArray.length; i++) {
921 var mappingData = mappingDataArray[i];
922 for (var j = 0; j < mappingData.length; j++) {
923 var mappingDatum = mappingData[j];
924 var key = this.getElementId(mappingDatum);
925 var finalKey = keyDatum.has(key) ? "".concat(key, "-").concat(i, "-").concat(j) : key;
926 keys.push(finalKey);
927 keyDatum.set(finalKey, mappingDatum);
928 keyIndex.set(finalKey, index);
929 index++;
930 }
931 }
932 this.elements = new Array(index);
933 var _d = (0, diff_1.diff)(this.lastElementsMap, keys), added = _d.added, updated = _d.updated, removed = _d.removed;
934 try {
935 // 新建 element
936 for (var added_1 = tslib_1.__values(added), added_1_1 = added_1.next(); !added_1_1.done; added_1_1 = added_1.next()) {
937 var key = added_1_1.value;
938 var mappingDatum = keyDatum.get(key);
939 var i = keyIndex.get(key);
940 var element = this.createElement(mappingDatum, i, isUpdate);
941 this.elements[i] = element;
942 this.elementsMap[key] = element;
943 if (element.shape) {
944 element.shape.set('zIndex', this.zIndexReversed ? this.elements.length - i : i);
945 }
946 }
947 }
948 catch (e_1_1) { e_1 = { error: e_1_1 }; }
949 finally {
950 try {
951 if (added_1_1 && !added_1_1.done && (_a = added_1.return)) _a.call(added_1);
952 }
953 finally { if (e_1) throw e_1.error; }
954 }
955 try {
956 // 更新 element
957 for (var updated_1 = tslib_1.__values(updated), updated_1_1 = updated_1.next(); !updated_1_1.done; updated_1_1 = updated_1.next()) {
958 var key = updated_1_1.value;
959 var element = this.lastElementsMap[key];
960 var mappingDatum = keyDatum.get(key);
961 var currentShapeCfg = this.getDrawCfg(mappingDatum);
962 var preShapeCfg = element.getModel();
963 var i = keyIndex.get(key);
964 if (this.isCoordinateChanged || (0, is_model_change_1.isModelChange)(currentShapeCfg, preShapeCfg)) {
965 element.animate = this.animateOption;
966 // 通过绘制数据的变更来判断是否需要更新,因为用户有可能会修改图形属性映射
967 element.update(currentShapeCfg); // 更新对应的 element
968 }
969 this.elements[i] = element;
970 this.elementsMap[key] = element;
971 if (element.shape) {
972 element.shape.set('zIndex', this.zIndexReversed ? this.elements.length - i : i);
973 }
974 }
975 }
976 catch (e_2_1) { e_2 = { error: e_2_1 }; }
977 finally {
978 try {
979 if (updated_1_1 && !updated_1_1.done && (_b = updated_1.return)) _b.call(updated_1);
980 }
981 finally { if (e_2) throw e_2.error; }
982 }
983 // 全部 setZIndex 之后,再执行 sort
984 if (this.container) {
985 this.container.sort();
986 }
987 try {
988 // 销毁被删除的 elements
989 for (var removed_1 = tslib_1.__values(removed), removed_1_1 = removed_1.next(); !removed_1_1.done; removed_1_1 = removed_1.next()) {
990 var key = removed_1_1.value;
991 var element = this.lastElementsMap[key];
992 // 更新动画配置,用户有可能在更新之前有对动画进行配置操作
993 element.animate = this.animateOption;
994 element.destroy();
995 }
996 }
997 catch (e_3_1) { e_3 = { error: e_3_1 }; }
998 finally {
999 try {
1000 if (removed_1_1 && !removed_1_1.done && (_c = removed_1.return)) _c.call(removed_1);
1001 }
1002 finally { if (e_3) throw e_3.error; }
1003 }
1004 };
1005 /**
1006 * 获取渲染的 label 类型。
1007 */
1008 Geometry.prototype.getLabelType = function () {
1009 var _a = this, labelOption = _a.labelOption, coordinate = _a.coordinate, type = _a.type;
1010 var coordinateType = coordinate.type, isTransposed = coordinate.isTransposed;
1011 var labelType = (0, util_1.get)(labelOption, ['cfg', 'type']);
1012 if (!labelType) {
1013 // 用户未定义,则进行默认的逻辑
1014 if (coordinateType === 'polar') {
1015 // 极坐标下使用通用的极坐标文本,转置则使用饼图
1016 labelType = isTransposed ? 'pie' : 'polar';
1017 }
1018 else if (coordinateType === 'theta') {
1019 // theta 坐标系下使用饼图文本
1020 labelType = 'pie';
1021 }
1022 else if (type === 'interval' || type === 'polygon') {
1023 labelType = 'interval';
1024 }
1025 else {
1026 labelType = 'base';
1027 }
1028 }
1029 return labelType;
1030 };
1031 /**
1032 * 获取 Y 轴上的最小值。
1033 */
1034 Geometry.prototype.getYMinValue = function () {
1035 var yScale = this.getYScale();
1036 var min = yScale.min, max = yScale.max;
1037 var value;
1038 if (min >= 0) {
1039 value = min;
1040 }
1041 else if (max <= 0) {
1042 // 当值全位于负区间时,需要保证 ymin 在区域内,不可为 0
1043 value = max;
1044 }
1045 else {
1046 value = 0;
1047 }
1048 return value;
1049 };
1050 // 创建图形属性相关的配置项
1051 Geometry.prototype.createAttrOption = function (attrName, field, cfg) {
1052 if ((0, util_1.isNil)(field) || (0, util_1.isObject)(field)) {
1053 if ((0, util_1.isObject)(field) && (0, util_1.isEqual)(Object.keys(field), ['values'])) {
1054 // shape({ values: [ 'funnel' ] })
1055 (0, util_1.set)(this.attributeOption, attrName, {
1056 fields: field.values,
1057 });
1058 }
1059 else {
1060 (0, util_1.set)(this.attributeOption, attrName, field);
1061 }
1062 }
1063 else {
1064 var attrCfg = {};
1065 if ((0, util_1.isNumber)(field)) {
1066 // size(3)
1067 attrCfg.values = [field];
1068 }
1069 else {
1070 attrCfg.fields = (0, parse_fields_1.parseFields)(field);
1071 }
1072 if (cfg) {
1073 if ((0, util_1.isFunction)(cfg)) {
1074 attrCfg.callback = cfg;
1075 }
1076 else {
1077 attrCfg.values = cfg;
1078 }
1079 }
1080 (0, util_1.set)(this.attributeOption, attrName, attrCfg);
1081 }
1082 };
1083 Geometry.prototype.initAttributes = function () {
1084 var _this = this;
1085 var _a = this, attributes = _a.attributes, attributeOption = _a.attributeOption, theme = _a.theme, shapeType = _a.shapeType;
1086 this.groupScales = [];
1087 var tmpMap = {};
1088 var _loop_1 = function (attrType) {
1089 if (attributeOption.hasOwnProperty(attrType)) {
1090 var option = attributeOption[attrType];
1091 if (!option) {
1092 return { value: void 0 };
1093 }
1094 var attrCfg = tslib_1.__assign({}, option);
1095 var callback = attrCfg.callback, values = attrCfg.values, _b = attrCfg.fields, fields = _b === void 0 ? [] : _b;
1096 // 获取每一个字段对应的 scale
1097 var scales = fields.map(function (field) {
1098 var scale = _this.scales[field];
1099 if (!tmpMap[field] && constant_1.GROUP_ATTRS.includes(attrType)) {
1100 var inferedScaleType = (0, scale_1.inferScaleType)(scale, (0, util_1.get)(_this.scaleDefs, field), attrType, _this.type);
1101 if (inferedScaleType === 'cat') {
1102 _this.groupScales.push(scale);
1103 tmpMap[field] = true;
1104 }
1105 }
1106 return scale;
1107 });
1108 attrCfg.scales = scales;
1109 if (attrType !== 'position' && scales.length === 1 && scales[0].type === 'identity') {
1110 // 用户在图形通道上声明了常量字段 color('red'), size(5)
1111 attrCfg.values = scales[0].values;
1112 }
1113 else if (!callback && !values) {
1114 // 用户没有指定任何规则,则使用默认的映射规则
1115 if (attrType === 'size') {
1116 attrCfg.values = theme.sizes;
1117 }
1118 else if (attrType === 'shape') {
1119 attrCfg.values = theme.shapes[shapeType] || [];
1120 }
1121 else if (attrType === 'color') {
1122 if (scales.length) {
1123 // 根据数值个数使用对应的色板
1124 attrCfg.values = scales[0].values.length <= 10 ? theme.colors10 : theme.colors20;
1125 }
1126 else {
1127 attrCfg.values = theme.colors10;
1128 }
1129 }
1130 }
1131 var AttributeCtor = (0, attr_1.getAttribute)(attrType);
1132 attributes[attrType] = new AttributeCtor(attrCfg);
1133 }
1134 };
1135 // 遍历每一个 attrOption,各自创建 Attribute 实例
1136 for (var attrType in attributeOption) {
1137 var state_1 = _loop_1(attrType);
1138 if (typeof state_1 === "object")
1139 return state_1.value;
1140 }
1141 };
1142 // 处理数据:分组 -> 数字化 -> adjust 调整
1143 Geometry.prototype.processData = function (data) {
1144 var e_4, _a;
1145 this.hasSorted = false;
1146 var scales = this.getAttribute('position').scales;
1147 var categoryScales = scales.filter(function (scale) { return scale.isCategory; });
1148 var groupedArray = this.groupData(data); // 数据分组
1149 var beforeAdjust = [];
1150 for (var i = 0, len = groupedArray.length; i < len; i++) {
1151 var subData = groupedArray[i];
1152 var arr = [];
1153 for (var j = 0, subLen = subData.length; j < subLen; j++) {
1154 var originData = subData[j];
1155 var item = {};
1156 // tslint:disable-next-line: forin
1157 for (var k in originData) {
1158 item[k] = originData[k];
1159 }
1160 item[constant_1.FIELD_ORIGIN] = originData;
1161 try {
1162 // 将分类数据翻译成数据, 仅对位置相关的度量进行数字化处理
1163 for (var categoryScales_1 = (e_4 = void 0, tslib_1.__values(categoryScales)), categoryScales_1_1 = categoryScales_1.next(); !categoryScales_1_1.done; categoryScales_1_1 = categoryScales_1.next()) {
1164 var scale = categoryScales_1_1.value;
1165 var field = scale.field;
1166 item[field] = scale.translate(item[field]);
1167 }
1168 }
1169 catch (e_4_1) { e_4 = { error: e_4_1 }; }
1170 finally {
1171 try {
1172 if (categoryScales_1_1 && !categoryScales_1_1.done && (_a = categoryScales_1.return)) _a.call(categoryScales_1);
1173 }
1174 finally { if (e_4) throw e_4.error; }
1175 }
1176 arr.push(item);
1177 }
1178 beforeAdjust.push(arr);
1179 }
1180 var dataArray = this.adjustData(beforeAdjust); // 进行 adjust 数据调整
1181 this.beforeMappingData = dataArray;
1182 return dataArray;
1183 };
1184 // 调整数据
1185 Geometry.prototype.adjustData = function (dataArray) {
1186 var adjustOption = this.adjustOption;
1187 var _a = this, intervalPadding = _a.intervalPadding, dodgePadding = _a.dodgePadding, theme = _a.theme;
1188 // 兼容theme配置
1189 var maxColumnWidth = this.maxColumnWidth || theme.maxColumnWidth;
1190 var minColumnWidth = this.minColumnWidth || theme.minColumnWidth;
1191 var columnWidthRatio = this.columnWidthRatio || theme.columnWidthRatio;
1192 var result = dataArray;
1193 if (adjustOption) {
1194 var xScale_2 = this.getXScale();
1195 var yScale = this.getYScale();
1196 var xField = xScale_2.field;
1197 var yField = yScale ? yScale.field : null;
1198 var xDimensionLength = (0, coordinate_1.getXDimensionLength)(this.coordinate);
1199 var groupNum = xScale_2.values.length;
1200 // 传入size计算相关参数,默认宽度、最大最小宽度约束
1201 var sizeAttr = this.getAttribute('size');
1202 var defaultSize = void 0;
1203 if (sizeAttr) {
1204 defaultSize = sizeAttr.values[0];
1205 }
1206 for (var i = 0, len = adjustOption.length; i < len; i++) {
1207 var adjust = adjustOption[i];
1208 var adjustCfg = tslib_1.__assign({ xField: xField, yField: yField, intervalPadding: intervalPadding, dodgePadding: dodgePadding, xDimensionLength: xDimensionLength, groupNum: groupNum, defaultSize: defaultSize, maxColumnWidth: maxColumnWidth, minColumnWidth: minColumnWidth, columnWidthRatio: columnWidthRatio }, adjust);
1209 var type = adjust.type;
1210 if (type === 'dodge') {
1211 var adjustNames = [];
1212 if (xScale_2.isCategory || xScale_2.type === 'identity') {
1213 adjustNames.push('x');
1214 }
1215 else if (!yScale) {
1216 adjustNames.push('y');
1217 }
1218 else {
1219 throw new Error('dodge is not support linear attribute, please use category attribute!');
1220 }
1221 adjustCfg.adjustNames = adjustNames;
1222 // 每个分组内每条柱子的宽度占比,用户不可指定,用户需要通过 columnWidthRatio 指定
1223 // 兼容theme配置
1224 adjustCfg.dodgeRatio = columnWidthRatio;
1225 }
1226 else if (type === 'stack') {
1227 var coordinate = this.coordinate;
1228 if (!yScale) {
1229 // 一维的情况下获取高度和默认size
1230 adjustCfg.height = coordinate.getHeight();
1231 var size = this.getDefaultValue('size') || 3;
1232 adjustCfg.size = size;
1233 }
1234 // 不进行 transpose 时,用户又没有设置这个参数时,默认从上向下
1235 if (!coordinate.isTransposed && (0, util_1.isNil)(adjustCfg.reverseOrder)) {
1236 adjustCfg.reverseOrder = true;
1237 }
1238 }
1239 var adjustCtor = (0, adjust_1.getAdjust)(type);
1240 adjustCfg.dimValuesMap = {};
1241 //生成dimValuesMap
1242 if (xScale_2 && xScale_2.values) {
1243 adjustCfg.dimValuesMap[xScale_2.field] = xScale_2.values.map(function (v) { return xScale_2.translate(v); });
1244 }
1245 var adjustInstance = new adjustCtor(adjustCfg);
1246 result = adjustInstance.process(result);
1247 this.adjusts[type] = adjustInstance;
1248 }
1249 }
1250 return result;
1251 };
1252 // 对数据进行分组
1253 Geometry.prototype.groupData = function (data) {
1254 var groupScales = this.getGroupScales();
1255 var scaleDefs = this.scaleDefs;
1256 var appendConditions = {};
1257 var groupFields = [];
1258 for (var index = 0; index < groupScales.length; index++) {
1259 var scale = groupScales[index];
1260 var field = scale.field;
1261 groupFields.push(field);
1262 if ((0, util_1.get)(scaleDefs, [field, 'values'])) {
1263 // 用户通过 view.scale() 接口指定了 values 属性
1264 appendConditions[field] = scaleDefs[field].values;
1265 }
1266 }
1267 return (0, group_data_1.group)(data, groupFields, appendConditions);
1268 };
1269 // 更新发生层叠后的数据对应的度量范围
1270 Geometry.prototype.updateStackRange = function (scale, dataArray) {
1271 var mergeArray = (0, util_1.flatten)(dataArray);
1272 var field = scale.field;
1273 var min = scale.min;
1274 var max = scale.max;
1275 for (var index = 0; index < mergeArray.length; index++) {
1276 var obj = mergeArray[index];
1277 var tmpMin = Math.min.apply(null, obj[field]);
1278 var tmpMax = Math.max.apply(null, obj[field]);
1279 if (tmpMin < min) {
1280 min = tmpMin;
1281 }
1282 if (tmpMax > max) {
1283 max = tmpMax;
1284 }
1285 }
1286 var scaleDefs = this.scaleDefs;
1287 var cfg = {};
1288 if (min < scale.min && !(0, util_1.get)(scaleDefs, [field, 'min'])) {
1289 // 用户如果在列定义中定义了 min,则以用户定义的为准
1290 cfg.min = min;
1291 }
1292 if (max > scale.max && !(0, util_1.get)(scaleDefs, [field, 'max'])) {
1293 // 用户如果在列定义中定义了 max
1294 cfg.max = max;
1295 }
1296 scale.change(cfg);
1297 };
1298 // 将数据映射至图形空间前的操作:排序以及关键点的生成
1299 Geometry.prototype.beforeMapping = function (beforeMappingData) {
1300 // 当初加 clone 是因为 points 的引用关系,导致更新失败,可是现在貌似复现不出来了,所以暂时不进行 clone
1301 // const source = clone(beforeMappingData);
1302 var source = beforeMappingData;
1303 if (this.sortable) {
1304 this.sort(source);
1305 }
1306 if (this.generatePoints) {
1307 // 需要生成关键点
1308 for (var index = 0, length_5 = source.length; index < length_5; index++) {
1309 var currentData = source[index];
1310 this.generateShapePoints(currentData);
1311 var nextData = source[index + 1];
1312 if (nextData) {
1313 this.generateShapePoints(nextData);
1314 currentData[0].nextPoints = nextData[0].points;
1315 }
1316 }
1317 }
1318 return source;
1319 };
1320 // 生成 shape 的关键点
1321 Geometry.prototype.generateShapePoints = function (data) {
1322 var shapeFactory = this.getShapeFactory();
1323 var shapeAttr = this.getAttribute('shape');
1324 for (var index = 0; index < data.length; index++) {
1325 var obj = data[index];
1326 var cfg = this.createShapePointsCfg(obj);
1327 var shape = shapeAttr ? this.getAttributeValues(shapeAttr, obj) : null;
1328 var points = shapeFactory.getShapePoints(shape, cfg);
1329 obj.points = points;
1330 }
1331 };
1332 // 将数据归一化
1333 Geometry.prototype.normalizeValues = function (values, scale) {
1334 var rst = [];
1335 if ((0, util_1.isArray)(values)) {
1336 for (var index = 0; index < values.length; index++) {
1337 var value = values[index];
1338 rst.push(scale.scale(value));
1339 }
1340 }
1341 else {
1342 rst = scale.scale(values);
1343 }
1344 return rst;
1345 };
1346 // 将数据映射至图形空间
1347 Geometry.prototype.mapping = function (data) {
1348 var attributes = this.attributes;
1349 var mappingData = [];
1350 for (var index = 0; index < data.length; index++) {
1351 var record = data[index];
1352 var newRecord = {
1353 _origin: record[constant_1.FIELD_ORIGIN],
1354 points: record.points,
1355 nextPoints: record.nextPoints,
1356 };
1357 for (var k in attributes) {
1358 if (attributes.hasOwnProperty(k)) {
1359 var attr = attributes[k];
1360 var names = attr.names;
1361 var values = this.getAttributeValues(attr, record);
1362 if (names.length > 1) {
1363 // position 之类的生成多个字段的属性
1364 for (var j = 0; j < values.length; j += 1) {
1365 var val = values[j];
1366 var name_1 = names[j];
1367 newRecord[name_1] = (0, util_1.isArray)(val) && val.length === 1 ? val[0] : val; // 只有一个值时返回第一个属性值
1368 }
1369 }
1370 else {
1371 // values.length === 1 的判断是以下情况,获取用户设置的图形属性值
1372 // shape('a', ['dot', 'dash']), color('a', ['red', 'yellow'])
1373 newRecord[names[0]] = values.length === 1 ? values[0] : values;
1374 }
1375 }
1376 }
1377 this.convertPoint(newRecord); // 将 x、y 转换成画布坐标
1378 mappingData.push(newRecord);
1379 }
1380 return mappingData;
1381 };
1382 // 将归一化的坐标值转换成画布坐标
1383 Geometry.prototype.convertPoint = function (mappingRecord) {
1384 var x = mappingRecord.x, y = mappingRecord.y;
1385 var rstX;
1386 var rstY;
1387 var obj;
1388 var coordinate = this.coordinate;
1389 if ((0, util_1.isArray)(x) && (0, util_1.isArray)(y)) {
1390 rstX = [];
1391 rstY = [];
1392 for (var i = 0, j = 0, xLen = x.length, yLen = y.length; i < xLen && j < yLen; i += 1, j += 1) {
1393 obj = coordinate.convert({
1394 x: x[i],
1395 y: y[j],
1396 });
1397 rstX.push(obj.x);
1398 rstY.push(obj.y);
1399 }
1400 }
1401 else if ((0, util_1.isArray)(y)) {
1402 rstY = [];
1403 for (var index = 0; index < y.length; index++) {
1404 var yVal = y[index];
1405 obj = coordinate.convert({
1406 x: x,
1407 y: yVal,
1408 });
1409 if (rstX && rstX !== obj.x) {
1410 if (!(0, util_1.isArray)(rstX)) {
1411 rstX = [rstX];
1412 }
1413 rstX.push(obj.x);
1414 }
1415 else {
1416 rstX = obj.x;
1417 }
1418 rstY.push(obj.y);
1419 }
1420 }
1421 else if ((0, util_1.isArray)(x)) {
1422 rstX = [];
1423 for (var index = 0; index < x.length; index++) {
1424 var xVal = x[index];
1425 obj = coordinate.convert({
1426 x: xVal,
1427 y: y,
1428 });
1429 if (rstY && rstY !== obj.y) {
1430 if (!(0, util_1.isArray)(rstY)) {
1431 rstY = [rstY];
1432 }
1433 rstY.push(obj.y);
1434 }
1435 else {
1436 rstY = obj.y;
1437 }
1438 rstX.push(obj.x);
1439 }
1440 }
1441 else {
1442 var point = coordinate.convert({
1443 x: x,
1444 y: y,
1445 });
1446 rstX = point.x;
1447 rstY = point.y;
1448 }
1449 mappingRecord.x = rstX;
1450 mappingRecord.y = rstY;
1451 };
1452 // 获取 style 配置
1453 Geometry.prototype.getStyleCfg = function (styleOption, originData) {
1454 var _a = styleOption.fields, fields = _a === void 0 ? [] : _a, callback = styleOption.callback, cfg = styleOption.cfg;
1455 if (cfg) {
1456 // 用户直接配置样式属性
1457 return cfg;
1458 }
1459 var params = fields.map(function (field) {
1460 return originData[field];
1461 });
1462 return callback.apply(void 0, tslib_1.__spreadArray([], tslib_1.__read(params), false));
1463 };
1464 Geometry.prototype.setCfg = function (cfg) {
1465 var _this = this;
1466 var coordinate = cfg.coordinate, data = cfg.data, theme = cfg.theme, scaleDefs = cfg.scaleDefs;
1467 if (coordinate) {
1468 this.coordinate = coordinate;
1469 }
1470 if (data) {
1471 this.data = data;
1472 }
1473 if (scaleDefs) {
1474 this.scaleDefs = scaleDefs;
1475 this.idFields = [];
1476 (0, util_1.each)(scaleDefs, function (scaleDef, field) {
1477 if (scaleDef && scaleDef.key) {
1478 _this.idFields.push(field);
1479 }
1480 });
1481 }
1482 if (theme) {
1483 this.theme = this.userTheme ? (0, util_1.deepMix)({}, theme, this.userTheme) : theme; // 支持 geometry 层级的主题设置
1484 }
1485 };
1486 Geometry.prototype.renderLabels = function (mappingArray, isUpdate) {
1487 if (isUpdate === void 0) { isUpdate = false; }
1488 return tslib_1.__awaiter(this, void 0, void 0, function () {
1489 var geometryLabel, labelType, GeometryLabelsCtor, labelsMap, elementLabels, _a, _b, _c, element, labels;
1490 var e_5, _d;
1491 var _this = this;
1492 return tslib_1.__generator(this, function (_e) {
1493 switch (_e.label) {
1494 case 0:
1495 geometryLabel = this.geometryLabel;
1496 this.emit(constant_1.GEOMETRY_LIFE_CIRCLE.BEFORE_RENDER_LABEL);
1497 if (!geometryLabel) {
1498 labelType = this.getLabelType();
1499 GeometryLabelsCtor = (0, label_1.getGeometryLabel)(labelType);
1500 geometryLabel = new GeometryLabelsCtor(this);
1501 this.geometryLabel = geometryLabel;
1502 }
1503 return [4 /*yield*/, geometryLabel.render(mappingArray, isUpdate)];
1504 case 1:
1505 _e.sent();
1506 labelsMap = geometryLabel.labelsRenderer.shapesMap;
1507 elementLabels = new Map();
1508 (0, util_1.each)(labelsMap, function (labelGroup, labelGroupId) {
1509 var labelChildren = labelGroup.getChildren() || [];
1510 for (var j = 0; j < labelChildren.length; j++) {
1511 var labelShape = labelChildren[j];
1512 var element = _this.elementsMap[labelShape.get('elementId') || labelGroupId.split(' ')[0]];
1513 if (element) {
1514 labelShape.cfg.name = ['element', 'label'];
1515 labelShape.cfg.element = element;
1516 var labels = elementLabels.get(element) || new Set();
1517 labels.add(labelGroup);
1518 elementLabels.set(element, labels);
1519 }
1520 }
1521 });
1522 try {
1523 for (_a = tslib_1.__values(elementLabels.entries()), _b = _a.next(); !_b.done; _b = _a.next()) {
1524 _c = tslib_1.__read(_b.value, 2), element = _c[0], labels = _c[1];
1525 element.labelShape = tslib_1.__spreadArray([], tslib_1.__read(labels), false);
1526 }
1527 }
1528 catch (e_5_1) { e_5 = { error: e_5_1 }; }
1529 finally {
1530 try {
1531 if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
1532 }
1533 finally { if (e_5) throw e_5.error; }
1534 }
1535 this.emit(constant_1.GEOMETRY_LIFE_CIRCLE.AFTER_RENDER_LABEL);
1536 return [2 /*return*/];
1537 }
1538 });
1539 });
1540 };
1541 /**
1542 * 是否需要进行群组入场动画
1543 * 规则:
1544 * 1. 如果发生更新,则不进行
1545 * 2. 如果用户关闭 geometry 动画,则不进行
1546 * 3. 如果用户关闭了 appear 动画,则不进行
1547 * 4. 如果用户配置了 appear.animation,则不进行
1548 */
1549 Geometry.prototype.canDoGroupAnimation = function (isUpdate) {
1550 return (!isUpdate &&
1551 this.animateOption &&
1552 ((0, util_1.get)(this.animateOption, 'appear') === undefined ||
1553 ((0, util_1.get)(this.animateOption, 'appear') && (0, util_1.get)(this.animateOption, ['appear', 'animation']) === undefined)));
1554 };
1555 return Geometry;
1556}(base_1.default));
1557exports.default = Geometry;
1558//# sourceMappingURL=base.js.map
\No newline at end of file