NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/g2/esm/geometry/element/index.js
2023-09-14 14:47:11 +08:00

401 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { __assign, __extends } from "tslib";
import { deepMix, each, get, isArray, isFunction, isString } from '@antv/util';
import { doAnimate } from '../../animate';
import Base from '../../base';
import { getReplaceAttrs } from '../../util/graphics';
import { propagationDelegate } from '@antv/component/lib/util/event';
/**
* Element 图形元素。
* 定义:在 G2 中我们会将数据通过图形语法映射成不同的图形比如点图数据集中的每条数据会对应一个点柱状图每条数据对应一个柱子线图则是一组数据对应一条折线Element 即一条/一组数据对应的图形元素,它代表一条数据或者一个数据集,在图形层面,它可以是单个 Shape 也可以是多个 Shape我们称之为图形元素。
*/
var Element = /** @class */ (function (_super) {
__extends(Element, _super);
function Element(cfg) {
var _this = _super.call(this, cfg) || this;
// 存储当前开启的状态
_this.states = [];
var shapeFactory = cfg.shapeFactory, container = cfg.container, offscreenGroup = cfg.offscreenGroup, _a = cfg.visible, visible = _a === void 0 ? true : _a;
_this.shapeFactory = shapeFactory;
_this.container = container;
_this.offscreenGroup = offscreenGroup;
_this.visible = visible;
return _this;
}
/**
* 绘制图形。
* @param model 绘制数据。
* @param isUpdate 可选,是否是更新发生后的绘制。
*/
Element.prototype.draw = function (model, isUpdate) {
if (isUpdate === void 0) { isUpdate = false; }
this.model = model;
this.data = model.data; // 存储原始数据
this.shapeType = this.getShapeType(model);
// 绘制图形
this.drawShape(model, isUpdate);
if (this.visible === false) {
// 用户在初始化的时候声明 visible: false
this.changeVisible(false);
}
};
/**
* 更新图形。
* @param model 更新的绘制数据。
*/
Element.prototype.update = function (model) {
var _a = this, shapeFactory = _a.shapeFactory, shape = _a.shape;
if (!shape) {
return;
}
// 更新数据
this.model = model;
this.data = model.data;
this.shapeType = this.getShapeType(model);
// step 1: 更新 shape 携带的信息
this.setShapeInfo(shape, model);
// step 2: 使用虚拟 Group 重新绘制 shape然后更新当前 shape
var offscreenGroup = this.getOffscreenGroup();
var newShape = shapeFactory.drawShape(this.shapeType, model, offscreenGroup);
// @ts-ignore
newShape.cfg.data = this.data;
// @ts-ignore
newShape.cfg.origin = model;
// step 3: 同步 shape 样式
this.syncShapeStyle(shape, newShape, '', this.getAnimateCfg('update'));
};
/**
* 销毁 element 实例。
*/
Element.prototype.destroy = function () {
var _a = this, shapeFactory = _a.shapeFactory, shape = _a.shape;
if (shape) {
var animateCfg = this.getAnimateCfg('leave');
if (animateCfg) {
// 指定了动画配置则执行销毁动画
doAnimate(shape, animateCfg, {
coordinate: shapeFactory.coordinate,
toAttrs: __assign({}, shape.attr()),
});
}
else {
// 否则直接销毁
shape.remove(true);
}
}
// reset
this.states = [];
this.shapeFactory = undefined;
this.container = undefined;
this.shape = undefined;
this.animate = undefined;
this.geometry = undefined;
this.labelShape = undefined;
this.model = undefined;
this.data = undefined;
this.offscreenGroup = undefined;
this.statesStyle = undefined;
_super.prototype.destroy.call(this);
};
/**
* 显示或者隐藏 element。
* @param visible 是否可见。
*/
Element.prototype.changeVisible = function (visible) {
_super.prototype.changeVisible.call(this, visible);
if (visible) {
if (this.shape) {
this.shape.show();
}
if (this.labelShape) {
this.labelShape.forEach(function (label) {
label.show();
});
}
}
else {
if (this.shape) {
this.shape.hide();
}
if (this.labelShape) {
this.labelShape.forEach(function (label) {
label.hide();
});
}
}
};
/**
* 设置 Element 的状态。
*
* 目前 Element 开放三种状态:
* 1. active
* 2. selected
* 3. inactive
*
* 这三种状态相互独立,可以进行叠加。
*
* 这三种状态的样式可在 [[Theme]] 主题中或者通过 `geometry.state()` 接口进行配置。
*
* ```ts
* // 激活 active 状态
* setState('active', true);
* ```
*
* @param stateName 状态名
* @param stateStatus 是否开启状态
*/
Element.prototype.setState = function (stateName, stateStatus) {
var _this = this;
var _a = this, states = _a.states, shapeFactory = _a.shapeFactory, model = _a.model, shape = _a.shape, shapeType = _a.shapeType;
var index = states.indexOf(stateName);
if (stateStatus) {
// 开启状态
if (index > -1) {
// 该状态已经开启,则返回
return;
}
states.push(stateName);
if (stateName === 'active' || stateName === 'selected') {
shape.toFront();
}
}
else {
if (index === -1) {
// 关闭状态,但是状态未设置过
return;
}
states.splice(index, 1);
if (stateName === 'active' || stateName === 'selected') {
shape.toBack();
}
}
// 使用虚拟 group 重新绘制 shape然后对这个 shape 应用状态样式后,更新当前 shape。
var offscreenShape = shapeFactory.drawShape(shapeType, model, this.getOffscreenGroup());
if (states.length) {
// 应用当前状态
states.forEach(function (state) {
_this.syncShapeStyle(shape, offscreenShape, state, null);
});
}
else {
// 如果没有状态,则需要恢复至原始状态
this.syncShapeStyle(shape, offscreenShape, 'reset', null);
}
offscreenShape.remove(true); // 销毁,减少内存占用
var eventObject = {
state: stateName,
stateStatus: stateStatus,
element: this,
target: this.container,
};
this.container.emit('statechange', eventObject);
//@ts-ignore
propagationDelegate(this.shape, 'statechange', eventObject);
};
/**
* 清空状量态,恢复至初始状态。
*/
Element.prototype.clearStates = function () {
var _this = this;
var states = this.states;
each(states, function (state) {
_this.setState(state, false);
});
this.states = [];
};
/**
* 查询当前 Element 上是否已设置 `stateName` 对应的状态。
* @param stateName 状态名称。
* @returns true 表示存在false 表示不存在。
*/
Element.prototype.hasState = function (stateName) {
return this.states.includes(stateName);
};
/**
* 获取当前 Element 上所有的状态。
* @returns 当前 Element 上所有的状态数组。
*/
Element.prototype.getStates = function () {
return this.states;
};
/**
* 获取 Element 对应的原始数据。
* @returns 原始数据。
*/
Element.prototype.getData = function () {
return this.data;
};
/**
* 获取 Element 对应的图形绘制数据。
* @returns 图形绘制数据。
*/
Element.prototype.getModel = function () {
return this.model;
};
/**
* 返回 Element 元素整体的 bbox包含文本及文本连线有的话
* @returns 整体包围盒。
*/
Element.prototype.getBBox = function () {
var _a = this, shape = _a.shape, labelShape = _a.labelShape;
var bbox = {
x: 0,
y: 0,
minX: 0,
minY: 0,
maxX: 0,
maxY: 0,
width: 0,
height: 0,
};
if (shape) {
bbox = shape.getCanvasBBox();
}
if (labelShape) {
labelShape.forEach(function (label) {
var labelBBox = label.getCanvasBBox();
bbox.x = Math.min(labelBBox.x, bbox.x);
bbox.y = Math.min(labelBBox.y, bbox.y);
bbox.minX = Math.min(labelBBox.minX, bbox.minX);
bbox.minY = Math.min(labelBBox.minY, bbox.minY);
bbox.maxX = Math.max(labelBBox.maxX, bbox.maxX);
bbox.maxY = Math.max(labelBBox.maxY, bbox.maxY);
});
}
bbox.width = bbox.maxX - bbox.minX;
bbox.height = bbox.maxY - bbox.minY;
return bbox;
};
Element.prototype.getStatesStyle = function () {
if (!this.statesStyle) {
var _a = this, shapeType = _a.shapeType, geometry = _a.geometry, shapeFactory = _a.shapeFactory;
var stateOption = geometry.stateOption;
var defaultShapeType = shapeFactory.defaultShapeType;
var stateTheme = shapeFactory.theme[shapeType] || shapeFactory.theme[defaultShapeType];
this.statesStyle = deepMix({}, stateTheme, stateOption);
}
return this.statesStyle;
};
// 从主题中获取对应状态量的样式
Element.prototype.getStateStyle = function (stateName, shapeKey) {
var statesStyle = this.getStatesStyle();
var stateCfg = get(statesStyle, [stateName, 'style'], {});
var shapeStyle = stateCfg[shapeKey] || stateCfg;
if (isFunction(shapeStyle)) {
return shapeStyle(this);
}
return shapeStyle;
};
// 获取动画配置
Element.prototype.getAnimateCfg = function (animateType) {
var animate = this.animate;
if (animate) {
return animate[animateType];
}
return null;
};
// 绘制图形
Element.prototype.drawShape = function (model, isUpdate) {
if (isUpdate === void 0) { isUpdate = false; }
var _a = this, shapeFactory = _a.shapeFactory, container = _a.container, shapeType = _a.shapeType;
// 自定义 shape 有可能返回空 shape
this.shape = shapeFactory.drawShape(shapeType, model, container);
if (this.shape) {
this.setShapeInfo(this.shape, model); // 存储绘图数据
// @ts-ignore
var name_1 = this.shape.cfg.name;
// 附加 element 的 name, name 现在支持数组了,很好用了
if (!name_1) {
// 这个地方如果用户添加了 name, 则附加 name ,否则就添加自己的 name
// @ts-ignore
this.shape.cfg.name = ['element', this.shapeFactory.geometryType];
}
else if (isString(name_1)) {
// @ts-ignore
this.shape.cfg.name = ['element', name_1];
}
// 执行入场动画
var animateType = isUpdate ? 'enter' : 'appear';
var animateCfg = this.getAnimateCfg(animateType);
if (animateCfg) {
doAnimate(this.shape, animateCfg, {
coordinate: shapeFactory.coordinate,
toAttrs: __assign({}, this.shape.attr()),
});
}
}
};
// 获取虚拟 Group
Element.prototype.getOffscreenGroup = function () {
if (!this.offscreenGroup) {
var GroupCtor = this.container.getGroupBase(); // 获取分组的构造函数
this.offscreenGroup = new GroupCtor({});
}
return this.offscreenGroup;
};
// 设置 shape 上需要携带的信息
Element.prototype.setShapeInfo = function (shape, data) {
var _this = this;
// @ts-ignore
shape.cfg.origin = data;
// @ts-ignore
shape.cfg.element = this;
if (shape.isGroup()) {
var children = shape.get('children');
children.forEach(function (child) {
_this.setShapeInfo(child, data);
});
}
};
// 更新当前 shape 的样式
Element.prototype.syncShapeStyle = function (sourceShape, targetShape, state, animateCfg, index) {
if (state === void 0) { state = ''; }
if (index === void 0) { index = 0; }
if (sourceShape.isGroup()) {
var children = sourceShape.get('children');
var newChildren = targetShape.get('children');
for (var i = 0; i < children.length; i++) {
this.syncShapeStyle(children[i], newChildren[i], state, animateCfg, index + i);
}
}
else {
if (state && state !== 'reset') {
var name_2 = sourceShape.get('name');
if (isArray(name_2)) { // 会附加 element 的 name
name_2 = name_2[1];
}
var style = this.getStateStyle(state, name_2 || index); // 如果用户没有设置 name则默认根据索引值
targetShape.attr(style);
}
var newAttrs = getReplaceAttrs(sourceShape, targetShape);
if (this.animate) {
if (animateCfg) {
// 需要进行动画
doAnimate(sourceShape, animateCfg, {
coordinate: this.shapeFactory.coordinate,
toAttrs: newAttrs,
shapeModel: this.model,
});
}
else if (state) {
sourceShape.stopAnimate();
sourceShape.animate(newAttrs, {
duration: 300,
});
}
else {
sourceShape.attr(newAttrs);
}
}
else {
sourceShape.attr(newAttrs);
}
}
};
Element.prototype.getShapeType = function (model) {
var shape = get(model, 'shape');
return isArray(shape) ? shape[0] : shape;
};
return Element;
}(Base));
export default Element;
//# sourceMappingURL=index.js.map