1346 lines
49 KiB
Java
1346 lines
49 KiB
Java
import { __assign, __extends } from "tslib";
|
||
import { getAdjust as getAdjustClass } from '@antv/adjust';
|
||
import { getAttribute as getAttributeClass } from '@antv/attr';
|
||
import { clone, deepMix, each, flatten, get, isArray, isEmpty, isEqual, isFunction, isNil, isNumber, isObject, isPlainObject, isString, set, } from '@antv/util';
|
||
import { doGroupAppearAnimate, getDefaultAnimateCfg } from '../animate';
|
||
import Base from '../base';
|
||
import { FIELD_ORIGIN, GROUP_ATTRS } from '../constant';
|
||
import { uniq } from '../util/helper';
|
||
import Element from './element';
|
||
import { getGeometryLabel } from './label';
|
||
import { getShapeFactory } from './shape/base';
|
||
import { group } from './util/group-data';
|
||
import { isModelChange } from './util/is-model-change';
|
||
import { parseFields } from './util/parse-fields';
|
||
// 根据 elementId 查找对应的 label,因为有可能一个 element 对应多个 labels,所以在给 labels 打标识时做了处理
|
||
// 打标规则详见 ./label/base.ts#L263
|
||
function filterLabelsById(id, labelsMap) {
|
||
var labels = [];
|
||
each(labelsMap, function (label, labelId) {
|
||
var elementId = labelId.split(' ')[0];
|
||
if (elementId === id) {
|
||
labels.push(label);
|
||
}
|
||
});
|
||
return labels;
|
||
}
|
||
/**
|
||
* Geometry 几何标记基类,主要负责数据到图形属性的映射以及绘制逻辑。
|
||
*/
|
||
var Geometry = /** @class */ (function (_super) {
|
||
__extends(Geometry, _super);
|
||
/**
|
||
* 创建 Geometry 实例。
|
||
* @param cfg
|
||
*/
|
||
function Geometry(cfg) {
|
||
var _this = _super.call(this, cfg) || this;
|
||
/** Geometry 几何标记类型。 */
|
||
_this.type = 'base';
|
||
// 内部产生的属性
|
||
/** Attribute map */
|
||
_this.attributes = {};
|
||
/** Element map */
|
||
_this.elements = [];
|
||
/** 使用 key-value 结构存储 Element,key 为每个 Element 实例对应的唯一 ID */
|
||
_this.elementsMap = {};
|
||
/** animate 配置项 */
|
||
_this.animateOption = true;
|
||
/** 图形属性映射配置 */
|
||
_this.attributeOption = {};
|
||
/** 存储上一次渲染时的 element 映射表,用于更新逻辑 */
|
||
_this.lastElementsMap = {};
|
||
/** 是否生成多个点来绘制图形。 */
|
||
_this.generatePoints = false;
|
||
/** 存储发生图形属性映射前的数据 */
|
||
_this.beforeMappingData = null;
|
||
_this.adjusts = {};
|
||
_this.idFields = [];
|
||
_this.hasSorted = false;
|
||
_this.isCoordinateChanged = false;
|
||
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;
|
||
_this.container = container;
|
||
_this.labelsContainer = labelsContainer;
|
||
_this.coordinate = coordinate;
|
||
_this.data = data;
|
||
_this.sortable = sortable;
|
||
_this.visible = visible;
|
||
_this.userTheme = theme;
|
||
_this.scales = scales;
|
||
_this.scaleDefs = scaleDefs;
|
||
return _this;
|
||
}
|
||
/**
|
||
* 配置 position 通道映射规则。
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* // 数据结构: [{ x: 'A', y: 10, color: 'red' }]
|
||
* geometry.position('x*y');
|
||
* geometry.position([ 'x', 'y' ]);
|
||
* geometry.position({
|
||
* fields: [ 'x', 'y' ],
|
||
* });
|
||
* ```
|
||
*
|
||
* @param cfg 映射规则
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.position = function (cfg) {
|
||
var positionCfg = cfg;
|
||
if (!isPlainObject(cfg)) {
|
||
// 字符串字段或者数组字段
|
||
positionCfg = {
|
||
fields: parseFields(cfg),
|
||
};
|
||
}
|
||
var fields = get(positionCfg, 'fields');
|
||
if (fields.length === 1) {
|
||
// 默认填充一维 1*xx
|
||
fields.unshift('1');
|
||
set(positionCfg, 'fields', fields);
|
||
}
|
||
set(this.attributeOption, 'position', positionCfg);
|
||
return this;
|
||
};
|
||
Geometry.prototype.color = function (field, cfg) {
|
||
this.createAttrOption('color', field, cfg);
|
||
return this;
|
||
};
|
||
Geometry.prototype.shape = function (field, cfg) {
|
||
this.createAttrOption('shape', field, cfg);
|
||
return this;
|
||
};
|
||
Geometry.prototype.size = function (field, cfg) {
|
||
this.createAttrOption('size', field, cfg);
|
||
return this;
|
||
};
|
||
/**
|
||
* 设置数据调整方式。G2 目前内置了四种类型:
|
||
* 1. dodge
|
||
* 2. stack
|
||
* 3. symmetric
|
||
* 4. jitter
|
||
*
|
||
*
|
||
* **Tip**
|
||
* + 对于 'dodge' 类型,可以额外进行如下属性的配置:
|
||
* ```typescript
|
||
* geometry.adjust('dodge', {
|
||
* marginRatio: 0, // 取 0 到 1 范围的值(相对于每个柱子宽度),用于控制一个分组中柱子之间的间距
|
||
* dodgeBy: 'x', // 该属性只对 'dodge' 类型生效,声明以哪个数据字段为分组依据
|
||
* });
|
||
* ```
|
||
*
|
||
* + 对于 'stack' 类型,可以额外进行如下属性的配置:
|
||
* ```typescript
|
||
* geometry.adjust('stack', {
|
||
* reverseOrder: false, // 用于控制是否对数据进行反序操作
|
||
* });
|
||
* ```
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* geometry.adjust('stack');
|
||
*
|
||
* geometry.adjust({
|
||
* type: 'stack',
|
||
* reverseOrder: false,
|
||
* });
|
||
*
|
||
* // 组合使用 adjust
|
||
* geometry.adjust([ 'stack', 'dodge' ]);
|
||
*
|
||
* geometry.adjust([
|
||
* { type: 'stack' },
|
||
* { type: 'dodge', dodgeBy: 'x' },
|
||
* ]);
|
||
* ```
|
||
*
|
||
* @param adjustCfg 数据调整配置
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.adjust = function (adjustCfg) {
|
||
var adjusts = adjustCfg;
|
||
if (isString(adjustCfg) || isPlainObject(adjustCfg)) {
|
||
adjusts = [adjustCfg];
|
||
}
|
||
each(adjusts, function (adjust, index) {
|
||
if (!isObject(adjust)) {
|
||
adjusts[index] = { type: adjust };
|
||
}
|
||
});
|
||
this.adjustOption = adjusts;
|
||
return this;
|
||
};
|
||
Geometry.prototype.style = function (field, styleFunc) {
|
||
if (isString(field)) {
|
||
var fields = parseFields(field);
|
||
this.styleOption = {
|
||
fields: fields,
|
||
callback: styleFunc,
|
||
};
|
||
}
|
||
else {
|
||
var _a = field, fields = _a.fields, callback = _a.callback, cfg = _a.cfg;
|
||
if (fields || callback || cfg) {
|
||
this.styleOption = field;
|
||
}
|
||
else {
|
||
this.styleOption = {
|
||
cfg: field,
|
||
};
|
||
}
|
||
}
|
||
return this;
|
||
};
|
||
Geometry.prototype.tooltip = function (field, cfg) {
|
||
if (isString(field)) {
|
||
var fields = parseFields(field);
|
||
this.tooltipOption = {
|
||
fields: fields,
|
||
callback: cfg,
|
||
};
|
||
}
|
||
else {
|
||
this.tooltipOption = field;
|
||
}
|
||
return this;
|
||
};
|
||
/**
|
||
* Geometry 动画配置。
|
||
*
|
||
* + `animate(false)` 关闭动画
|
||
* + `animate(true)` 开启动画,默认开启。
|
||
*
|
||
* 我们将动画分为四个场景:
|
||
* 1. appear: 图表第一次加载时的入场动画;
|
||
* 2. enter: 图表绘制完成,发生更新后,产生的新图形的进场动画;
|
||
* 3. update: 图表绘制完成,数据发生变更后,有状态变更的图形的更新动画;
|
||
* 4. leave: 图表绘制完成,数据发生变更后,被销毁图形的销毁动画。
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* animate({
|
||
* enter: {
|
||
* duration: 1000, // enter 动画执行时间
|
||
* },
|
||
* leave: false, // 关闭 leave 销毁动画
|
||
* });
|
||
* ```
|
||
*
|
||
* @param cfg 动画配置
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.animate = function (cfg) {
|
||
this.animateOption = cfg;
|
||
return this;
|
||
};
|
||
Geometry.prototype.label = function (field, secondParam, thirdParam) {
|
||
if (isString(field)) {
|
||
var labelOption = {};
|
||
var fields = parseFields(field);
|
||
labelOption.fields = fields;
|
||
if (isFunction(secondParam)) {
|
||
labelOption.callback = secondParam;
|
||
}
|
||
else if (isPlainObject(secondParam)) {
|
||
labelOption.cfg = secondParam;
|
||
}
|
||
if (thirdParam) {
|
||
labelOption.cfg = thirdParam;
|
||
}
|
||
this.labelOption = labelOption;
|
||
}
|
||
else {
|
||
this.labelOption = field;
|
||
}
|
||
return this;
|
||
};
|
||
/**
|
||
* 设置状态对应的样式。
|
||
*
|
||
* @example
|
||
* ```ts
|
||
* chart.interval().state({
|
||
* selected: {
|
||
* animate: { duration: 100, easing: 'easeLinear' },
|
||
* style: {
|
||
* lineWidth: 2,
|
||
* stroke: '#000',
|
||
* },
|
||
* },
|
||
* });
|
||
* ```
|
||
*
|
||
* 如果图形 shape 是由多个 shape 组成,即为一个 G.Group 对象,那么针对 group 中的每个 shape,我们需要使用下列方式进行状态样式设置:
|
||
* 如果我们为 group 中的每个 shape 设置了 'name' 属性(shape.set('name', 'xx')),则以 'name' 作为 key,否则默认以索引值(即 shape 的 添加顺序)为 key。
|
||
*
|
||
* ```ts
|
||
* chart.interval().shape('groupShape').state({
|
||
* selected: {
|
||
* style: {
|
||
* 0: { lineWidth: 2 },
|
||
* 1: { fillOpacity: 1 },
|
||
* }
|
||
* }
|
||
* });
|
||
* ```
|
||
*
|
||
* @param cfg 状态样式
|
||
*/
|
||
Geometry.prototype.state = function (cfg) {
|
||
this.stateOption = cfg;
|
||
return this;
|
||
};
|
||
/**
|
||
* 初始化 Geomtry 实例:
|
||
* 创建 [[Attribute]] and [[Scale]] 实例,进行数据处理,包括分组、数值化以及数据调整。
|
||
*/
|
||
Geometry.prototype.init = function (cfg) {
|
||
if (cfg === void 0) { cfg = {}; }
|
||
this.setCfg(cfg);
|
||
this.initAttributes(); // 创建图形属性
|
||
// 数据加工:分组 -> 数字化 -> adjust
|
||
this.processData(this.data);
|
||
// 调整 scale
|
||
this.adjustScale();
|
||
};
|
||
/**
|
||
* Geometry 更新。
|
||
* @param [cfg] 更新的配置
|
||
*/
|
||
Geometry.prototype.update = function (cfg) {
|
||
if (cfg === void 0) { cfg = {}; }
|
||
var data = cfg.data, isDataChanged = cfg.isDataChanged, isCoordinateChanged = cfg.isCoordinateChanged;
|
||
var _a = this, attributeOption = _a.attributeOption, lastAttributeOption = _a.lastAttributeOption;
|
||
if (!isEqual(attributeOption, lastAttributeOption)) {
|
||
// 映射发生改变,则重新创建图形属性
|
||
this.init(cfg);
|
||
}
|
||
else if (data && (isDataChanged || !isEqual(data, this.data))) {
|
||
// 数据发生变化
|
||
this.setCfg(cfg);
|
||
this.processData(data); // 数据加工:分组 -> 数字化 -> adjust
|
||
}
|
||
else {
|
||
// 有可能 coordinate 变化
|
||
this.setCfg(cfg);
|
||
}
|
||
// 调整 scale
|
||
this.adjustScale();
|
||
this.isCoordinateChanged = isCoordinateChanged;
|
||
};
|
||
/**
|
||
* 将原始数据映射至图形空间,同时创建图形对象。
|
||
*/
|
||
Geometry.prototype.paint = function (isUpdate) {
|
||
var _this = this;
|
||
if (isUpdate === void 0) { isUpdate = false; }
|
||
if (this.animateOption) {
|
||
this.animateOption = deepMix({}, getDefaultAnimateCfg(this.type, this.coordinate), this.animateOption);
|
||
}
|
||
this.defaultSize = undefined;
|
||
this.elements = [];
|
||
this.elementsMap = {};
|
||
var offscreenGroup = this.getOffscreenGroup();
|
||
offscreenGroup.clear();
|
||
var beforeMappingData = this.beforeMappingData;
|
||
var dataArray = this.beforeMapping(beforeMappingData);
|
||
var mappingArray = [];
|
||
for (var index = 0, length_1 = dataArray.length; index < length_1; index++) {
|
||
var eachGroup = dataArray[index];
|
||
var mappingData = this.mapping(eachGroup);
|
||
mappingArray.push(mappingData);
|
||
this.createElements(mappingData, index, isUpdate);
|
||
}
|
||
if (this.canDoGroupAnimation(isUpdate)) {
|
||
// 如果用户没有配置 appear.animation,就默认走整体动画
|
||
var container = this.container;
|
||
var type = this.type;
|
||
var coordinate = this.coordinate;
|
||
var animateCfg = get(this.animateOption, 'appear');
|
||
var yScale = this.getYScale();
|
||
var yMinPoint = coordinate.convert({
|
||
x: 0,
|
||
y: yScale.scale(this.getYMinValue()),
|
||
});
|
||
doGroupAppearAnimate(container, animateCfg, type, coordinate, yMinPoint);
|
||
}
|
||
// 添加 label
|
||
if (this.labelOption) {
|
||
this.renderLabels(flatten(mappingArray), isUpdate);
|
||
}
|
||
this.dataArray = mappingArray;
|
||
// 销毁被删除的 elements
|
||
each(this.lastElementsMap, function (deletedElement) {
|
||
// 更新动画配置,用户有可能在更新之前有对动画进行配置操作
|
||
deletedElement.animate = _this.animateOption;
|
||
deletedElement.destroy();
|
||
});
|
||
this.lastElementsMap = this.elementsMap;
|
||
// 缓存,用于更新
|
||
this.lastAttributeOption = __assign({}, this.attributeOption);
|
||
if (this.visible === false) {
|
||
// 用户在初始化的时候声明 visible: false
|
||
this.changeVisible(false);
|
||
}
|
||
};
|
||
/**
|
||
* 清空当前 Geometry,配置项仍保留,但是内部创建的对象全部清空。
|
||
* @override
|
||
*/
|
||
Geometry.prototype.clear = function () {
|
||
var _a = this, container = _a.container, geometryLabel = _a.geometryLabel, offscreenGroup = _a.offscreenGroup;
|
||
if (container) {
|
||
container.clear();
|
||
}
|
||
if (geometryLabel) {
|
||
geometryLabel.clear();
|
||
}
|
||
if (offscreenGroup) {
|
||
offscreenGroup.clear();
|
||
}
|
||
// 属性恢复至出厂状态
|
||
this.scaleDefs = undefined;
|
||
this.attributes = {};
|
||
this.scales = {};
|
||
this.elementsMap = {};
|
||
this.lastElementsMap = {};
|
||
this.elements = [];
|
||
this.adjusts = {};
|
||
this.dataArray = null;
|
||
this.beforeMappingData = null;
|
||
this.lastAttributeOption = undefined;
|
||
this.defaultSize = undefined;
|
||
this.idFields = [];
|
||
this.groupScales = undefined;
|
||
this.hasSorted = false;
|
||
this.isCoordinateChanged = false;
|
||
};
|
||
/**
|
||
* 销毁 Geometry 实例。
|
||
*/
|
||
Geometry.prototype.destroy = function () {
|
||
this.clear();
|
||
var container = this.container;
|
||
container.remove(true);
|
||
if (this.offscreenGroup) {
|
||
this.offscreenGroup.remove(true);
|
||
this.offscreenGroup = null;
|
||
}
|
||
if (this.geometryLabel) {
|
||
this.geometryLabel.destroy();
|
||
this.geometryLabel = null;
|
||
}
|
||
this.theme = undefined;
|
||
this.shapeFactory = undefined;
|
||
_super.prototype.destroy.call(this);
|
||
};
|
||
/**
|
||
* 获取决定分组的图形属性对应的 scale 实例。
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getGroupScales = function () {
|
||
return this.groupScales;
|
||
};
|
||
/**
|
||
* 根据名字获取图形属性实例。
|
||
*/
|
||
Geometry.prototype.getAttribute = function (name) {
|
||
return this.attributes[name];
|
||
};
|
||
/** 获取 x 轴对应的 scale 实例。 */
|
||
Geometry.prototype.getXScale = function () {
|
||
return this.getAttribute('position').scales[0];
|
||
};
|
||
/** 获取 y 轴对应的 scale 实例。 */
|
||
Geometry.prototype.getYScale = function () {
|
||
return this.getAttribute('position').scales[1];
|
||
};
|
||
/**
|
||
* 获取决定分组的图形属性实例。
|
||
*/
|
||
Geometry.prototype.getGroupAttributes = function () {
|
||
var rst = [];
|
||
each(this.attributes, function (attr) {
|
||
if (GROUP_ATTRS.includes(attr.type)) {
|
||
rst.push(attr);
|
||
}
|
||
});
|
||
return rst;
|
||
};
|
||
/** 获取图形属性默认的映射值。 */
|
||
Geometry.prototype.getDefaultValue = function (attrName) {
|
||
var value;
|
||
var attr = this.getAttribute(attrName);
|
||
if (attr && isEmpty(attr.scales)) {
|
||
// 获取映射至常量的值
|
||
value = attr.values[0];
|
||
}
|
||
return value;
|
||
};
|
||
/**
|
||
* 获取该数据发生图形映射后对应的 Attribute 图形空间数据。
|
||
* @param attr Attribute 图形属性实例。
|
||
* @param obj 需要进行映射的原始数据。
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getAttributeValues = function (attr, obj) {
|
||
var params = [];
|
||
var scales = attr.scales;
|
||
for (var index = 0, length_2 = scales.length; index < length_2; index++) {
|
||
var scale = scales[index];
|
||
var field = scale.field;
|
||
if (scale.isIdentity) {
|
||
params.push(scale.values);
|
||
}
|
||
else {
|
||
params.push(obj[field]);
|
||
}
|
||
}
|
||
return attr.mapping.apply(attr, params);
|
||
};
|
||
Geometry.prototype.getAdjust = function (adjustType) {
|
||
return this.adjusts[adjustType];
|
||
};
|
||
/**
|
||
* 获取 shape 对应的 marker 样式。
|
||
* @param shapeName shape 具体名字
|
||
* @param cfg marker 信息
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getShapeMarker = function (shapeName, cfg) {
|
||
var shapeFactory = this.getShapeFactory();
|
||
return shapeFactory.getMarker(shapeName, cfg);
|
||
};
|
||
/**
|
||
* 根据一定的规则查找 Geometry 的 Elements。
|
||
*
|
||
* ```typescript
|
||
* getElementsBy((element) => {
|
||
* const data = element.getData();
|
||
*
|
||
* return data.a === 'a';
|
||
* });
|
||
* ```
|
||
*
|
||
* @param condition 定义查找规则的回调函数。
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getElementsBy = function (condition) {
|
||
return this.elements.filter(function (element) {
|
||
return condition(element);
|
||
});
|
||
};
|
||
/**
|
||
* 获取数据对应的唯一 id。
|
||
* @param data Element 对应的绘制数据
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getElementId = function (data) {
|
||
data = isArray(data) ? data[0] : data;
|
||
var originData = data[FIELD_ORIGIN];
|
||
// 如果用户声明了使用哪些字段作为 id 值
|
||
if (this.idFields.length) {
|
||
var elementId = originData[this.idFields[0]];
|
||
for (var index = 1; index < this.idFields.length; index++) {
|
||
elementId += '-' + originData[this.idFields[index]];
|
||
}
|
||
return elementId;
|
||
}
|
||
var type = this.type;
|
||
var xScale = this.getXScale();
|
||
var yScale = this.getYScale();
|
||
var xField = xScale.field || 'x';
|
||
var yField = yScale.field || 'y';
|
||
var yVal = originData[yField];
|
||
var xVal;
|
||
if (xScale.type === 'identity') {
|
||
xVal = xScale.values[0];
|
||
}
|
||
else {
|
||
xVal = originData[xField];
|
||
}
|
||
var id;
|
||
if (type === 'interval' || type === 'schema') {
|
||
id = xVal;
|
||
}
|
||
else if (type === 'line' || type === 'area' || type === 'path') {
|
||
id = type;
|
||
}
|
||
else {
|
||
id = xVal + "-" + yVal;
|
||
}
|
||
var groupScales = this.groupScales;
|
||
for (var index = 0, length_3 = groupScales.length; index < length_3; index++) {
|
||
var groupScale = groupScales[index];
|
||
var field = groupScale.field;
|
||
id = id + "-" + originData[field];
|
||
}
|
||
// 用户在进行 dodge 类型的 adjust 调整的时候设置了 dodgeBy 属性
|
||
var dodgeAdjust = this.getAdjust('dodge');
|
||
if (dodgeAdjust) {
|
||
var dodgeBy = dodgeAdjust.dodgeBy;
|
||
if (dodgeBy) {
|
||
id = id + "-" + originData[dodgeBy];
|
||
}
|
||
}
|
||
if (this.getAdjust('jitter')) {
|
||
id = id + "-" + data.x + "-" + data.y;
|
||
}
|
||
return id;
|
||
};
|
||
/**
|
||
* 获取所有需要创建 scale 的字段名称。
|
||
*/
|
||
Geometry.prototype.getScaleFields = function () {
|
||
var fields = [];
|
||
var tmpMap = {};
|
||
var _a = this, attributeOption = _a.attributeOption, labelOption = _a.labelOption, tooltipOption = _a.tooltipOption;
|
||
// 获取图形属性上的 fields
|
||
for (var attributeType in attributeOption) {
|
||
if (attributeOption.hasOwnProperty(attributeType)) {
|
||
var eachOpt = attributeOption[attributeType];
|
||
if (eachOpt.fields) {
|
||
uniq(eachOpt.fields, fields, tmpMap);
|
||
}
|
||
else if (eachOpt.values) {
|
||
// 考虑 size(10), shape('circle') 等场景
|
||
uniq(eachOpt.values, fields, tmpMap);
|
||
}
|
||
}
|
||
}
|
||
// 获取 label 上的字段
|
||
if (labelOption && labelOption.fields) {
|
||
uniq(labelOption.fields, fields, tmpMap);
|
||
}
|
||
// 获取 tooltip 上的字段
|
||
if (isObject(tooltipOption) && tooltipOption.fields) {
|
||
uniq(tooltipOption.fields, fields, tmpMap);
|
||
}
|
||
return fields;
|
||
};
|
||
/**
|
||
* 显示或者隐藏 geometry。
|
||
* @param visible
|
||
*/
|
||
Geometry.prototype.changeVisible = function (visible) {
|
||
_super.prototype.changeVisible.call(this, visible);
|
||
var elements = this.elements;
|
||
for (var index = 0, length_4 = elements.length; index < length_4; index++) {
|
||
var element = elements[index];
|
||
element.changeVisible(visible);
|
||
}
|
||
if (visible) {
|
||
if (this.container) {
|
||
this.container.show();
|
||
}
|
||
if (this.labelsContainer) {
|
||
this.labelsContainer.show();
|
||
}
|
||
}
|
||
else {
|
||
if (this.container) {
|
||
this.container.hide();
|
||
}
|
||
if (this.labelsContainer) {
|
||
this.labelsContainer.hide();
|
||
}
|
||
}
|
||
};
|
||
/**
|
||
* 获取当前配置中的所有分组 & 分类的字段。
|
||
* @return fields string[]
|
||
*/
|
||
Geometry.prototype.getGroupFields = function () {
|
||
var groupFields = [];
|
||
var tmpMap = {}; // 用于去重过滤
|
||
for (var index = 0, length_5 = GROUP_ATTRS.length; index < length_5; index++) {
|
||
var attributeName = GROUP_ATTRS[index];
|
||
var cfg = this.attributeOption[attributeName];
|
||
if (cfg && cfg.fields) {
|
||
uniq(cfg.fields, groupFields, tmpMap);
|
||
}
|
||
}
|
||
return groupFields;
|
||
};
|
||
/**
|
||
* 获得图形的 x y 字段。
|
||
*/
|
||
Geometry.prototype.getXYFields = function () {
|
||
var _a = this.attributeOption.position.fields, x = _a[0], y = _a[1];
|
||
return [x, y];
|
||
};
|
||
/**
|
||
* 获取该 Geometry 下所有生成的 shapes。
|
||
* @returns shapes
|
||
*/
|
||
Geometry.prototype.getShapes = function () {
|
||
return this.elements.map(function (element) { return element.shape; });
|
||
};
|
||
/**
|
||
* 获取虚拟 Group。
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.getOffscreenGroup = function () {
|
||
if (!this.offscreenGroup) {
|
||
var GroupCtor = this.container.getGroupBase(); // 获取分组的构造函数
|
||
this.offscreenGroup = new GroupCtor({});
|
||
}
|
||
return this.offscreenGroup;
|
||
};
|
||
// 对数据进行排序
|
||
Geometry.prototype.sort = function (mappingArray) {
|
||
if (!this.hasSorted) {
|
||
// 未发生过排序
|
||
var xScale_1 = this.getXScale();
|
||
var xField_1 = xScale_1.field;
|
||
for (var index = 0; index < mappingArray.length; index++) {
|
||
var itemArr = mappingArray[index];
|
||
itemArr.sort(function (obj1, obj2) {
|
||
return xScale_1.translate(obj1[FIELD_ORIGIN][xField_1]) - xScale_1.translate(obj2[FIELD_ORIGIN][xField_1]);
|
||
});
|
||
}
|
||
;
|
||
}
|
||
this.hasSorted = true;
|
||
};
|
||
/**
|
||
* 调整度量范围。主要针对发生层叠以及一些特殊需求的 Geometry,比如 Interval 下的柱状图 Y 轴默认从 0 开始。
|
||
*/
|
||
Geometry.prototype.adjustScale = function () {
|
||
var yScale = this.getYScale();
|
||
// 如果数据发生过 stack adjust,需要调整下 yScale 的数据范围
|
||
if (yScale && this.getAdjust('stack')) {
|
||
this.updateStackRange(yScale, this.beforeMappingData);
|
||
}
|
||
};
|
||
/**
|
||
* 获取当前 Geometry 对应的 Shape 工厂实例。
|
||
*/
|
||
Geometry.prototype.getShapeFactory = function () {
|
||
var shapeType = this.shapeType;
|
||
if (!getShapeFactory(shapeType)) {
|
||
return;
|
||
}
|
||
if (!this.shapeFactory) {
|
||
this.shapeFactory = clone(getShapeFactory(shapeType)); // 防止多个 view 共享一个 shapeFactory 实例,导致 coordinate 被篡改
|
||
}
|
||
// 因为这里缓存了 shapeFactory,但是外部可能会变更 coordinate,导致无法重新设置到 shapeFactory 中
|
||
this.shapeFactory.coordinate = this.coordinate;
|
||
// theme 原因同上
|
||
this.shapeFactory.theme = this.theme.geometries[shapeType] || {};
|
||
return this.shapeFactory;
|
||
};
|
||
/**
|
||
* 获取每个 Shape 对应的关键点数据。
|
||
* @param obj 经过分组 -> 数字化 -> adjust 调整后的数据记录
|
||
* @returns
|
||
*/
|
||
Geometry.prototype.createShapePointsCfg = function (obj) {
|
||
var xScale = this.getXScale();
|
||
var yScale = this.getYScale();
|
||
var x = this.normalizeValues(obj[xScale.field], xScale);
|
||
var y; // 存在没有 y 的情况
|
||
if (yScale) {
|
||
y = this.normalizeValues(obj[yScale.field], yScale);
|
||
}
|
||
else {
|
||
y = obj.y ? obj.y : 0.1;
|
||
}
|
||
return {
|
||
x: x,
|
||
y: y,
|
||
y0: yScale ? yScale.scale(this.getYMinValue()) : undefined,
|
||
};
|
||
};
|
||
/**
|
||
* 创建 Element 实例。
|
||
* @param mappingDatum Element 对应的绘制数据
|
||
* @param [isUpdate] 是否处于更新阶段
|
||
* @returns element 返回创建的 Element 实例
|
||
*/
|
||
Geometry.prototype.createElement = function (mappingDatum, isUpdate) {
|
||
if (isUpdate === void 0) { isUpdate = false; }
|
||
var container = this.container;
|
||
var shapeCfg = this.getDrawCfg(mappingDatum); // 获取绘制图形的配置信息
|
||
var shapeFactory = this.getShapeFactory();
|
||
var element = new Element({
|
||
shapeFactory: shapeFactory,
|
||
container: container,
|
||
offscreenGroup: this.getOffscreenGroup(),
|
||
});
|
||
element.animate = this.animateOption;
|
||
element.geometry = this;
|
||
element.draw(shapeCfg, isUpdate); // 绘制
|
||
return element;
|
||
};
|
||
/**
|
||
* 获取每条数据对应的图形绘制数据。
|
||
* @param mappingDatum 映射后的数据
|
||
* @returns draw cfg
|
||
*/
|
||
Geometry.prototype.getDrawCfg = function (mappingDatum) {
|
||
var originData = mappingDatum[FIELD_ORIGIN]; // 原始数据
|
||
var cfg = {
|
||
mappingData: mappingDatum,
|
||
data: originData,
|
||
x: mappingDatum.x,
|
||
y: mappingDatum.y,
|
||
color: mappingDatum.color,
|
||
size: mappingDatum.size,
|
||
isInCircle: this.coordinate.isPolar,
|
||
};
|
||
var shapeName = mappingDatum.shape;
|
||
if (!shapeName && this.getShapeFactory()) {
|
||
shapeName = this.getShapeFactory().defaultShapeType;
|
||
}
|
||
cfg.shape = shapeName;
|
||
// 获取默认样式
|
||
var theme = this.theme.geometries[this.shapeType];
|
||
cfg.defaultStyle = get(theme, [shapeName, 'default'], {}).style;
|
||
var styleOption = this.styleOption;
|
||
if (styleOption) {
|
||
cfg.style = this.getStyleCfg(styleOption, originData);
|
||
}
|
||
if (this.generatePoints) {
|
||
cfg.points = mappingDatum.points;
|
||
cfg.nextPoints = mappingDatum.nextPoints;
|
||
}
|
||
return cfg;
|
||
};
|
||
/**
|
||
* 创建所有的 Elements。
|
||
* @param mappingData
|
||
* @param [isUpdate]
|
||
* @returns elements
|
||
*/
|
||
Geometry.prototype.createElements = function (mappingData, index, isUpdate) {
|
||
if (isUpdate === void 0) { isUpdate = false; }
|
||
var _a = this, lastElementsMap = _a.lastElementsMap, elementsMap = _a.elementsMap, elements = _a.elements;
|
||
for (var subIndex = 0, length_6 = mappingData.length; subIndex < length_6; subIndex++) {
|
||
var mappingDatum = mappingData[subIndex];
|
||
var id = this.getElementId(mappingDatum);
|
||
if (elementsMap[id]) {
|
||
// 存在重复数据,则根据再根据 index 进行区分
|
||
id = id + "-" + index + "-" + subIndex;
|
||
}
|
||
var result = lastElementsMap[id];
|
||
if (!result) {
|
||
// 创建新的 element
|
||
result = this.createElement(mappingDatum, isUpdate);
|
||
}
|
||
else {
|
||
// element 已经创建
|
||
var currentShapeCfg = this.getDrawCfg(mappingDatum);
|
||
var preShapeCfg = result.getModel();
|
||
if (this.isCoordinateChanged || isModelChange(currentShapeCfg, preShapeCfg)) {
|
||
result.animate = this.animateOption;
|
||
// 通过绘制数据的变更来判断是否需要更新,因为用户有可能会修改图形属性映射
|
||
result.update(currentShapeCfg); // 更新对应的 element
|
||
}
|
||
delete lastElementsMap[id];
|
||
}
|
||
elements.push(result);
|
||
elementsMap[id] = result;
|
||
}
|
||
return elements;
|
||
};
|
||
/**
|
||
* 获取渲染的 label 类型。
|
||
*/
|
||
Geometry.prototype.getLabelType = function () {
|
||
var _a = this, labelOption = _a.labelOption, coordinate = _a.coordinate, type = _a.type;
|
||
var coordinateType = coordinate.type;
|
||
var labelType = get(labelOption, ['cfg', 'type']);
|
||
if (!labelType) {
|
||
// 用户未定义,则进行默认的逻辑
|
||
if (coordinateType === 'polar') {
|
||
// 极坐标下使用通用的极坐标文本
|
||
labelType = 'polar';
|
||
}
|
||
else if (coordinateType === 'theta') {
|
||
// theta 坐标系下使用饼图文本
|
||
labelType = 'pie';
|
||
}
|
||
else if (type === 'interval' || type === 'polygon') {
|
||
labelType = 'interval';
|
||
}
|
||
else {
|
||
labelType = 'base';
|
||
}
|
||
}
|
||
return labelType;
|
||
};
|
||
/**
|
||
* 获取 Y 轴上的最小值。
|
||
*/
|
||
Geometry.prototype.getYMinValue = function () {
|
||
var yScale = this.getYScale();
|
||
var min = yScale.min, max = yScale.max;
|
||
var value;
|
||
if (min >= 0) {
|
||
value = min;
|
||
}
|
||
else if (max <= 0) {
|
||
// 当值全位于负区间时,需要保证 ymin 在区域内,不可为 0
|
||
value = max;
|
||
}
|
||
else {
|
||
value = 0;
|
||
}
|
||
return value;
|
||
};
|
||
// 创建图形属性相关的配置项
|
||
Geometry.prototype.createAttrOption = function (attrName, field, cfg) {
|
||
if (isNil(field) || isObject(field)) {
|
||
if (isObject(field) && isEqual(Object.keys(field), ['values'])) {
|
||
// shape({ values: [ 'funnel' ] })
|
||
set(this.attributeOption, attrName, {
|
||
fields: field.values,
|
||
});
|
||
}
|
||
else {
|
||
set(this.attributeOption, attrName, field);
|
||
}
|
||
}
|
||
else {
|
||
var attrCfg = {};
|
||
if (isNumber(field)) {
|
||
// size(3)
|
||
attrCfg.values = [field];
|
||
}
|
||
else {
|
||
attrCfg.fields = parseFields(field);
|
||
}
|
||
if (cfg) {
|
||
if (isFunction(cfg)) {
|
||
attrCfg.callback = cfg;
|
||
}
|
||
else {
|
||
attrCfg.values = cfg;
|
||
}
|
||
}
|
||
set(this.attributeOption, attrName, attrCfg);
|
||
}
|
||
};
|
||
Geometry.prototype.initAttributes = function () {
|
||
var _this = this;
|
||
var _a = this, attributes = _a.attributes, attributeOption = _a.attributeOption, theme = _a.theme, shapeType = _a.shapeType;
|
||
this.groupScales = [];
|
||
var tmpMap = {};
|
||
var _loop_1 = function (attrType) {
|
||
if (attributeOption.hasOwnProperty(attrType)) {
|
||
var option = attributeOption[attrType];
|
||
if (!option) {
|
||
return { value: void 0 };
|
||
}
|
||
var attrCfg = __assign({}, option);
|
||
var callback = attrCfg.callback, values = attrCfg.values, _a = attrCfg.fields, fields = _a === void 0 ? [] : _a;
|
||
// 获取每一个字段对应的 scale
|
||
var scales = fields.map(function (field) {
|
||
var scale = _this.scales[field];
|
||
if (scale.isCategory && !tmpMap[field] && GROUP_ATTRS.includes(attrType)) {
|
||
_this.groupScales.push(scale);
|
||
tmpMap[field] = true;
|
||
}
|
||
return scale;
|
||
});
|
||
attrCfg.scales = scales;
|
||
if (attrType !== 'position' && scales.length === 1 && scales[0].type === 'identity') {
|
||
// 用户在图形通道上声明了常量字段 color('red'), size(5)
|
||
attrCfg.values = scales[0].values;
|
||
}
|
||
else if (!callback && !values) {
|
||
// 用户没有指定任何规则,则使用默认的映射规则
|
||
if (attrType === 'size') {
|
||
attrCfg.values = theme.sizes;
|
||
}
|
||
else if (attrType === 'shape') {
|
||
attrCfg.values = theme.shapes[shapeType] || [];
|
||
}
|
||
else if (attrType === 'color') {
|
||
if (scales.length) {
|
||
// 根据数值个数使用对应的色板
|
||
attrCfg.values = scales[0].values.length <= 10 ? theme.colors10 : theme.colors20;
|
||
}
|
||
else {
|
||
attrCfg.values = theme.colors10;
|
||
}
|
||
}
|
||
}
|
||
var AttributeCtor = getAttributeClass(attrType);
|
||
attributes[attrType] = new AttributeCtor(attrCfg);
|
||
}
|
||
};
|
||
// 遍历每一个 attrOption,各自创建 Attribute 实例
|
||
for (var attrType in attributeOption) {
|
||
var state_1 = _loop_1(attrType);
|
||
if (typeof state_1 === "object")
|
||
return state_1.value;
|
||
}
|
||
};
|
||
// 处理数据:分组 -> 数字化 -> adjust 调整
|
||
Geometry.prototype.processData = function (data) {
|
||
this.hasSorted = false;
|
||
var scales = this.getAttribute('position').scales;
|
||
var categoryScales = scales.filter(function (scale) { return scale.isCategory; });
|
||
var groupedArray = this.groupData(data); // 数据分组
|
||
var beforeAdjust = [];
|
||
for (var i = 0, len = groupedArray.length; i < len; i++) {
|
||
var subData = groupedArray[i];
|
||
var arr = [];
|
||
for (var j = 0, subLen = subData.length; j < subLen; j++) {
|
||
var originData = subData[j];
|
||
var item = {};
|
||
// tslint:disable-next-line: forin
|
||
for (var k in originData) {
|
||
item[k] = originData[k];
|
||
}
|
||
item[FIELD_ORIGIN] = originData;
|
||
// 将分类数据翻译成数据, 仅对位置相关的度量进行数字化处理
|
||
for (var _i = 0, categoryScales_1 = categoryScales; _i < categoryScales_1.length; _i++) {
|
||
var scale = categoryScales_1[_i];
|
||
var field = scale.field;
|
||
item[field] = scale.translate(item[field]);
|
||
}
|
||
arr.push(item);
|
||
}
|
||
beforeAdjust.push(arr);
|
||
}
|
||
var dataArray = this.adjustData(beforeAdjust); // 进行 adjust 数据调整
|
||
this.beforeMappingData = dataArray;
|
||
return dataArray;
|
||
};
|
||
// 调整数据
|
||
Geometry.prototype.adjustData = function (dataArray) {
|
||
var adjustOption = this.adjustOption;
|
||
var result = dataArray;
|
||
if (adjustOption) {
|
||
var xScale = this.getXScale();
|
||
var yScale = this.getYScale();
|
||
var xField = xScale.field;
|
||
var yField = yScale ? yScale.field : null;
|
||
for (var i = 0, len = adjustOption.length; i < len; i++) {
|
||
var adjust = adjustOption[i];
|
||
var adjustCfg = __assign({ xField: xField,
|
||
yField: yField }, adjust);
|
||
var type = adjust.type;
|
||
if (type === 'dodge') {
|
||
var adjustNames = [];
|
||
if (xScale.isCategory || xScale.type === 'identity') {
|
||
adjustNames.push('x');
|
||
}
|
||
else if (!yScale) {
|
||
adjustNames.push('y');
|
||
}
|
||
else {
|
||
throw new Error('dodge is not support linear attribute, please use category attribute!');
|
||
}
|
||
adjustCfg.adjustNames = adjustNames;
|
||
// 每个分组内每条柱子的宽度占比,用户不可指定,用户需要通过 columnWidthRatio 指定
|
||
adjustCfg.dodgeRatio = this.theme.columnWidthRatio;
|
||
}
|
||
else if (type === 'stack') {
|
||
var coordinate = this.coordinate;
|
||
if (!yScale) {
|
||
// 一维的情况下获取高度和默认size
|
||
adjustCfg.height = coordinate.getHeight();
|
||
var size = this.getDefaultValue('size') || 3;
|
||
adjustCfg.size = size;
|
||
}
|
||
// 不进行 transpose 时,用户又没有设置这个参数时,默认从上向下
|
||
if (!coordinate.isTransposed && isNil(adjustCfg.reverseOrder)) {
|
||
adjustCfg.reverseOrder = true;
|
||
}
|
||
}
|
||
var adjustCtor = getAdjustClass(type);
|
||
var adjustInstance = new adjustCtor(adjustCfg);
|
||
result = adjustInstance.process(result);
|
||
this.adjusts[type] = adjustInstance;
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
// 对数据进行分组
|
||
Geometry.prototype.groupData = function (data) {
|
||
var groupScales = this.getGroupScales();
|
||
var scaleDefs = this.scaleDefs;
|
||
var appendConditions = {};
|
||
var groupFields = [];
|
||
for (var index = 0; index < groupScales.length; index++) {
|
||
var scale = groupScales[index];
|
||
var field = scale.field;
|
||
groupFields.push(field);
|
||
if (get(scaleDefs, [field, 'values'])) {
|
||
// 用户通过 view.scale() 接口指定了 values 属性
|
||
appendConditions[field] = scaleDefs[field].values;
|
||
}
|
||
}
|
||
return group(data, groupFields, appendConditions);
|
||
};
|
||
// 更新发生层叠后的数据对应的度量范围
|
||
Geometry.prototype.updateStackRange = function (scale, dataArray) {
|
||
var mergeArray = flatten(dataArray);
|
||
var field = scale.field;
|
||
var min = scale.min;
|
||
var max = scale.max;
|
||
for (var index = 0; index < mergeArray.length; index++) {
|
||
var obj = mergeArray[index];
|
||
var tmpMin = Math.min.apply(null, obj[field]);
|
||
var tmpMax = Math.max.apply(null, obj[field]);
|
||
if (tmpMin < min) {
|
||
min = tmpMin;
|
||
}
|
||
if (tmpMax > max) {
|
||
max = tmpMax;
|
||
}
|
||
}
|
||
var scaleDefs = this.scaleDefs;
|
||
var cfg = {};
|
||
if ((min < scale.min) && !get(scaleDefs, [field, 'min'])) {
|
||
// 用户如果在列定义中定义了 min,则以用户定义的为准
|
||
cfg.min = min;
|
||
}
|
||
if ((max > scale.max) && !get(scaleDefs, [field, 'max'])) {
|
||
// 用户如果在列定义中定义了 max
|
||
cfg.max = max;
|
||
}
|
||
scale.change(cfg);
|
||
};
|
||
// 将数据映射至图形空间前的操作:排序以及关键点的生成
|
||
Geometry.prototype.beforeMapping = function (beforeMappingData) {
|
||
// 当初加 clone 是因为 points 的引用关系,导致更新失败,可是现在貌似复现不出来了,所以暂时不进行 clone
|
||
// const source = clone(beforeMappingData);
|
||
var source = beforeMappingData;
|
||
if (this.sortable) {
|
||
this.sort(source);
|
||
}
|
||
if (this.generatePoints) {
|
||
// 需要生成关键点
|
||
for (var index = 0, length_7 = source.length; index < length_7; index++) {
|
||
var currentData = source[index];
|
||
this.generateShapePoints(currentData);
|
||
var nextData = source[index + 1];
|
||
if (nextData) {
|
||
this.generateShapePoints(nextData);
|
||
currentData[0].nextPoints = nextData[0].points;
|
||
}
|
||
}
|
||
}
|
||
return source;
|
||
};
|
||
// 生成 shape 的关键点
|
||
Geometry.prototype.generateShapePoints = function (data) {
|
||
var shapeFactory = this.getShapeFactory();
|
||
var shapeAttr = this.getAttribute('shape');
|
||
for (var index = 0; index < data.length; index++) {
|
||
var obj = data[index];
|
||
var cfg = this.createShapePointsCfg(obj);
|
||
var shape = shapeAttr ? this.getAttributeValues(shapeAttr, obj) : null;
|
||
var points = shapeFactory.getShapePoints(shape, cfg);
|
||
obj.points = points;
|
||
}
|
||
};
|
||
// 将数据归一化
|
||
Geometry.prototype.normalizeValues = function (values, scale) {
|
||
var rst = [];
|
||
if (isArray(values)) {
|
||
for (var index = 0; index < values.length; index++) {
|
||
var value = values[index];
|
||
rst.push(scale.scale(value));
|
||
}
|
||
}
|
||
else {
|
||
rst = scale.scale(values);
|
||
}
|
||
return rst;
|
||
};
|
||
// 将数据映射至图形空间
|
||
Geometry.prototype.mapping = function (data) {
|
||
var attributes = this.attributes;
|
||
var mappingData = [];
|
||
for (var index = 0; index < data.length; index++) {
|
||
var record = data[index];
|
||
var newRecord = {
|
||
_origin: record[FIELD_ORIGIN],
|
||
points: record.points,
|
||
nextPoints: record.nextPoints,
|
||
};
|
||
for (var k in attributes) {
|
||
if (attributes.hasOwnProperty(k)) {
|
||
var attr = attributes[k];
|
||
var names = attr.names;
|
||
var values = this.getAttributeValues(attr, record);
|
||
if (names.length > 1) {
|
||
// position 之类的生成多个字段的属性
|
||
for (var j = 0; j < values.length; j += 1) {
|
||
var val = values[j];
|
||
var name_1 = names[j];
|
||
newRecord[name_1] = isArray(val) && val.length === 1 ? val[0] : val; // 只有一个值时返回第一个属性值
|
||
}
|
||
}
|
||
else {
|
||
// values.length === 1 的判断是以下情况,获取用户设置的图形属性值
|
||
// shape('a', ['dot', 'dash']), color('a', ['red', 'yellow'])
|
||
newRecord[names[0]] = values.length === 1 ? values[0] : values;
|
||
}
|
||
}
|
||
}
|
||
this.convertPoint(newRecord); // 将 x、y 转换成画布坐标
|
||
mappingData.push(newRecord);
|
||
}
|
||
return mappingData;
|
||
};
|
||
// 将归一化的坐标值转换成画布坐标
|
||
Geometry.prototype.convertPoint = function (mappingRecord) {
|
||
var x = mappingRecord.x, y = mappingRecord.y;
|
||
var rstX;
|
||
var rstY;
|
||
var obj;
|
||
var coordinate = this.coordinate;
|
||
if (isArray(x) && isArray(y)) {
|
||
rstX = [];
|
||
rstY = [];
|
||
for (var i = 0, j = 0, xLen = x.length, yLen = y.length; i < xLen && j < yLen; i += 1, j += 1) {
|
||
obj = coordinate.convert({
|
||
x: x[i],
|
||
y: y[j],
|
||
});
|
||
rstX.push(obj.x);
|
||
rstY.push(obj.y);
|
||
}
|
||
}
|
||
else if (isArray(y)) {
|
||
rstY = [];
|
||
for (var index = 0; index < y.length; index++) {
|
||
var yVal = y[index];
|
||
obj = coordinate.convert({
|
||
x: x,
|
||
y: yVal,
|
||
});
|
||
if (rstX && rstX !== obj.x) {
|
||
if (!isArray(rstX)) {
|
||
rstX = [rstX];
|
||
}
|
||
rstX.push(obj.x);
|
||
}
|
||
else {
|
||
rstX = obj.x;
|
||
}
|
||
rstY.push(obj.y);
|
||
}
|
||
}
|
||
else if (isArray(x)) {
|
||
rstX = [];
|
||
for (var index = 0; index < x.length; index++) {
|
||
var xVal = x[index];
|
||
obj = coordinate.convert({
|
||
x: xVal,
|
||
y: y,
|
||
});
|
||
if (rstY && rstY !== obj.y) {
|
||
if (!isArray(rstY)) {
|
||
rstY = [rstY];
|
||
}
|
||
rstY.push(obj.y);
|
||
}
|
||
else {
|
||
rstY = obj.y;
|
||
}
|
||
rstX.push(obj.x);
|
||
}
|
||
}
|
||
else {
|
||
var point = coordinate.convert({
|
||
x: x,
|
||
y: y,
|
||
});
|
||
rstX = point.x;
|
||
rstY = point.y;
|
||
}
|
||
mappingRecord.x = rstX;
|
||
mappingRecord.y = rstY;
|
||
};
|
||
// 获取 style 配置
|
||
Geometry.prototype.getStyleCfg = function (styleOption, originData) {
|
||
var _a = styleOption.fields, fields = _a === void 0 ? [] : _a, callback = styleOption.callback, cfg = styleOption.cfg;
|
||
if (cfg) {
|
||
// 用户直接配置样式属性
|
||
return cfg;
|
||
}
|
||
var params = fields.map(function (field) {
|
||
return originData[field];
|
||
});
|
||
return callback.apply(void 0, params);
|
||
};
|
||
Geometry.prototype.setCfg = function (cfg) {
|
||
var _this = this;
|
||
var coordinate = cfg.coordinate, data = cfg.data, theme = cfg.theme, scaleDefs = cfg.scaleDefs;
|
||
if (coordinate) {
|
||
this.coordinate = coordinate;
|
||
}
|
||
if (data) {
|
||
this.data = data;
|
||
}
|
||
if (scaleDefs) {
|
||
this.scaleDefs = scaleDefs;
|
||
this.idFields = [];
|
||
each(scaleDefs, function (scaleDef, field) {
|
||
if (scaleDef && scaleDef.key) {
|
||
_this.idFields.push(field);
|
||
}
|
||
});
|
||
}
|
||
if (theme) {
|
||
this.theme = this.userTheme ? deepMix({}, theme, this.userTheme) : theme; // 支持 geometry 层级的主题设置
|
||
}
|
||
};
|
||
Geometry.prototype.renderLabels = function (mappingArray, isUpdate) {
|
||
if (isUpdate === void 0) { isUpdate = false; }
|
||
var geometryLabel = this.geometryLabel;
|
||
if (!geometryLabel) {
|
||
// 初次创建
|
||
var labelType = this.getLabelType();
|
||
var GeometryLabelsCtor = getGeometryLabel(labelType);
|
||
geometryLabel = new GeometryLabelsCtor(this);
|
||
this.geometryLabel = geometryLabel;
|
||
}
|
||
geometryLabel.render(mappingArray, isUpdate);
|
||
// 将 label 同 element 进行关联
|
||
var labelsMap = geometryLabel.labelsRenderer.shapesMap;
|
||
each(this.elementsMap, function (element, id) {
|
||
var labels = filterLabelsById(id, labelsMap); // element 实例同 label 进行绑定
|
||
if (labels.length) {
|
||
element.labelShape = labels;
|
||
for (var i = 0; i < labels.length; i++) {
|
||
var label = labels[i];
|
||
var labelChildren = label.getChildren();
|
||
for (var j = 0; j < labelChildren.length; j++) {
|
||
var child = labelChildren[j];
|
||
child.cfg.name = ['element', 'label'];
|
||
child.cfg.element = element;
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
/**
|
||
* 是否需要进行群组入场动画
|
||
* 规则:
|
||
* 1. 如果发生更新,则不进行
|
||
* 2. 如果用户关闭 geometry 动画,则不进行
|
||
* 3. 如果用户关闭了 appear 动画,则不进行
|
||
* 4. 如果用户配置了 appear.animation,则不进行
|
||
*/
|
||
Geometry.prototype.canDoGroupAnimation = function (isUpdate) {
|
||
return (!isUpdate &&
|
||
this.animateOption &&
|
||
(get(this.animateOption, 'appear') === undefined ||
|
||
(get(this.animateOption, 'appear') && get(this.animateOption, ['appear', 'animation']) === undefined)));
|
||
};
|
||
return Geometry;
|
||
}(Base));
|
||
export default Geometry;
|
||
//# sourceMappingURL=base.js.map |