244 lines
10 KiB
Java
244 lines
10 KiB
Java
import { __assign } from "tslib";
|
||
import { deepMix, each, get, isArray } from '@antv/util';
|
||
import { doAnimate } from '../animate';
|
||
import { getGeometryLabelLayout } from '../geometry/label';
|
||
import { getReplaceAttrs } from '../util/graphics';
|
||
import { rotate, translate } from '../util/transform';
|
||
/**
|
||
* Geometry labels 渲染组件
|
||
*/
|
||
var Labels = /** @class */ (function () {
|
||
function Labels(cfg) {
|
||
/** 存储当前 shape 的映射表,键值为 shape id */
|
||
this.shapesMap = {};
|
||
this.lastShapesMap = {};
|
||
var layout = cfg.layout, container = cfg.container;
|
||
this.layout = layout;
|
||
this.container = container;
|
||
}
|
||
/**
|
||
* 渲染文本
|
||
*/
|
||
Labels.prototype.render = function (items, shapes, isUpdate) {
|
||
var _this = this;
|
||
if (isUpdate === void 0) { isUpdate = false; }
|
||
this.shapesMap = {};
|
||
var container = this.container;
|
||
var offscreenGroup = this.createOffscreenGroup(); // 创建虚拟分组
|
||
if (items.length) {
|
||
// 如果 items 空的话就不进行绘制调整操作
|
||
// step 1: 在虚拟 group 中创建 shapes
|
||
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
||
var item = items_1[_i];
|
||
if (item) {
|
||
this.renderLabel(item, offscreenGroup);
|
||
}
|
||
}
|
||
// step 2: 根据布局,调整 labels
|
||
this.doLayout(items, shapes);
|
||
// step 3: 绘制 labelLine
|
||
this.renderLabelLine(items);
|
||
// step 4: 根据用户设置的偏移量调整 label
|
||
this.adjustLabel(items);
|
||
}
|
||
// 进行添加、更新、销毁操作
|
||
var lastShapesMap = this.lastShapesMap;
|
||
var shapesMap = this.shapesMap;
|
||
each(shapesMap, function (shape, id) {
|
||
if (shape.destroyed) {
|
||
// label 在布局调整环节被删除了(doLayout)
|
||
delete shapesMap[id];
|
||
}
|
||
else {
|
||
if (lastShapesMap[id]) {
|
||
// 图形发生更新
|
||
var data_1 = shape.get('data');
|
||
var origin_1 = shape.get('origin');
|
||
var coordinate_1 = shape.get('coordinate');
|
||
var currentShape = lastShapesMap[id]; // 已经在渲染树上的 shape
|
||
var currentAnimateCfg_1 = shape.get('animateCfg');
|
||
currentShape.set('data', data_1);
|
||
currentShape.set('origin', origin_1);
|
||
currentShape.set('animateCfg', currentAnimateCfg_1);
|
||
currentShape.set('coordinate', coordinate_1);
|
||
var updateAnimateCfg_1 = get(currentAnimateCfg_1, 'update');
|
||
var currentChildren_1 = currentShape.getChildren();
|
||
shape.getChildren().map(function (child, index) {
|
||
var currentChild = currentChildren_1[index];
|
||
currentChild.set('data', data_1);
|
||
currentChild.set('origin', origin_1);
|
||
currentChild.set('animateCfg', currentAnimateCfg_1);
|
||
currentChild.set('coordinate', coordinate_1);
|
||
var newAttrs = getReplaceAttrs(currentChild, child);
|
||
if (updateAnimateCfg_1) {
|
||
doAnimate(currentChild, updateAnimateCfg_1, {
|
||
toAttrs: newAttrs,
|
||
coordinate: coordinate_1,
|
||
});
|
||
}
|
||
else {
|
||
currentChild.attr(newAttrs);
|
||
}
|
||
});
|
||
_this.shapesMap[id] = currentShape; // 保存引用
|
||
}
|
||
else {
|
||
// 新生成的 shape
|
||
container.add(shape);
|
||
var animateCfg = get(shape.get('animateCfg'), isUpdate ? 'enter' : 'appear');
|
||
if (animateCfg) {
|
||
doAnimate(shape, animateCfg, {
|
||
toAttrs: __assign({}, shape.attr()),
|
||
coordinate: shape.get('coordinate'),
|
||
});
|
||
}
|
||
}
|
||
delete lastShapesMap[id];
|
||
}
|
||
});
|
||
// 移除
|
||
each(lastShapesMap, function (deleteShape) {
|
||
var animateCfg = get(deleteShape.get('animateCfg'), 'leave');
|
||
if (animateCfg) {
|
||
doAnimate(deleteShape, animateCfg, {
|
||
toAttrs: null,
|
||
coordinate: deleteShape.get('coordinate'),
|
||
});
|
||
}
|
||
else {
|
||
deleteShape.remove(true); // 移除
|
||
}
|
||
});
|
||
this.lastShapesMap = shapesMap;
|
||
offscreenGroup.destroy();
|
||
};
|
||
/** 清楚当前 labels */
|
||
Labels.prototype.clear = function () {
|
||
this.container.clear();
|
||
this.shapesMap = {};
|
||
this.lastShapesMap = {};
|
||
};
|
||
/** 销毁 */
|
||
Labels.prototype.destroy = function () {
|
||
this.container.destroy();
|
||
this.shapesMap = null;
|
||
this.lastShapesMap = null;
|
||
};
|
||
Labels.prototype.renderLabel = function (cfg, container) {
|
||
var id = cfg.id, data = cfg.data, mappingData = cfg.mappingData, coordinate = cfg.coordinate, animate = cfg.animate, content = cfg.content;
|
||
var shapeAppendCfg = {
|
||
id: id,
|
||
data: data,
|
||
origin: mappingData,
|
||
coordinate: coordinate,
|
||
};
|
||
var labelGroup = container.addGroup(__assign({ name: 'label',
|
||
// 如果 this.animate === false 或者 cfg.animate === false/null 则不进行动画,否则进行动画配置的合并
|
||
animateCfg: this.animate === false || animate === null || animate === false ? false : deepMix({}, this.animate, animate) }, shapeAppendCfg));
|
||
var labelShape;
|
||
if ((content.isGroup && content.isGroup()) || (content.isShape && content.isShape())) {
|
||
// 如果 content 是 Group 或者 Shape,根据 textAlign 调整位置后,直接将其加入 labelGroup
|
||
var _a = content.getCanvasBBox(), width = _a.width, height = _a.height;
|
||
var textAlign = get(cfg, 'textAlign', 'left');
|
||
var x = cfg.x;
|
||
var y = cfg.y - (height / 2);
|
||
if (textAlign === 'center') {
|
||
x = x - (width / 2);
|
||
}
|
||
else if (textAlign === 'right' || textAlign === 'end') {
|
||
x = x - width;
|
||
}
|
||
translate(content, x, y); // 将 label 平移至 x, y 指定的位置
|
||
labelShape = content;
|
||
labelGroup.add(content);
|
||
}
|
||
else {
|
||
labelShape = labelGroup.addShape('text', __assign({ attrs: __assign({ x: cfg.x, y: cfg.y, textAlign: cfg.textAlign, textBaseline: get(cfg, 'textBaseline', 'middle'), text: cfg.content }, cfg.style) }, shapeAppendCfg));
|
||
}
|
||
if (cfg.rotate) {
|
||
rotate(labelShape, cfg.rotate);
|
||
}
|
||
this.shapesMap[id] = labelGroup;
|
||
};
|
||
// 根据type对label布局
|
||
Labels.prototype.doLayout = function (items, shapes) {
|
||
var _this = this;
|
||
if (this.layout) {
|
||
var layouts = isArray(this.layout) ? this.layout : [this.layout];
|
||
each(layouts, function (layout) {
|
||
var layoutFn = getGeometryLabelLayout(get(layout, 'type', ''));
|
||
if (layoutFn) {
|
||
var labelShapes_1 = [];
|
||
var geometryShapes_1 = [];
|
||
each(_this.shapesMap, function (labelShape, id) {
|
||
labelShapes_1.push(labelShape);
|
||
geometryShapes_1.push(shapes[id]);
|
||
});
|
||
layoutFn(items, labelShapes_1, geometryShapes_1, _this.region, layout.cfg);
|
||
}
|
||
});
|
||
}
|
||
};
|
||
Labels.prototype.renderLabelLine = function (labelItems) {
|
||
var _this = this;
|
||
each(labelItems, function (labelItem) {
|
||
if (!labelItem) {
|
||
return;
|
||
}
|
||
if (!labelItem.labelLine) {
|
||
// labelLine: null | false,关闭 label 对应的 labelLine
|
||
return;
|
||
}
|
||
var labelLineCfg = get(labelItem, 'labelLine', {});
|
||
var id = labelItem.id;
|
||
var path = labelLineCfg.path;
|
||
if (!path) {
|
||
var start = labelItem.start;
|
||
path = [
|
||
['M', start.x, start.y],
|
||
['L', labelItem.x, labelItem.y],
|
||
];
|
||
}
|
||
var labelGroup = _this.shapesMap[id];
|
||
if (!labelGroup.destroyed) {
|
||
labelGroup.addShape('path', {
|
||
capture: false,
|
||
attrs: __assign({ path: path, stroke: labelItem.color ? labelItem.color : get(labelItem, ['style', 'fill'], '#000'), fill: null }, labelLineCfg.style),
|
||
id: id,
|
||
origin: labelItem.mappingData,
|
||
data: labelItem.data,
|
||
coordinate: labelItem.coordinate,
|
||
});
|
||
}
|
||
});
|
||
};
|
||
Labels.prototype.createOffscreenGroup = function () {
|
||
var container = this.container;
|
||
var GroupClass = container.getGroupBase(); // 获取分组的构造函数
|
||
var newGroup = new GroupClass({});
|
||
return newGroup;
|
||
};
|
||
Labels.prototype.adjustLabel = function (items) {
|
||
var _this = this;
|
||
each(items, function (item) {
|
||
if (item) {
|
||
var id = item.id;
|
||
var labelGroup = _this.shapesMap[id];
|
||
if (!labelGroup.destroyed) {
|
||
var labelShape = labelGroup.find(function (ele) { return ele.get('type') === 'text'; });
|
||
if (labelShape) {
|
||
if (item.offsetX) {
|
||
labelShape.attr('x', labelShape.attr('x') + item.offsetX);
|
||
}
|
||
if (item.offsetY) {
|
||
labelShape.attr('y', labelShape.attr('y') + item.offsetY);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
});
|
||
};
|
||
return Labels;
|
||
}());
|
||
export default Labels;
|
||
//# sourceMappingURL=labels.js.map |