NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/g2/lib/geom/label/geom-labels.js

601 lines
16 KiB
Java
Raw Normal View History

2023-09-14 14:47:11 +08:00
var _require = require('../../renderer'),
Group = _require.Group;
var _require2 = require('@antv/component/lib'),
Label = _require2.Label; // const visualCenter = require('@antv/component/lib/label/utils/visual-center');
var Global = require('../../global');
var Util = require('../../util');
var IGNORE_ARR = ['line', 'point', 'path'];
var ORIGIN = '_origin';
function avg(arr) {
var sum = 0;
Util.each(arr, function (value) {
sum += value;
});
return sum / arr.length;
} // 计算多边形重心: https://en.wikipedia.org/wiki/Centroid#Of_a_polygon
function getCentroid(xs, ys) {
if (Util.isNumber(xs) && Util.isNumber(ys)) {
return [xs, ys];
}
var i = -1,
x = 0,
y = 0;
var former,
current = xs.length - 1;
var diff,
k = 0;
while (++i < xs.length) {
former = current;
current = i;
k += diff = xs[former] * ys[current] - xs[current] * ys[former];
x += (xs[former] + xs[current]) * diff;
y += (ys[former] + ys[current]) * diff;
}
k *= 3;
return [x / k, y / k];
}
var GeomLabels = function GeomLabels(cfg) {
GeomLabels.superclass.constructor.call(this, cfg);
};
Util.extend(GeomLabels, Group);
Util.augment(GeomLabels, {
getDefaultCfg: function getDefaultCfg() {
return {
label: Global.label,
/**
* 用户传入的文本配置信息
* @type {Object}
*/
labelCfg: null,
/**
* 所在的坐标系
* @type {Object}
*/
coord: null,
/**
* 图表的类型
* @type {String}
*/
geomType: null,
zIndex: 6
};
},
_renderUI: function _renderUI() {
GeomLabels.superclass._renderUI.call(this);
this.initLabelsCfg();
var labelsGroup = this.addGroup();
var lineGroup = this.addGroup({
elCls: 'x-line-group'
});
var labelRenderer = this.get('labelRenderer');
this.set('labelsGroup', labelsGroup);
this.set('lineGroup', lineGroup);
this.get('labelRenderer').set('group', labelsGroup);
labelRenderer.set('group', labelsGroup);
labelRenderer.set('lineGroup', lineGroup);
},
// 初始化labels的配置项
initLabelsCfg: function initLabelsCfg() {
var self = this;
var labelRenderer = new Label();
var labels = self.getDefaultLabelCfg();
var labelCfg = self.get('labelCfg'); // Util.merge(labels, labelCfg.cfg);
Util.deepMix(labels, labelCfg.globalCfg || labelCfg.cfg);
labelRenderer.set('config', false);
if (labels.labelLine) {
labelRenderer.set('labelLine', labels.labelLine);
}
labelRenderer.set('coord', self.get('coord'));
this.set('labelRenderer', labelRenderer);
self.set('label', labels);
},
/**
* @protected
* 默认的文本样式
* @return {Object} default label config
*/
getDefaultLabelCfg: function getDefaultLabelCfg() {
var self = this;
var labelCfg = self.get('labelCfg').cfg || self.get('labelCfg').globalCfg;
var geomType = self.get('geomType');
var viewTheme = self.get('viewTheme') || Global;
if (geomType === 'polygon' || labelCfg && labelCfg.offset < 0 && Util.indexOf(IGNORE_ARR, geomType) === -1) {
return Util.deepMix({}, self.get('label'), viewTheme.innerLabels, labelCfg);
}
return Util.deepMix({}, self.get('label'), viewTheme.label, labelCfg);
},
/**
* @protected
* 获取labels
* @param {Array} points points
* @param {Array} shapes shapes
* @return {Array} label items
*/
getLabelsItems: function getLabelsItems(points, shapes) {
var self = this;
var items = [];
var geom = self.get('geom');
var coord = self.get('coord');
self._getLabelCfgs(points, shapes);
var labelCfg = self.get('labelItemCfgs'); // 获取label相关的xy的值获取具体的x,y,防止存在数组
Util.each(points, function (point, i) {
var origin = point[ORIGIN];
var label = labelCfg[i];
if (!label) {
items.push(null);
return;
}
if (!Util.isArray(label.text)) {
label.text = [label.text];
}
var total = label.text.length;
Util.each(label.text, function (sub, subIndex) {
if (Util.isNil(sub) || sub === '') {
items.push(null);
return;
}
var obj = self.getLabelPoint(label, point, subIndex);
obj = Util.mix({}, label, obj);
if (!obj.textAlign) {
obj.textAlign = self.getLabelAlign(obj, subIndex, total);
}
if (geom) {
obj._id = geom._getShapeId(origin) + '-glabel-' + subIndex + '-' + obj.text;
}
obj.coord = coord;
items.push(obj);
});
});
return items;
},
/* /!*
* @protected
* 如果发生冲突则会调整文本的位置
* @param {Array} items 文本的集合
* @param {Array} shapes 关联形状
* @return {Array} adjusted items
*!/
adjustItems(items, shapes) {
// 多边形shape的label位于其可视中心
if (this.get('geomType') === 'polygon') {
let index,
shape,
path,
center,
points;
Util.each(items, (item, i) => {
if (!item) return;
shape = shapes[ i ];
path = shape.attr('path');
points = [[]];
index = 0;
path.forEach((segment, i) => {
if (segment[ 0 ] === 'z' || segment[ 0 ] === 'Z' && i !== path.length - 1) {
points.push([]);
index += 1;
}
if (segment.length === 3) {
points[ index ].push([ segment[ 1 ], segment[ 2 ] ]);
}
});
center = visualCenter(points);
item.x = center.x;
item.y = center.y;
});
}
return items;
}
*/
adjustItems: function adjustItems(items) {
Util.each(items, function (item) {
if (!item) {
return;
}
if (item.offsetX) {
item.x += item.offsetX;
}
if (item.offsetY) {
item.y += item.offsetY;
}
});
return items;
},
/**
* drawing lines to labels
* @param {Array} items labels
* @param {Object} labelLine configuration for label lines
*/
drawLines: function drawLines(items) {
var self = this;
Util.each(items, function (point) {
if (!point) {
return;
}
if (point.offset > 0) {
self.lineToLabel(point);
}
});
},
// 定义连接线
lineToLabel: function lineToLabel() {},
/**
* @protected
* 获取文本的位置信息
* @param {Array} labelCfg labels
* @param {Object} point point
* @param {Number} index index
* @return {Object} point
*/
getLabelPoint: function getLabelPoint(labelCfg, point, index) {
var self = this;
var coord = self.get('coord');
var total = labelCfg.text.length;
function getDimValue(value, idx) {
if (Util.isArray(value)) {
if (labelCfg.text.length === 1) {
// 如果仅一个label,多个y,取最后一个y
if (value.length <= 2) {
value = value[value.length - 1]; // value = value[0];
} else {
value = avg(value);
}
} else {
value = value[idx];
}
}
return value;
}
var label = {
text: labelCfg.text[index]
}; // 多边形场景,多用于地图
if (point && this.get('geomType') === 'polygon') {
var centroid = getCentroid(point.x, point.y); // 多边形的场景也有 x 和 y 只是数字的情况,譬如当 x 和 y 都是分类字段的时候 @see #1184
label.x = centroid[0];
label.y = centroid[1];
} else {
label.x = getDimValue(point.x, index);
label.y = getDimValue(point.y, index);
} // get nearest point of the shape as the label line start point
if (point && point.nextPoints && (point.shape === 'funnel' || point.shape === 'pyramid')) {
var maxX = -Infinity;
point.nextPoints.forEach(function (p) {
p = coord.convert(p);
if (p.x > maxX) {
maxX = p.x;
}
});
label.x = (label.x + maxX) / 2;
} // sharp edge of the pyramid
if (point.shape === 'pyramid' && !point.nextPoints && point.points) {
point.points.forEach(function (p) {
p = coord.convert(p);
if (Util.isArray(p.x) && !point.x.includes(p.x) || Util.isNumber(p.x) && point.x !== p.x) {
label.x = (label.x + p.x) / 2;
}
});
}
if (labelCfg.position) {
self.setLabelPosition(label, point, index, labelCfg.position);
}
var offsetPoint = self.getLabelOffset(labelCfg, index, total);
if (labelCfg.offsetX) {
offsetPoint.x += labelCfg.offsetX;
}
if (labelCfg.offsetY) {
offsetPoint.y += labelCfg.offsetY;
}
self.transLabelPoint(label);
label.start = {
x: label.x,
y: label.y
};
label.x += offsetPoint.x;
label.y += offsetPoint.y;
label.color = point.color;
return label;
},
setLabelPosition: function setLabelPosition() {},
transLabelPoint: function transLabelPoint(point) {
var self = this;
var coord = self.get('coord');
var tmpPoint = coord.applyMatrix(point.x, point.y, 1);
point.x = tmpPoint[0];
point.y = tmpPoint[1];
},
getOffsetVector: function getOffsetVector(point) {
var self = this;
var offset = point.offset || 0;
var coord = self.get('coord');
var vector;
if (coord.isTransposed) {
// 如果x,y翻转则偏移x
vector = coord.applyMatrix(offset, 0);
} else {
// 否则偏转y
vector = coord.applyMatrix(0, offset);
}
return vector;
},
// 获取默认的偏移量
getDefaultOffset: function getDefaultOffset(point) {
var self = this;
var offset = 0;
var coord = self.get('coord');
var vector = self.getOffsetVector(point);
if (coord.isTransposed) {
// 如果x,y翻转则偏移x
offset = vector[0];
} else {
// 否则偏转y
offset = vector[1];
}
var yScale = this.get('yScale');
if (yScale && point.point) {
// 仅考虑 y 单值的情况,多值的情况在这里不考虑
var yValue = point.point[yScale.field];
if (yValue < 0) {
offset = offset * -1; // 如果 y 值是负值,则反向
}
}
return offset;
},
// 获取文本的偏移位置x,y
getLabelOffset: function getLabelOffset(point, index, total) {
var self = this;
var offset = self.getDefaultOffset(point);
var coord = self.get('coord');
var transposed = coord.isTransposed;
var yField = transposed ? 'x' : 'y';
var factor = transposed ? 1 : -1; // y 方向上越大像素的坐标越小所以transposed时将系数变成
var offsetPoint = {
x: 0,
y: 0
};
if (index > 0 || total === 1) {
// 判断是否小于0
offsetPoint[yField] = offset * factor;
} else {
offsetPoint[yField] = offset * factor * -1;
}
return offsetPoint;
},
getLabelAlign: function getLabelAlign(point, index, total) {
var self = this;
var align = 'center';
var coord = self.get('coord');
if (coord.isTransposed) {
var offset = self.getDefaultOffset(point); // var vector = coord.applyMatrix(offset,0);
if (offset < 0) {
align = 'right';
} else if (offset === 0) {
align = 'center';
} else {
align = 'left';
}
if (total > 1 && index === 0) {
if (align === 'right') {
align = 'left';
} else if (align === 'left') {
align = 'right';
}
}
}
return align;
},
_getLabelValue: function _getLabelValue(origin, scales) {
if (!Util.isArray(scales)) {
scales = [scales];
}
var text = [];
Util.each(scales, function (scale) {
var value = origin[scale.field];
if (Util.isArray(value)) {
var tmp = [];
Util.each(value, function (subVal) {
tmp.push(scale.getText(subVal));
});
value = tmp;
} else {
value = scale.getText(value);
}
if (Util.isNil(value) || value === '') {
text.push(null);
}
text.push(value);
});
return text;
},
// 获取每个label的配置
_getLabelCfgs: function _getLabelCfgs(points) {
var self = this;
var labelCfg = this.get('labelCfg');
var scales = labelCfg.scales;
var defaultCfg = this.get('label');
var viewTheme = self.get('viewTheme') || Global;
var cfgs = [];
if (labelCfg.globalCfg && labelCfg.globalCfg.type) {
self.set('type', labelCfg.globalCfg.type);
}
Util.each(points, function (point, i) {
var cfg = {};
var origin = point[ORIGIN];
var originText = self._getLabelValue(origin, scales);
if (labelCfg.callback) {
// callback中应使用原始数据而不是数据字符串
var originValues = scales.map(function (scale) {
return origin[scale.field];
}); // 将point信息以及index信息也返回方便能够根据point以及index返回不同的配置
cfg = labelCfg.callback.apply(null, [].concat(originValues, [point, i]));
}
if (!cfg && cfg !== 0) {
cfgs.push(null);
return;
}
if (Util.isString(cfg) || Util.isNumber(cfg)) {
cfg = {
text: cfg
};
} else {
cfg.text = cfg.content || originText[0];
delete cfg.content;
}
cfg = Util.mix({}, defaultCfg, labelCfg.globalCfg || {}, cfg); // 兼容旧的源数据写在item.point中
point.point = origin;
cfg.point = origin;
if (cfg.htmlTemplate) {
cfg.useHtml = true;
cfg.text = cfg.htmlTemplate.call(null, cfg.text, point, i);
delete cfg.htmlTemplate;
}
if (cfg.formatter) {
cfg.text = cfg.formatter.call(null, cfg.text, point, i);
delete cfg.formatter;
}
if (cfg.label) {
// 兼容有些直接写在labelCfg.label的配置
var label = cfg.label;
delete cfg.label;
cfg = Util.mix(cfg, label);
}
if (cfg.textStyle) {
// 兼容旧写法globalCfg的offset优先级高
delete cfg.textStyle.offset;
var textStyle = cfg.textStyle;
if (Util.isFunction(textStyle)) {
cfg.textStyle = textStyle.call(null, cfg.text, point, i);
}
}
if (cfg.labelLine) {
cfg.labelLine = Util.mix({}, defaultCfg.labelLine, cfg.labelLine);
} // 因为 defaultCfg.textStyle 有可能是函数,所以这里可能没有把主题的 label 样式合进来
cfg.textStyle = Util.mix({}, defaultCfg.textStyle, viewTheme.label.textStyle, cfg.textStyle);
delete cfg.items;
cfgs.push(cfg);
});
this.set('labelItemCfgs', cfgs);
},
showLabels: function showLabels(points, shapes) {
var self = this;
var labelRenderer = self.get('labelRenderer');
var items = self.getLabelsItems(points, shapes);
shapes = [].concat(shapes);
var type = self.get('type');
items = self.adjustItems(items, shapes);
self.drawLines(items);
labelRenderer.set('items', items.filter(function (item, i) {
if (!item) {
shapes.splice(i, 1);
return false;
}
return true;
}));
if (type) {
labelRenderer.set('shapes', shapes);
labelRenderer.set('type', type);
labelRenderer.set('points', points);
}
labelRenderer.set('canvas', this.get('canvas'));
labelRenderer.draw();
},
destroy: function destroy() {
this.get('labelRenderer').destroy(); // 清理文本
GeomLabels.superclass.destroy.call(this);
}
}); // Util.assign(GeomLabels.prototype, Labels.LabelslabelRenderer);
module.exports = GeomLabels;