cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
385 lines (384 loc) • 13.8 kB
JavaScript
import { parsePercent } from "../../util/number.mjs";
import "../../util/graphic.mjs";
import { each, isNumber } from "../../../../zrender/lib/core/util.mjs";
import { limitTurnAngle, limitSurfaceAngle } from "../../label/labelGuideHelper.mjs";
import { shiftLayoutOnY } from "../../label/labelLayoutHelper.mjs";
import Point from "../../../../zrender/lib/core/Point.mjs";
var RADIAN = Math.PI / 180;
function adjustSingleSide(list, cx, cy, r, dir, viewWidth, viewHeight, viewLeft, viewTop, farthestX) {
if (list.length < 2) {
return;
}
function recalculateXOnSemiToAlignOnEllipseCurve(semi) {
var rB = semi.rB;
var rB2 = rB * rB;
for (var i2 = 0; i2 < semi.list.length; i2++) {
var item = semi.list[i2];
var dy = Math.abs(item.label.y - cy);
var rA = r + item.len;
var rA2 = rA * rA;
var dx2 = Math.sqrt((1 - Math.abs(dy * dy / rB2)) * rA2);
var newX = cx + (dx2 + item.len2) * dir;
var deltaX = newX - item.label.x;
var newTargetWidth = item.targetTextWidth - deltaX * dir;
constrainTextWidth(item, newTargetWidth, true);
item.label.x = newX;
}
}
function recalculateX(items) {
var topSemi = {
list: [],
maxY: 0
};
var bottomSemi = {
list: [],
maxY: 0
};
for (var i2 = 0; i2 < items.length; i2++) {
if (items[i2].labelAlignTo !== "none") {
continue;
}
var item = items[i2];
var semi = item.label.y > cy ? bottomSemi : topSemi;
var dy = Math.abs(item.label.y - cy);
if (dy >= semi.maxY) {
var dx2 = item.label.x - cx - item.len2 * dir;
var rA = r + item.len;
var rB = Math.abs(dx2) < rA ? Math.sqrt(dy * dy / (1 - dx2 * dx2 / rA / rA)) : rA;
semi.rB = rB;
semi.maxY = dy;
}
semi.list.push(item);
}
recalculateXOnSemiToAlignOnEllipseCurve(topSemi);
recalculateXOnSemiToAlignOnEllipseCurve(bottomSemi);
}
var len = list.length;
for (var i = 0; i < len; i++) {
if (list[i].position === "outer" && list[i].labelAlignTo === "labelLine") {
var dx = list[i].label.x - farthestX;
list[i].linePoints[1][0] += dx;
list[i].label.x = farthestX;
}
}
if (shiftLayoutOnY(list, viewTop, viewTop + viewHeight)) {
recalculateX(list);
}
}
function avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop) {
var leftList = [];
var rightList = [];
var leftmostX = Number.MAX_VALUE;
var rightmostX = -Number.MAX_VALUE;
for (var i = 0; i < labelLayoutList.length; i++) {
var label = labelLayoutList[i].label;
if (isPositionCenter(labelLayoutList[i])) {
continue;
}
if (label.x < cx) {
leftmostX = Math.min(leftmostX, label.x);
leftList.push(labelLayoutList[i]);
} else {
rightmostX = Math.max(rightmostX, label.x);
rightList.push(labelLayoutList[i]);
}
}
for (var i = 0; i < labelLayoutList.length; i++) {
var layout = labelLayoutList[i];
if (!isPositionCenter(layout) && layout.linePoints) {
if (layout.labelStyleWidth != null) {
continue;
}
var label = layout.label;
var linePoints = layout.linePoints;
var targetTextWidth = void 0;
if (layout.labelAlignTo === "edge") {
if (label.x < cx) {
targetTextWidth = linePoints[2][0] - layout.labelDistance - viewLeft - layout.edgeDistance;
} else {
targetTextWidth = viewLeft + viewWidth - layout.edgeDistance - linePoints[2][0] - layout.labelDistance;
}
} else if (layout.labelAlignTo === "labelLine") {
if (label.x < cx) {
targetTextWidth = leftmostX - viewLeft - layout.bleedMargin;
} else {
targetTextWidth = viewLeft + viewWidth - rightmostX - layout.bleedMargin;
}
} else {
if (label.x < cx) {
targetTextWidth = label.x - viewLeft - layout.bleedMargin;
} else {
targetTextWidth = viewLeft + viewWidth - label.x - layout.bleedMargin;
}
}
layout.targetTextWidth = targetTextWidth;
constrainTextWidth(layout, targetTextWidth);
}
}
adjustSingleSide(rightList, cx, cy, r, 1, viewWidth, viewHeight, viewLeft, viewTop, rightmostX);
adjustSingleSide(leftList, cx, cy, r, -1, viewWidth, viewHeight, viewLeft, viewTop, leftmostX);
for (var i = 0; i < labelLayoutList.length; i++) {
var layout = labelLayoutList[i];
if (!isPositionCenter(layout) && layout.linePoints) {
var label = layout.label;
var linePoints = layout.linePoints;
var isAlignToEdge = layout.labelAlignTo === "edge";
var padding = label.style.padding;
var paddingH = padding ? padding[1] + padding[3] : 0;
var extraPaddingH = label.style.backgroundColor ? 0 : paddingH;
var realTextWidth = layout.rect.width + extraPaddingH;
var dist = linePoints[1][0] - linePoints[2][0];
if (isAlignToEdge) {
if (label.x < cx) {
linePoints[2][0] = viewLeft + layout.edgeDistance + realTextWidth + layout.labelDistance;
} else {
linePoints[2][0] = viewLeft + viewWidth - layout.edgeDistance - realTextWidth - layout.labelDistance;
}
} else {
if (label.x < cx) {
linePoints[2][0] = label.x + layout.labelDistance;
} else {
linePoints[2][0] = label.x - layout.labelDistance;
}
linePoints[1][0] = linePoints[2][0] + dist;
}
linePoints[1][1] = linePoints[2][1] = label.y;
}
}
}
function constrainTextWidth(layout, availableWidth, forceRecalculate) {
if (forceRecalculate === void 0) {
forceRecalculate = false;
}
if (layout.labelStyleWidth != null) {
return;
}
var label = layout.label;
var style = label.style;
var textRect = layout.rect;
var bgColor = style.backgroundColor;
var padding = style.padding;
var paddingH = padding ? padding[1] + padding[3] : 0;
var overflow = style.overflow;
var oldOuterWidth = textRect.width + (bgColor ? 0 : paddingH);
if (availableWidth < oldOuterWidth || forceRecalculate) {
var oldHeight = textRect.height;
if (overflow && overflow.match("break")) {
label.setStyle("backgroundColor", null);
label.setStyle("width", availableWidth - paddingH);
var innerRect = label.getBoundingRect();
label.setStyle("width", Math.ceil(innerRect.width));
label.setStyle("backgroundColor", bgColor);
} else {
var availableInnerWidth = availableWidth - paddingH;
var newWidth = availableWidth < oldOuterWidth ? availableInnerWidth : forceRecalculate ? availableInnerWidth > layout.unconstrainedWidth ? null : availableInnerWidth : null;
label.setStyle("width", newWidth);
}
var newRect = label.getBoundingRect();
textRect.width = newRect.width;
var margin = (label.style.margin || 0) + 2.1;
textRect.height = newRect.height + margin;
textRect.y -= (textRect.height - oldHeight) / 2;
}
}
function isPositionCenter(sectorShape) {
return sectorShape.position === "center";
}
function pieLabelLayout(seriesModel) {
var data = seriesModel.getData();
var labelLayoutList = [];
var cx;
var cy;
var hasLabelRotate = false;
var minShowLabelRadian = (seriesModel.get("minShowLabelAngle") || 0) * RADIAN;
var viewRect = data.getLayout("viewRect");
var r = data.getLayout("r");
var viewWidth = viewRect.width;
var viewLeft = viewRect.x;
var viewTop = viewRect.y;
var viewHeight = viewRect.height;
function setNotShow(el) {
el.ignore = true;
}
function isLabelShown(label2) {
if (!label2.ignore) {
return true;
}
for (var key in label2.states) {
if (label2.states[key].ignore === false) {
return true;
}
}
return false;
}
data.each(function(idx) {
var sector = data.getItemGraphicEl(idx);
var sectorShape = sector.shape;
var label2 = sector.getTextContent();
var labelLine2 = sector.getTextGuideLine();
var itemModel = data.getItemModel(idx);
var labelModel = itemModel.getModel("label");
var labelPosition = labelModel.get("position") || itemModel.get(["emphasis", "label", "position"]);
var labelDistance = labelModel.get("distanceToLabelLine");
var labelAlignTo = labelModel.get("alignTo");
var edgeDistance = parsePercent(labelModel.get("edgeDistance"), viewWidth);
var bleedMargin = labelModel.get("bleedMargin");
var labelLineModel = itemModel.getModel("labelLine");
var labelLineLen = labelLineModel.get("length");
labelLineLen = parsePercent(labelLineLen, viewWidth);
var labelLineLen2 = labelLineModel.get("length2");
labelLineLen2 = parsePercent(labelLineLen2, viewWidth);
if (Math.abs(sectorShape.endAngle - sectorShape.startAngle) < minShowLabelRadian) {
each(label2.states, setNotShow);
label2.ignore = true;
if (labelLine2) {
each(labelLine2.states, setNotShow);
labelLine2.ignore = true;
}
return;
}
if (!isLabelShown(label2)) {
return;
}
var midAngle = (sectorShape.startAngle + sectorShape.endAngle) / 2;
var nx = Math.cos(midAngle);
var ny = Math.sin(midAngle);
var textX;
var textY;
var linePoints2;
var textAlign;
cx = sectorShape.cx;
cy = sectorShape.cy;
var isLabelInside = labelPosition === "inside" || labelPosition === "inner";
if (labelPosition === "center") {
textX = sectorShape.cx;
textY = sectorShape.cy;
textAlign = "center";
} else {
var x1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * nx : sectorShape.r * nx) + cx;
var y1 = (isLabelInside ? (sectorShape.r + sectorShape.r0) / 2 * ny : sectorShape.r * ny) + cy;
textX = x1 + nx * 3;
textY = y1 + ny * 3;
if (!isLabelInside) {
var x2 = x1 + nx * (labelLineLen + r - sectorShape.r);
var y2 = y1 + ny * (labelLineLen + r - sectorShape.r);
var x3 = x2 + (nx < 0 ? -1 : 1) * labelLineLen2;
var y3 = y2;
if (labelAlignTo === "edge") {
textX = nx < 0 ? viewLeft + edgeDistance : viewLeft + viewWidth - edgeDistance;
} else {
textX = x3 + (nx < 0 ? -labelDistance : labelDistance);
}
textY = y3;
linePoints2 = [[x1, y1], [x2, y2], [x3, y3]];
}
textAlign = isLabelInside ? "center" : labelAlignTo === "edge" ? nx > 0 ? "right" : "left" : nx > 0 ? "left" : "right";
}
var PI = Math.PI;
var labelRotate = 0;
var rotate = labelModel.get("rotate");
if (isNumber(rotate)) {
labelRotate = rotate * (PI / 180);
} else if (labelPosition === "center") {
labelRotate = 0;
} else if (rotate === "radial" || rotate === true) {
var radialAngle = nx < 0 ? -midAngle + PI : -midAngle;
labelRotate = radialAngle;
} else if (rotate === "tangential" && labelPosition !== "outside" && labelPosition !== "outer") {
var rad = Math.atan2(nx, ny);
if (rad < 0) {
rad = PI * 2 + rad;
}
var isDown = ny > 0;
if (isDown) {
rad = PI + rad;
}
labelRotate = rad - PI;
}
hasLabelRotate = !!labelRotate;
label2.x = textX;
label2.y = textY;
label2.rotation = labelRotate;
label2.setStyle({
verticalAlign: "middle"
});
if (!isLabelInside) {
var textRect = label2.getBoundingRect().clone();
textRect.applyTransform(label2.getComputedTransform());
var margin = (label2.style.margin || 0) + 2.1;
textRect.y -= margin / 2;
textRect.height += margin;
labelLayoutList.push({
label: label2,
labelLine: labelLine2,
position: labelPosition,
len: labelLineLen,
len2: labelLineLen2,
minTurnAngle: labelLineModel.get("minTurnAngle"),
maxSurfaceAngle: labelLineModel.get("maxSurfaceAngle"),
surfaceNormal: new Point(nx, ny),
linePoints: linePoints2,
textAlign,
labelDistance,
labelAlignTo,
edgeDistance,
bleedMargin,
rect: textRect,
unconstrainedWidth: textRect.width,
labelStyleWidth: label2.style.width
});
} else {
label2.setStyle({
align: textAlign
});
var selectState2 = label2.states.select;
if (selectState2) {
selectState2.x += label2.x;
selectState2.y += label2.y;
}
}
sector.setTextConfig({
inside: isLabelInside
});
});
if (!hasLabelRotate && seriesModel.get("avoidLabelOverlap")) {
avoidOverlap(labelLayoutList, cx, cy, r, viewWidth, viewHeight, viewLeft, viewTop);
}
for (var i = 0; i < labelLayoutList.length; i++) {
var layout = labelLayoutList[i];
var label = layout.label;
var labelLine = layout.labelLine;
var notShowLabel = isNaN(label.x) || isNaN(label.y);
if (label) {
label.setStyle({
align: layout.textAlign
});
if (notShowLabel) {
each(label.states, setNotShow);
label.ignore = true;
}
var selectState = label.states.select;
if (selectState) {
selectState.x += label.x;
selectState.y += label.y;
}
}
if (labelLine) {
var linePoints = layout.linePoints;
if (notShowLabel || !linePoints) {
each(labelLine.states, setNotShow);
labelLine.ignore = true;
} else {
limitTurnAngle(linePoints, layout.minTurnAngle);
limitSurfaceAngle(linePoints, layout.surfaceNormal, layout.maxSurfaceAngle);
labelLine.setShape({
points: linePoints
});
label.__hostTarget.textGuideLineConfig = {
anchor: new Point(linePoints[0][0], linePoints[0][1])
};
}
}
}
}
export { pieLabelLayout as default };