| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import { __assign, __read, __rest, __spreadArray } from "tslib";
- import { get, isFunction, memoize } from '@antv/util';
- import { fadeOut, onAnimateFinished, onAnimatesFinished, transition, transitionShape, } from '../../../animation';
- import { add, defined, ellipsisIt, getCallbackValue, hide, inRange, percentTransform, radToDeg, renderExtDo, scale, select, show, splitStyle, subStyleProps, wrapIt, } from '../../../util';
- import { CLASS_NAMES } from '../constant';
- import { processOverlap } from '../overlap';
- import { getFactor } from '../utils';
- import { getValuePos } from './line';
- import { filterExec, getCallbackStyle, getLabelVector, getLineTangentVector } from './utils';
- var angleNormalizer = function (angle) {
- var normalizedAngle = angle;
- while (normalizedAngle < 0)
- normalizedAngle += 360;
- return Math.round(normalizedAngle % 360);
- };
- var getAngle = memoize(function (v1, v2) {
- var _a = __read(v1, 2), x1 = _a[0], y1 = _a[1];
- var _b = __read(v2, 2), x2 = _b[0], y2 = _b[1];
- var _c = __read([x1 * x2 + y1 * y2, x1 * y2 - y1 * x2], 2), dot = _c[0], det = _c[1];
- return Math.atan2(det, dot);
- }, function (v1, v2) { return __spreadArray(__spreadArray([], __read(v1), false), __read(v2), false).join(); });
- /** to correct label rotation to avoid inverted character */
- function correctLabelRotation(_rotate) {
- var rotate = (_rotate + 360) % 180;
- if (!inRange(rotate, -90, 90))
- rotate += 180;
- return rotate;
- }
- /** get rotation from preset or layout */
- function getLabelRotation(datum, label, attr) {
- var _a;
- var labelAlign = attr.labelAlign;
- // if label rotate is set, use it
- var customRotate = (_a = label.style.transform) === null || _a === void 0 ? void 0 : _a.includes('rotate');
- if (customRotate)
- return label.getLocalEulerAngles();
- var rotate = 0;
- var labelVector = getLabelVector(datum.value, attr);
- var tangentVector = getLineTangentVector(datum.value, attr);
- if (labelAlign === 'horizontal')
- return 0;
- if (labelAlign === 'perpendicular')
- rotate = getAngle([1, 0], labelVector);
- else
- rotate = getAngle([tangentVector[0] < 0 ? -1 : 1, 0], tangentVector);
- return correctLabelRotation(radToDeg(rotate));
- }
- /** get the label align according to its tick and label angle */
- function getLabelStyle(value, rotate, attr) {
- var type = attr.type, labelAlign = attr.labelAlign;
- var labelVector = getLabelVector(value, attr);
- var labelAngle = angleNormalizer(rotate);
- var tickAngle = angleNormalizer(radToDeg(getAngle([1, 0], labelVector)));
- var textAlign = 'center';
- var textBaseline = 'middle';
- if (type === 'linear') {
- // tick 和 label 均为水平或垂直时,做快速判断
- if ([90, 270].includes(tickAngle) && labelAngle === 0) {
- textAlign = 'center';
- textBaseline = labelVector[1] === 1 ? 'top' : 'bottom';
- }
- else if (!(tickAngle % 180) && [90, 270].includes(labelAngle)) {
- textAlign = 'center';
- }
- // 根据 tick 和 label 的角度,判断 label 的对齐方式
- else if (tickAngle === 0) {
- if (inRange(labelAngle, 0, 90, false, true)) {
- textAlign = 'start';
- }
- else if (inRange(labelAngle, 0, 90) || inRange(labelAngle, 270, 360)) {
- textAlign = 'start';
- }
- }
- else if (tickAngle === 90) {
- if (inRange(labelAngle, 0, 90, false, true)) {
- textAlign = 'start';
- }
- else if (inRange(labelAngle, 90, 180) || inRange(labelAngle, 270, 360)) {
- textAlign = 'end';
- }
- }
- else if (tickAngle === 270) {
- if (inRange(labelAngle, 0, 90, false, true)) {
- textAlign = 'end';
- }
- else if (inRange(labelAngle, 90, 180) || inRange(labelAngle, 270, 360)) {
- textAlign = 'start';
- }
- }
- else if (tickAngle === 180) {
- if (labelAngle === 90) {
- textAlign = 'start';
- }
- else if (inRange(labelAngle, 0, 90) || inRange(labelAngle, 270, 360)) {
- textAlign = 'end';
- }
- }
- /**
- * todo tick 倾斜时的判断逻辑,该情况下坐标轴非垂直或水平
- */
- }
- else {
- // 弧线坐标轴 label 的对齐方式判断逻辑
- if (labelAlign === 'parallel') {
- if (inRange(tickAngle, 0, 180, true)) {
- textBaseline = 'top';
- }
- else {
- textBaseline = 'bottom';
- }
- }
- else if (labelAlign === 'horizontal') {
- if (inRange(tickAngle, 90, 270, false)) {
- textAlign = 'end';
- }
- else if (inRange(tickAngle, 270, 360, false) || inRange(tickAngle, 0, 90)) {
- textAlign = 'start';
- }
- }
- else if (labelAlign === 'perpendicular') {
- if (inRange(tickAngle, 90, 270)) {
- textAlign = 'end';
- }
- else {
- textAlign = 'start';
- }
- }
- }
- return { textAlign: textAlign, textBaseline: textBaseline };
- }
- function setRotateAndAdjustLabelAlign(rotate, group, attr) {
- group.setLocalEulerAngles(rotate);
- var value = group.__data__.value;
- var textStyle = getLabelStyle(value, rotate, attr);
- var label = group.querySelector(CLASS_NAMES.labelItem.class);
- if (label)
- applyTextStyle(label, textStyle);
- }
- function getLabelPos(datum, data, attr) {
- var showTick = attr.showTick, tickLength = attr.tickLength, tickDirection = attr.tickDirection, labelDirection = attr.labelDirection, labelSpacing = attr.labelSpacing;
- var index = data.indexOf(datum);
- var finalLabelSpacing = getCallbackValue(labelSpacing, [datum, index, data]);
- var _a = __read([getLabelVector(datum.value, attr), getFactor(labelDirection, tickDirection)], 2), labelVector = _a[0], unionFactor = _a[1];
- var extraLength = unionFactor === 1 ? getCallbackValue(showTick ? tickLength : 0, [datum, index, data]) : 0;
- var _b = __read(add(scale(labelVector, finalLabelSpacing + extraLength), getValuePos(datum.value, attr)), 2), x = _b[0], y = _b[1];
- return { x: x, y: y };
- }
- function formatter(datum, index, data, attr) {
- var labelFormatter = attr.labelFormatter;
- var element = isFunction(labelFormatter)
- ? function () { return renderExtDo(getCallbackValue(labelFormatter, [datum, index, data, getLabelVector(datum.value, attr)])); }
- : function () { return renderExtDo(datum.label || ''); };
- return element;
- }
- function applyTextStyle(node, style) {
- if (node.nodeName === 'text')
- node.attr(style);
- }
- function overlapHandler(attr) {
- processOverlap(this.node().childNodes, attr, {
- hide: hide,
- show: show,
- rotate: function (label, angle) {
- setRotateAndAdjustLabelAlign(+angle, label, attr);
- },
- ellipsis: function (label, len, suffix) {
- if (len === void 0) { len = Infinity; }
- label && ellipsisIt(label, len, suffix);
- },
- wrap: function (label, width, lines) {
- label && wrapIt(label, width, lines);
- },
- getTextShape: function (label) { return label.querySelector('text'); },
- });
- }
- function renderLabel(container, datum, data, style, attr) {
- var index = data.indexOf(datum);
- var label = select(container)
- .append(formatter(datum, index, data, attr))
- .attr('className', CLASS_NAMES.labelItem.name)
- .node();
- var _a = __read(splitStyle(getCallbackStyle(style, [datum, index, data])), 2), labelStyle = _a[0], _b = _a[1], transform = _b.transform, groupStyle = __rest(_b, ["transform"]);
- percentTransform(container, transform);
- var rotate = getLabelRotation(datum, container, attr);
- container.setLocalEulerAngles(+rotate);
- applyTextStyle(label, __assign(__assign({}, getLabelStyle(datum.value, rotate, attr)), labelStyle));
- // todo G transform 存在问题,需要二次设置
- percentTransform(container, transform);
- container.attr(groupStyle);
- return label;
- }
- export function renderLabels(container, data, attr, animate) {
- var finalData = filterExec(data, attr.labelFilter);
- var style = subStyleProps(attr, 'label');
- return container
- .selectAll(CLASS_NAMES.label.class)
- .data(finalData, function (d, i) { return i; })
- .join(function (enter) {
- return enter
- .append('g')
- .attr('className', CLASS_NAMES.label.name)
- .transition(function (datum) {
- renderLabel(this, datum, data, style, attr);
- this.attr(getLabelPos(datum, data, attr));
- this.__bbox__ = datum.bbox;
- return null;
- })
- .call(function () { return overlapHandler.call(container, attr); });
- }, function (update) {
- return update
- .transition(function (datum) {
- var prevLabel = this.querySelector(CLASS_NAMES.labelItem.class);
- var label = renderLabel(this, datum, data, style, attr);
- var shapeAnimation = transitionShape(prevLabel, label, animate.update);
- var animation = transition(this, getLabelPos(datum, data, attr), animate.update);
- this.__bbox__ = datum.bbox;
- return __spreadArray(__spreadArray([], __read(shapeAnimation), false), [animation], false);
- })
- .call(function (selection) {
- var transitions = get(selection, '_transitions').flat().filter(defined);
- onAnimatesFinished(transitions, function () { return overlapHandler.call(container, attr); });
- });
- }, function (exit) {
- return exit.transition(function () {
- var _this = this;
- var animation = fadeOut(this, animate.exit);
- onAnimateFinished(animation, function () { return select(_this).remove(); });
- return animation;
- });
- })
- .transitions();
- }
- //# sourceMappingURL=labels.js.map
|