NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/g2/esm/chart/controller/annotation.js
2023-09-14 14:47:11 +08:00

555 lines
20 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 { contains, deepMix, each, get, isArray, isFunction, isNil, isString, keys, upperFirst } from '@antv/util';
import { Annotation as AnnotationComponent } from '../../dependents';
import { DEFAULT_ANIMATE_CFG } from '../../animate/';
import { COMPONENT_TYPE, DIRECTION, LAYER, VIEW_LIFE_CIRCLE } from '../../constant';
import { getAngleByPoint, getDistanceToCenter } from '../../util/coordinate';
import { omit } from '../../util/helper';
import { Controller } from './base';
/**
* Annotation controller, 主要作用:
* 1. 创建 Annotation: line、text、arc ...
* 2. 生命周期: init、layout、render、clear、destroy
*/
var Annotation = /** @class */ (function (_super) {
__extends(Annotation, _super);
function Annotation(view) {
var _this = _super.call(this, view) || this;
/* 组件更新的 cache组件配置 object : 组件 */
_this.cache = new Map();
_this.foregroundContainer = _this.view.getLayer(LAYER.FORE).addGroup();
_this.backgroundContainer = _this.view.getLayer(LAYER.BG).addGroup();
_this.option = [];
return _this;
}
Object.defineProperty(Annotation.prototype, "name", {
get: function () {
return 'annotation';
},
enumerable: false,
configurable: true
});
Annotation.prototype.init = function () { };
Annotation.prototype.layout = function () {
var _this = this;
var components = this.getComponents();
var updateComponentFn = function (co) {
var component = co.component, extra = co.extra;
var type = extra.type;
var theme = _this.getAnnotationTheme(type);
component.update(_this.getAnnotationCfg(type, extra, theme));
};
var createComponentFn = function (option) {
var co = _this.createAnnotation(option);
if (co) {
co.component.init();
// NoteregionFilter 特殊处理regionFilter需要取到 Geometry 中的 Shape需要在 view render 之后处理
// 其他组件使用外层的统一 render 逻辑
if (option.type === 'regionFilter') {
co.component.render();
}
// 缓存起来
_this.cache.set(option, co);
}
};
if (components.length) {
each(components, function (co) {
var component = co.component;
if (component.get('type') === 'regionFilter') {
// regionFilter 依赖绘制后的 Geometry Shapes
_this.view.once(VIEW_LIFE_CIRCLE.AFTER_RENDER, function () {
updateComponentFn(co);
});
}
else {
updateComponentFn(co);
}
});
}
else {
each(this.option, function (option) {
if (option.type === 'regionFilter') {
_this.view.once(VIEW_LIFE_CIRCLE.AFTER_RENDER, function () {
// regionFilter 依赖绘制后的 Geometry Shapes
createComponentFn(option);
});
}
else {
createComponentFn(option);
}
});
}
};
Annotation.prototype.render = function () {
// 因为 Annotation 不参与布局,但是渲染的位置依赖于坐标系,所以可以将绘制阶段延迟到 layout() 进行
};
/**
* 更新
*/
Annotation.prototype.update = function () {
var _this = this;
// 已经处理过的 legend
var updated = new WeakMap();
var updateComponentFn = function (option) {
var type = option.type;
var theme = _this.getAnnotationTheme(type);
var cfg = _this.getAnnotationCfg(type, option, theme);
var existCo = _this.cache.get(option);
// 存在,则更新
if (existCo) {
// 忽略掉一些配置
omit(cfg, ['container']);
existCo.component.update(cfg);
updated.set(option, true);
}
else {
// 不存在,则创建
var co = _this.createAnnotation(option);
if (co) {
co.component.init();
// NoteregionFilter 特殊处理regionFilter需要取到 Geometry 中的 Shape需要在 view render 之后处理
// 其他组件使用外层的统一 render 逻辑
if (option.type === 'regionFilter') {
co.component.render();
}
// 缓存起来
_this.cache.set(option, co);
updated.set(option, true);
}
}
};
this.view.once(VIEW_LIFE_CIRCLE.AFTER_RENDER, function () {
// 先看是否有 regionFilter 要更新
each(_this.option, function (option) {
if (option.type === 'regionFilter') {
updateComponentFn(option);
}
});
// 处理完成之后,销毁删除的
// 不在处理中的
var newCache = new Map();
_this.cache.forEach(function (value, key) {
if (updated.has(key)) {
newCache.set(key, value);
}
else {
// 不存在,则是所有需要被销毁的组件
value.component.destroy();
}
});
// 更新缓存
_this.cache = newCache;
});
each(this.option, function (option) {
if (option.type !== 'regionFilter') {
updateComponentFn(option);
}
});
};
/**
* 清空
* @param includeOption 是否清空 option 配置项
*/
Annotation.prototype.clear = function (includeOption) {
if (includeOption === void 0) { includeOption = false; }
_super.prototype.clear.call(this);
this.cache.clear();
this.foregroundContainer.clear();
this.backgroundContainer.clear();
// clear all option
if (includeOption) {
this.option = [];
}
};
Annotation.prototype.destroy = function () {
this.clear(true);
this.foregroundContainer.remove(true);
this.backgroundContainer.remove(true);
};
/**
* 复写基类的方法
*/
Annotation.prototype.getComponents = function () {
var co = [];
this.cache.forEach(function (value) {
co.push(value);
});
return co;
};
Annotation.prototype.createAnnotation = function (option) {
var type = option.type;
var Ctor = AnnotationComponent[upperFirst(type)];
if (Ctor) {
var theme = this.getAnnotationTheme(type);
var cfg = this.getAnnotationCfg(type, option, theme);
var annotation = new Ctor(cfg);
return {
component: annotation,
layer: this.isTop(cfg) ? LAYER.FORE : LAYER.BG,
direction: DIRECTION.NONE,
type: COMPONENT_TYPE.ANNOTATION,
extra: option,
};
}
};
// APIs for creating annotation component
Annotation.prototype.annotation = function (option) {
this.option.push(option);
};
/**
* 创建 Arc
* @param option
* @returns AnnotationController
*/
Annotation.prototype.arc = function (option) {
this.annotation(__assign({ type: 'arc' }, option));
return this;
};
/**
* 创建 image
* @param option
* @returns AnnotationController
*/
Annotation.prototype.image = function (option) {
this.annotation(__assign({ type: 'image' }, option));
return this;
};
/**
* 创建 Line
* @param option
* @returns AnnotationController
*/
Annotation.prototype.line = function (option) {
this.annotation(__assign({ type: 'line' }, option));
return this;
};
/**
* 创建 Region
* @param option
* @returns AnnotationController
*/
Annotation.prototype.region = function (option) {
this.annotation(__assign({ type: 'region' }, option));
return this;
};
/**
* 创建 Text
* @param option
* @returns AnnotationController
*/
Annotation.prototype.text = function (option) {
this.annotation(__assign({ type: 'text' }, option));
return this;
};
/**
* 创建 DataMarker
* @param option
* @returns AnnotationController
*/
Annotation.prototype.dataMarker = function (option) {
this.annotation(__assign({ type: 'dataMarker' }, option));
return this;
};
/**
* 创建 DataRegion
* @param option
* @returns AnnotationController
*/
Annotation.prototype.dataRegion = function (option) {
this.annotation(__assign({ type: 'dataRegion' }, option));
};
/**
* 创建 RegionFilter
* @param option
* @returns AnnotationController
*/
Annotation.prototype.regionFilter = function (option) {
this.annotation(__assign({ type: 'regionFilter' }, option));
};
// end API
/**
* parse the point position to [x, y]
* @param p Position
* @returns { x, y }
*/
Annotation.prototype.parsePosition = function (p) {
var xScale = this.view.getXScale();
// 转成 object
var yScales = this.view.getScalesByDim('y');
var position = isFunction(p) ? p.call(null, xScale, yScales) : p;
var x = 0;
var y = 0;
// 入参是 [24, 24] 这类时
if (isArray(position)) {
var xPos = position[0], yPos = position[1];
// 如果数据格式是 ['50%', '50%'] 的格式
// fix: 原始数据中可能会包含 'xxx5%xxx' 这样的数据,需要判断下 https://github.com/antvis/f2/issues/590
// @ts-ignore
if (isString(xPos) && xPos.indexOf('%') !== -1 && !isNaN(xPos.slice(0, -1))) {
return this.parsePercentPosition(position);
}
x = this.getNormalizedValue(xPos, xScale);
y = this.getNormalizedValue(yPos, Object.values(yScales)[0]);
}
else if (!isNil(position)) {
// 入参是 object 结构,数据点
for (var _i = 0, _a = keys(position); _i < _a.length; _i++) {
var key = _a[_i];
var value = position[key];
if (key === xScale.field) {
x = this.getNormalizedValue(value, xScale);
}
if (yScales[key]) {
y = this.getNormalizedValue(value, yScales[key]);
}
}
}
return this.view.getCoordinate().convert({ x: x, y: y });
};
/**
* parse all the points between start and end
* @param start
* @param end
* @return Point[]
*/
Annotation.prototype.getRegionPoints = function (start, end) {
var _this = this;
var xScale = this.view.getXScale();
var yScales = this.view.getScalesByDim('y');
var yScale = Object.values(yScales)[0];
var xField = xScale.field;
var viewData = this.view.getData();
var startXValue = isArray(start) ? start[0] : start[xField];
var endXValue = isArray(end) ? end[0] : end[xField];
var arr = [];
var startIndex;
each(viewData, function (item, idx) {
if (item[xField] === startXValue) {
startIndex = idx;
}
if (idx >= startIndex) {
var point = _this.parsePosition([item[xField], item[yScale.field]]);
if (point) {
arr.push(point);
}
}
if (item[xField] === endXValue) {
return false;
}
});
return arr;
};
/**
* parse the value position
* @param val
* @param scale
*/
Annotation.prototype.getNormalizedValue = function (val, scale) {
var result;
var scaled;
switch (val) {
case 'start':
result = 0;
break;
case 'end':
result = 1;
break;
case 'median': {
scaled = scale.isCategory ? (scale.values.length - 1) / 2 : (scale.min + scale.max) / 2;
result = scale.scale(scaled);
break;
}
case 'min':
case 'max':
if (scale.isCategory) {
scaled = val === 'min' ? 0 : scale.values.length - 1;
}
else {
scaled = scale[val];
}
result = scale.scale(scaled);
break;
default:
result = scale.scale(val);
}
return result;
};
/**
* parse percent position
* @param position
*/
Annotation.prototype.parsePercentPosition = function (position) {
var xPercent = parseFloat(position[0]) / 100;
var yPercent = parseFloat(position[1]) / 100;
var coordinate = this.view.getCoordinate();
var start = coordinate.start, end = coordinate.end;
var topLeft = {
x: Math.min(start.x, end.x),
y: Math.min(start.y, end.y),
};
var x = coordinate.getWidth() * xPercent + topLeft.x;
var y = coordinate.getHeight() * yPercent + topLeft.y;
return { x: x, y: y };
};
/**
* get coordinate bbox
*/
Annotation.prototype.getCoordinateBBox = function () {
var coordinate = this.view.getCoordinate();
var start = coordinate.start, end = coordinate.end;
var width = coordinate.getWidth();
var height = coordinate.getHeight();
var topLeft = {
x: Math.min(start.x, end.x),
y: Math.min(start.y, end.y),
};
return {
x: topLeft.x,
y: topLeft.y,
minX: topLeft.x,
minY: topLeft.y,
maxX: topLeft.x + width,
maxY: topLeft.y + height,
width: width,
height: height,
};
};
/**
* get annotation component config by different type
* @param type
* @param option 用户的配置
* @param theme
*/
Annotation.prototype.getAnnotationCfg = function (type, option, theme) {
var coordinate = this.view.getCoordinate();
var o = {};
if (isNil(option)) {
return null;
}
if (type === 'arc') {
var _a = option, start = _a.start, end = _a.end;
var sp = this.parsePosition(start);
var ep = this.parsePosition(end);
var startAngle = getAngleByPoint(coordinate, sp);
var endAngle = getAngleByPoint(coordinate, ep);
if (startAngle > endAngle) {
endAngle = Math.PI * 2 + endAngle;
}
o = {
center: coordinate.getCenter(),
radius: getDistanceToCenter(coordinate, sp),
startAngle: startAngle,
endAngle: endAngle,
};
}
else if (type === 'image') {
var _b = option, start = _b.start, end = _b.end;
o = {
start: this.parsePosition(start),
end: this.parsePosition(end),
src: option.src,
};
}
else if (type === 'line') {
var _c = option, start = _c.start, end = _c.end;
o = {
start: this.parsePosition(start),
end: this.parsePosition(end),
text: get(option, 'text', null),
};
}
else if (type === 'region') {
var _d = option, start = _d.start, end = _d.end;
o = {
start: this.parsePosition(start),
end: this.parsePosition(end),
};
}
else if (type === 'text') {
var _e = option, position = _e.position, rotate = _e.rotate;
o = __assign(__assign({}, this.parsePosition(position)), { content: option.content, rotate: rotate });
}
else if (type === 'dataMarker') {
var _f = option, position = _f.position, point = _f.point, line = _f.line, text = _f.text, autoAdjust = _f.autoAdjust, direction = _f.direction;
o = __assign(__assign({}, this.parsePosition(position)), { coordinateBBox: this.getCoordinateBBox(), point: point,
line: line,
text: text,
autoAdjust: autoAdjust,
direction: direction });
}
else if (type === 'dataRegion') {
var _g = option, start = _g.start, end = _g.end, region = _g.region, text = _g.text, lineLength = _g.lineLength;
o = {
points: this.getRegionPoints(start, end),
region: region,
text: text,
lineLength: lineLength,
};
}
else if (type === 'regionFilter') {
var _h = option, start = _h.start, end = _h.end, apply_1 = _h.apply, color = _h.color;
var geometries = this.view.geometries;
var shapes_1 = [];
var addShapes_1 = function (item) {
if (!item) {
return;
}
if (item.isGroup()) {
item.getChildren().forEach(function (child) { return addShapes_1(child); });
}
else {
shapes_1.push(item);
}
};
each(geometries, function (geom) {
if (apply_1) {
if (contains(apply_1, geom.type)) {
each(geom.elements, function (elem) {
addShapes_1(elem.shape);
});
}
}
else {
each(geom.elements, function (elem) {
addShapes_1(elem.shape);
});
}
});
o = {
color: color,
shapes: shapes_1,
start: this.parsePosition(start),
end: this.parsePosition(end),
};
}
// 合并主题,用户配置优先级高于默认主题
var cfg = deepMix({}, theme, __assign(__assign({}, o), { top: option.top, style: option.style, offsetX: option.offsetX, offsetY: option.offsetY }));
cfg.container = this.getComponentContainer(cfg);
cfg.animate = this.view.getOptions().animate && cfg.animate && get(option, 'animate', cfg.animate); // 如果 view 关闭动画,则不执行
cfg.animateOption = deepMix({}, DEFAULT_ANIMATE_CFG, cfg.animateOption, option.animateOption);
return cfg;
};
/**
* is annotation render on top
* @param option
* @return whethe on top
*/
Annotation.prototype.isTop = function (option) {
return get(option, 'top', true);
};
/**
* get the container by option.top
* default is on top
* @param option
* @returns the container
*/
Annotation.prototype.getComponentContainer = function (option) {
return this.isTop(option) ? this.foregroundContainer : this.backgroundContainer;
};
Annotation.prototype.getAnnotationTheme = function (type) {
return get(this.view.getTheme(), ['components', 'annotation', type], {});
};
return Annotation;
}(Controller));
export default Annotation;
//# sourceMappingURL=annotation.js.map