UNPKG

@antv/g2plot

Version:

G2 Plot, a market of plots built with the Grammar of Graphics'

219 lines 7.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var g_1 = require("@antv/g"); var g2_1 = require("@antv/g2"); var _ = tslib_1.__importStar(require("@antv/util")); var DEFAULT_SIZE = 12; var TOLERANCE = 0.01; var MAX_ITERATION = 100; var MIN_HEIGHT = 12; function getRange(points) { var maxHeight = -Infinity; var min = Infinity; var max = -Infinity; _.each(points, function (p) { min = Math.min(p.x, min); max = Math.max(p.x, max); var height = Math.abs(p.y[0] - p.y[1]); maxHeight = Math.max(maxHeight, height); }); return { xRange: [min, max], maxHeight: maxHeight, }; } function interpolateY(x, points, index) { var leftPoint = points[0]; var rightPoint = points[points.length - 1]; _.each(points, function (p) { if (p.x === x) { return p.y[index]; } if (p.x < x && p.x > leftPoint.x) { leftPoint = p; } if (p.x > x && p.x < rightPoint.x) { rightPoint = p; } }); var t = (x - leftPoint.x) / (rightPoint.x - leftPoint.x); return leftPoint.y[index] * (1 - t) + rightPoint.y[index] * t; } function getXIndex(data, x) { // tslint:disable-next-line: prefer-for-of var i; for (i = 0; i < data.length; i++) { var d = data[i]; if (d.x === x || d.x > x) { break; } } return i; } var AreaLabel = /** @class */ (function (_super) { tslib_1.__extends(AreaLabel, _super); function AreaLabel() { var _this = _super !== null && _super.apply(this, arguments) || this; _this.scaleFactor = []; return _this; } AreaLabel.prototype.showLabels = function (points, shapes) { var _this = this; // 获取堆叠字段 var stackField = this.get('element').get('attrs').color.scales[0].field; // 根据stackField将point分组 var groupedPoints = this._groupPoints(points, stackField); var labelPoints = []; _.each(groupedPoints, function (pointArray, name) { var labelPoint = _this._drawLabel(pointArray, name); if (labelPoint) { labelPoints.push(_.mix({}, pointArray[0], labelPoint)); _this.scaleFactor.push(labelPoint.scaleFactor); } }); _super.prototype.showLabels.call(this, labelPoints, shapes); var labelOptions = this.get('labelOptions'); if (labelOptions.autoScale) { this._adjuestLabelSize(); } }; AreaLabel.prototype._groupPoints = function (points, field) { var groupedPoints = {}; _.each(points, function (p) { var value = p._origin[field]; if (!_.has(groupedPoints, value)) { groupedPoints[value] = []; } groupedPoints[value].push(p); }); return groupedPoints; }; AreaLabel.prototype._drawLabel = function (points, name) { var _a = getRange(points), xRange = _a.xRange, maxHeight = _a.maxHeight; // 根据area宽度在x方向各点间做插值 var resolution = xRange[1] - xRange[0]; var interpolatedPoints = this._getInterpolatedPoints(xRange[0], resolution, points); // 获取label的bbox var bbox = this._getLabelBbox(name); var fitOption = { xRange: xRange, aspect: bbox.width / bbox.height, data: interpolatedPoints, justTest: true, }; var height = this._bisection(MIN_HEIGHT, maxHeight, this._testFit, fitOption, TOLERANCE, MAX_ITERATION); if (height === null) { return; } fitOption.justTest = false; var fit = this._testFit(fitOption); fit.x = fit.x; fit.y = fit.y0 + (fit.y1 - fit.y0) / 2; fit.scaleFactor = (height / bbox.height) * 0.4; return fit; }; AreaLabel.prototype._getInterpolatedPoints = function (minX, resolution, points) { var interpolatedPoints = []; var step = 2; for (var i = minX; i < resolution; i += step) { var y0 = interpolateY(i, points, 0); var y1 = interpolateY(i, points, 1); interpolatedPoints.push({ x: i, y: [y0, y1], }); } return interpolatedPoints; }; AreaLabel.prototype._bisection = function (min, max, test, testOption, tolerance, maxIteration) { for (var i = 0; i < maxIteration; i++) { var middle = (min + max) / 2; var options = testOption; options.height = middle; options.width = middle * options.aspect; var passesTest = test(options); var withinTolerance = (max - min) / 2 < tolerance; if (passesTest && withinTolerance) { return middle; } if (passesTest) { min = middle; } else { max = middle; } } return null; }; AreaLabel.prototype._testFit = function (option) { var xRange = option.xRange, width = option.width, height = option.height, data = option.data, justTest = option.justTest; for (var i = 0; i < data.length; i++) { var d = data[i]; var x0 = d.x; var x1 = x0 + width; if (x1 > xRange[1]) { break; } var x1_index = getXIndex(data, x1); var ceiling = -Infinity; var ceilingFloor = null; // 保存ceiling时对应的bottom位置,ceil和floor不一定是一对坐标 var floor = Infinity; for (var j = i; j < x1_index; j++) { var top_1 = data[j].y[1]; var bottom = data[j].y[0]; if (bottom < floor) { floor = bottom; } if (top_1 > ceiling) { ceiling = top_1; ceilingFloor = bottom; } if (floor - ceiling < height) { break; } } if (floor - ceiling >= height) { if (justTest) { return true; } return { x: x0, y0: ceiling, y1: ceilingFloor, width: width, height: height, }; } } return false; }; AreaLabel.prototype._getLabelBbox = function (text) { var plot = this.get('labelOptions').plot; var labelStyle = _.clone(plot.theme.label.textStyle); labelStyle.fontSize = DEFAULT_SIZE; var tShape = new g_1.Text({ attrs: tslib_1.__assign({ text: text, x: 0, y: 0 }, labelStyle), }); return tShape.getBBox(); }; AreaLabel.prototype._adjuestLabelSize = function () { var _this = this; var renderer = this.get('labelsRenderer'); var labels = renderer.get('group').get('children'); var view = this.get('element').get('view'); _.each(labels, function (label, index) { var scaleFactor = _this.scaleFactor[index]; label.attr('fontSize', DEFAULT_SIZE); label.transform([ ['t', -label.attr('x'), -label.attr('y')], ['s', scaleFactor, scaleFactor], ['t', label.attr('x'), label.attr('y')], ]); }); view.get('canvas').draw(); }; return AreaLabel; }(g2_1.ElementLabels)); g2_1.registerElementLabels('area', AreaLabel); //# sourceMappingURL=area-label.js.map