@antv/g2plot
Version:
G2 Plot, a market of plots built with the Grammar of Graphics'
335 lines • 13.3 kB
JavaScript
import { BBox } from '@antv/g';
import * as _ from '@antv/util';
/**
* 处理图表padding的逻辑:
* 注册参与padding的自定义组件
*/
var PaddingController = /** @class */ (function () {
function PaddingController(cfg) {
this.innerPaddingComponents = [];
this.outerPaddingComponents = [];
this.plot = cfg.plot;
}
PaddingController.prototype.registerPadding = function (component, type, checkIfExist) {
if (type === void 0) { type = 'outer'; }
if (checkIfExist === void 0) { checkIfExist = false; }
if (type === 'inner') {
if (checkIfExist) {
if (!this.innerPaddingComponents.find(function (c) { return c == component; })) {
this.innerPaddingComponents.push(component);
}
}
else {
this.innerPaddingComponents.push(component);
}
}
else {
if (checkIfExist) {
if (!this.outerPaddingComponents.find(function (c) { return c == component; })) {
this.outerPaddingComponents.push(component);
}
}
else {
this.outerPaddingComponents.push(component);
}
}
};
/**
* 清除已经注册的元素
*/
PaddingController.prototype.clear = function () {
this.innerPaddingComponents = [];
// 一些组件是在view渲染完成之后渲染初始化的
// TODO: afterRender的什么时候清除
this.outerPaddingComponents = _.filter(this.outerPaddingComponents, function (component) { return component.afterRender; });
};
PaddingController.prototype.clearOuterComponents = function () {
_.each(this.outerPaddingComponents, function (component) {
if (component.afterRender) {
component.destroy();
}
});
this.outerPaddingComponents = [];
};
PaddingController.prototype.getPadding = function () {
var props = this.plot.options;
var padding = props.padding ? props.padding : this.plot.config.theme.padding;
if (padding === 'auto') {
return [0, 0, 0, 0];
}
return padding;
};
/** view层的padding计算 */
PaddingController.prototype.processAutoPadding = function () {
var padding = this._getInnerAutoPadding();
this.plot.updateConfig({
padding: padding,
});
this.plot.render();
};
PaddingController.prototype.processOuterPadding = function () {
var viewMinX = this.plot.layerBBox.minX;
var viewMaxX = this.plot.layerBBox.maxX;
var viewMinY = this.plot.layerBBox.minY;
var viewMaxY = this.plot.layerBBox.maxY;
_.each(this.outerPaddingComponents, function (component) {
var position = component.position;
var _a = component.getBBox(), minX = _a.minX, maxX = _a.maxX, minY = _a.minY, maxY = _a.maxY;
if (maxY >= viewMinY && maxY <= viewMaxY && position === 'top') {
viewMinY = maxY;
}
if (minY >= viewMinY && minY <= viewMaxY && position === 'bottom') {
viewMaxY = minY;
}
if (maxX > viewMinX && maxX <= viewMaxX && position === 'left') {
viewMinX = maxX;
}
if (minX >= viewMinX && maxX <= viewMaxX && position === 'right') {
viewMaxX = minX;
}
});
return new BBox(viewMinX, viewMinY, viewMaxX - viewMinX, viewMaxY - viewMinY);
};
PaddingController.prototype._getInnerAutoPadding = function () {
var props = this.plot.options;
var view = this.plot.view;
var viewRange = view.get('viewRange');
var maxX = viewRange.maxX, maxY = viewRange.maxY;
var bleeding = this.plot.config.theme.bleeding;
if (_.isArray(bleeding)) {
_.each(bleeding, function (it, index) {
if (typeof bleeding[index] === 'function') {
bleeding[index] = bleeding[index](props);
}
});
}
this.plot.config.theme.legend.margin = bleeding;
this.bleeding = _.clone(bleeding);
// 参与auto padding的components: axis legend
var components_bbox = [view.get('panelRange')];
this._getAxis(view, components_bbox);
var box = this._mergeBBox(components_bbox);
this._getLegend(view, components_bbox, box);
box = this._mergeBBox(components_bbox);
// 参与auto padding的自定义组件
var components = this.innerPaddingComponents;
_.each(components, function (obj) {
var component = obj;
var bbox = component.getBBox();
components_bbox.push(bbox);
});
box = this._mergeBBox(components_bbox);
var minY = box.minY;
/** 极坐标下padding计算错误问题 */
if (minY === viewRange.minY) {
minY = 0;
}
var padding = [
0 - minY + this.bleeding[0],
box.maxX - maxX + this.bleeding[1],
box.maxY - maxY + this.bleeding[2],
0 - box.minX + this.bleeding[3],
];
this.adjustAxisPadding(view, padding);
// label、annotation等
var panelPadding = this._getPanel(view, box);
padding[0] += panelPadding[0];
padding[1] += panelPadding[1];
padding[2] += panelPadding[2];
padding[3] += panelPadding[3];
return padding;
};
PaddingController.prototype._getAxis = function (view, bboxes) {
var axes = view.get('axisController').axes;
if (axes.length > 0) {
_.each(axes, function (a) {
var axis = a;
var bbox = axis.get('group').getBBox();
bboxes.push(bbox);
});
}
};
PaddingController.prototype._getLegend = function (view, bboxes, box) {
var _this = this;
var viewRange = view.get('viewRange');
var legends = view.get('legendController').legends;
if (legends.length > 0) {
_.each(legends, function (l) {
var legend = l;
_this._adjustLegend(legend, view, box);
var legendBBox = legend.getBBox();
var width = legendBBox.width, height = legendBBox.height;
var x = 0;
var y = 0;
var position = legend.get('position').split('-');
if (position[0] === 'right') {
x = viewRange.maxX;
y = legendBBox.minY;
}
if (position[0] === 'left') {
x = box.minX - width;
y = legendBBox.minY;
}
if (position[0] === 'top') {
x = legendBBox.minX;
y = -height;
}
if (position[0] === 'bottom') {
x = legendBBox.minX;
y = viewRange.maxY + height;
}
var bbox = new BBox(x, y, width, height);
bboxes.push(bbox);
var innerPadding = _this._getLegendInnerPadding(legend);
_this._mergeBleeding(innerPadding);
});
}
};
PaddingController.prototype._getPanel = function (view, box) {
var groups = [];
var geoms = view.get('elements');
_.each(geoms, function (geom) {
if (geom.get('labelController')) {
var labelContainer = geom.get('labelController').labelsContainer;
if (labelContainer) {
groups.push(labelContainer);
}
}
});
var minX = Infinity;
var maxX = -Infinity;
var minY = Infinity;
var maxY = -Infinity;
_.each(groups, function (group) {
var children = group.get('children');
children.forEach(function (child) {
if (child.type === 'group' && child.get('children').length === 0) {
return;
}
var bbox = child.getBBox();
if (bbox.minX < minX) {
minX = bbox.minX;
}
if (bbox.maxX > maxX) {
maxX = bbox.maxX;
}
if (bbox.minY < minY) {
minY = bbox.minY;
}
if (bbox.maxY > maxY) {
maxY = bbox.maxY;
}
});
});
var panelRange = view.get('panelRange');
//right
var rightDist = Math.max(maxX - parseFloat(panelRange.maxX), 0);
if (rightDist > 0) {
var ratio = panelRange.width / (panelRange.width + rightDist);
rightDist *= ratio;
}
//left
var leftDist = Math.max(parseFloat(panelRange.minX) - minX, 0);
if (leftDist > 0) {
var ratio = panelRange.width / (panelRange.width + leftDist);
leftDist *= ratio;
}
//top
var topDist = Math.max(parseFloat(panelRange.minY) - minY, 0);
if (topDist > 0) {
var ratio = panelRange.height / (panelRange.height + topDist);
topDist *= ratio;
}
//bottom
var bottomDist = Math.max(maxY - parseFloat(panelRange.maxY), 0);
if (bottomDist > 0) {
var ratio = panelRange.height / (panelRange.height + bottomDist);
bottomDist *= ratio;
}
return [topDist, rightDist, bottomDist, leftDist];
};
PaddingController.prototype._mergeBBox = function (bboxes) {
var minX = Infinity;
var maxX = -Infinity;
var minY = Infinity;
var maxY = -Infinity;
_.each(bboxes, function (bbox) {
var box = bbox;
minX = Math.min(box.minX, minX);
maxX = Math.max(box.maxX, maxX);
minY = Math.min(box.minY, minY);
maxY = Math.max(box.maxY, maxY);
});
return { minX: minX, maxX: maxX, minY: minY, maxY: maxY };
// return new BBox(minX, minY, maxX - minX, maxY - minY);
};
PaddingController.prototype._adjustLegend = function (legend, view, box) {
var position = legend.get('position').split('-');
var container = legend.get('container');
var bbox = container.getBBox();
var _a = view.get('viewRange'), width = _a.width, height = _a.height, maxX = _a.maxX, minX = _a.minX, maxY = _a.maxY, minY = _a.minY;
if (position[0] === 'right') {
container.move(width, minY);
}
if (position[0] === 'left') {
container.move(box.minX - bbox.width, minY);
}
if (position[0] === 'top') {
container.move(0, box.minY - bbox.height);
}
if (position[0] === 'bottom') {
container.move(0, Math.max(maxY, box.maxY));
}
};
PaddingController.prototype._getLegendInnerPadding = function (legend) {
var innerPadding = this.plot.theme.legend.innerPadding;
var position = legend.get('position').split('-');
if (position[0] === 'top') {
return [innerPadding[0], 0, 0, 0];
}
if (position[0] === 'bottom') {
return [0, 0, innerPadding[2], 0];
}
if (position[0] === 'left') {
return [0, 0, 0, innerPadding[3]];
}
if (position[0] === 'right') {
return [0, innerPadding[1], 0, 0];
}
};
PaddingController.prototype._mergeBleeding = function (source) {
var target = this.bleeding;
if (source.length !== target.length) {
return;
}
for (var i = 0; i < source.length; i++) {
target[i] += source[i];
}
};
PaddingController.prototype.adjustAxisPadding = function (view, padding) {
// 3.6.x Axis组件的 autoRotate padding 修正
var xAxis = view.get('axisController').axes[0];
if (!xAxis || !xAxis.get('autoRotateLabel') || !xAxis.getOffsetByRotateAngle) {
return;
}
var labelRenderer = xAxis.get('labelRenderer');
var labels = labelRenderer.getLabels();
var curOffset = xAxis.getOffsetByRotateAngle(xAxis.get('autoRotateAngle'));
var curTotalWidth = Math.abs(xAxis.get('end').x - xAxis.get('start').x);
// 如果只有一项数据, 平均宽度 = 总宽
var curAvgWidth = curTotalWidth;
// 当多项数据时,根据 label 位置计算均宽
if (labels.length > 1) {
curAvgWidth = Math.abs(labels[1].attr('x') - labels[0].attr('x'));
}
var newTotalWidth = curTotalWidth - padding[1] - padding[3];
var newAvgWidth = (curAvgWidth * newTotalWidth) / curTotalWidth;
var newOffset = xAxis.getOffsetByRotateAngle(xAxis.getAutoRotateAngleByAvgWidth(newAvgWidth));
if (newOffset > curOffset) {
padding[2] += newOffset - curOffset;
}
};
return PaddingController;
}());
export default PaddingController;
//# sourceMappingURL=padding.js.map