UNPKG

cione-comp-lib

Version:

`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`

385 lines (384 loc) 13.8 kB
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 };