mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-24 01:40:06 +00:00
增加Pie对LabelLine的lineEndX的支持
This commit is contained in:
@@ -76,6 +76,7 @@ slug: /changelog
|
|||||||
|
|
||||||
日志详情:
|
日志详情:
|
||||||
|
|
||||||
|
* (2023.08.08) 增加`Pie`对`LabelLine`的`lineEndX`的支持
|
||||||
* (2023.08.05) 整理`Examples`的代码,删除不必要的用例
|
* (2023.08.05) 整理`Examples`的代码,删除不必要的用例
|
||||||
* (2023.08.04) 增加`LabelLine`的`lineEndX`可设置引导线固定X位置的支持
|
* (2023.08.04) 增加`LabelLine`的`lineEndX`可设置引导线固定X位置的支持
|
||||||
* (2023.08.04) 增加`Ring`的`avoidLabelOverlap`避免文本堆叠的支持 (#247)
|
* (2023.08.04) 增加`Ring`的`avoidLabelOverlap`避免文本堆叠的支持 (#247)
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ namespace XCharts.Runtime
|
|||||||
set { if (PropertyUtil.SetStruct(ref m_LineColor, value)) SetVerticesDirty(); }
|
set { if (PropertyUtil.SetStruct(ref m_LineColor, value)) SetVerticesDirty(); }
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// the angle of visual guild line.
|
/// the angle of visual guild line. Valid for broken line and curve line. Invalid in Pie.
|
||||||
/// |视觉引导线的固定角度。对折线和曲线有效。
|
/// |视觉引导线的固定角度。对折线和曲线有效。在Pie中无效。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float lineAngle
|
public float lineAngle
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,167 +71,6 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
|
|
||||||
{
|
|
||||||
if (serieData.labelObject == null) return;
|
|
||||||
var startAngle = serie.context.startAngle;
|
|
||||||
var currAngle = serieData.context.halfAngle;
|
|
||||||
var currRad = currAngle * Mathf.Deg2Rad;
|
|
||||||
var offsetRadius = serieData.context.offsetRadius;
|
|
||||||
var insideRadius = serieData.context.insideRadius;
|
|
||||||
var outsideRadius = serieData.context.outsideRadius;
|
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
|
||||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
|
||||||
var center = serieData.context.offsetCenter;
|
|
||||||
var interact = false;
|
|
||||||
serieData.interact.TryGetValueAndColor(ref outsideRadius, ref center, ref interact, serie.animation.GetInteractionDuration());
|
|
||||||
switch (serieLabel.position)
|
|
||||||
{
|
|
||||||
case LabelStyle.Position.Center:
|
|
||||||
serieData.context.labelPosition = serie.context.center;
|
|
||||||
break;
|
|
||||||
case LabelStyle.Position.Inside:
|
|
||||||
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2 + serieLabel.distance;
|
|
||||||
var labelCenter = new Vector2(center.x + labelRadius * Mathf.Sin(currRad),
|
|
||||||
center.y + labelRadius * Mathf.Cos(currRad));
|
|
||||||
serieData.context.labelPosition = labelCenter;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
//LabelStyle.Position.Outside
|
|
||||||
if (labelLine != null && labelLine.lineType == LabelLine.LineType.HorizontalLine)
|
|
||||||
{
|
|
||||||
var radius1 = serie.context.outsideRadius;
|
|
||||||
var radius3 = insideRadius + (outsideRadius - insideRadius) / 2;
|
|
||||||
var currSin = Mathf.Sin(currRad);
|
|
||||||
var currCos = Mathf.Cos(currRad);
|
|
||||||
var pos0 = new Vector3(center.x + radius3 * currSin, center.y + radius3 * currCos);
|
|
||||||
if ((currAngle - startAngle) % 360 > 180)
|
|
||||||
{
|
|
||||||
currSin = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
currCos = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
}
|
|
||||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
|
||||||
r4 += labelLine.lineLength1 + labelLine.lineWidth * 4;
|
|
||||||
r4 += serieData.labelObject.text.GetPreferredWidth() / 2;
|
|
||||||
serieData.context.labelPosition = pos0 + ((currAngle - startAngle) % 360 > 180 ? Vector3.left : Vector3.right) * r4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
labelRadius = serie.context.outsideRadius + (labelLine == null ? 0 : labelLine.lineLength1);
|
|
||||||
labelCenter = new Vector2(center.x + labelRadius * Mathf.Sin(currRad),
|
|
||||||
center.y + labelRadius * Mathf.Cos(currRad));
|
|
||||||
serieData.context.labelPosition = labelCenter;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void AvoidLabelOverlap(Serie serie, ComponentTheme theme)
|
|
||||||
{
|
|
||||||
if (!serie.avoidLabelOverlap) return;
|
|
||||||
var lastCheckPos = Vector3.zero;
|
|
||||||
var lastX = 0f;
|
|
||||||
var data = serie.data;
|
|
||||||
var splitCount = 0;
|
|
||||||
for (int n = 0; n < data.Count; n++)
|
|
||||||
{
|
|
||||||
var serieData = data[n];
|
|
||||||
if (serieData.context.labelPosition.x != 0 && serieData.context.labelPosition.x < serie.context.center.x)
|
|
||||||
{
|
|
||||||
splitCount = n;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int n = 0; n < splitCount; n++)
|
|
||||||
{
|
|
||||||
CheckSerieDataLabel(serie, data[n], splitCount, false, theme, ref lastCheckPos, ref lastX);
|
|
||||||
}
|
|
||||||
lastCheckPos = Vector3.zero;
|
|
||||||
for (int n = data.Count - 1; n >= splitCount; n--)
|
|
||||||
{
|
|
||||||
CheckSerieDataLabel(serie, data[n], data.Count - splitCount, true, theme, ref lastCheckPos, ref lastX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, int total, bool isLeft, ComponentTheme theme,
|
|
||||||
ref Vector3 lastCheckPos, ref float lastX)
|
|
||||||
{
|
|
||||||
if (!serieData.context.canShowLabel)
|
|
||||||
{
|
|
||||||
serieData.SetLabelActive(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!serieData.show) return;
|
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
|
||||||
if (serieLabel == null) return;
|
|
||||||
var isOutside = serieLabel.position == LabelStyle.Position.Outside ||
|
|
||||||
serieLabel.position == LabelStyle.Position.Default;
|
|
||||||
if (!serieLabel.show) return;
|
|
||||||
if (!isOutside) return;
|
|
||||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
|
||||||
var fontSize = serieData.labelObject.GetHeight();
|
|
||||||
if (lastCheckPos == Vector3.zero)
|
|
||||||
{
|
|
||||||
lastCheckPos = serieData.context.labelPosition;
|
|
||||||
}
|
|
||||||
else if (serieData.context.labelPosition.x != 0)
|
|
||||||
{
|
|
||||||
if (lastCheckPos.y - serieData.context.labelPosition.y < fontSize)
|
|
||||||
{
|
|
||||||
var labelRadius = serie.context.outsideRadius + labelLine.lineLength1;
|
|
||||||
var y1 = lastCheckPos.y - fontSize;
|
|
||||||
var cy = serie.context.center.y;
|
|
||||||
var diff = Mathf.Abs(y1 - cy);
|
|
||||||
var diffX = labelRadius * labelRadius - diff * diff;
|
|
||||||
diffX = diffX <= 0 ? 0 : diffX;
|
|
||||||
var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
|
|
||||||
var newPos = new Vector3(x1, y1);
|
|
||||||
serieData.context.labelPosition = newPos;
|
|
||||||
var angle = ChartHelper.GetAngle360(Vector2.up, newPos - serie.context.center);
|
|
||||||
if (angle >= 180 && angle <= 270)
|
|
||||||
{
|
|
||||||
serieData.context.labelPosition = new Vector3(isLeft ? (++lastX) : (--lastX), y1);
|
|
||||||
}
|
|
||||||
else if (angle < 180 && angle >= 90)
|
|
||||||
{
|
|
||||||
serieData.context.labelPosition = new Vector3(isLeft ? (++lastX) : (--lastX), y1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastX = x1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastX = serieData.context.labelPosition.x;
|
|
||||||
}
|
|
||||||
lastCheckPos = serieData.context.labelPosition;
|
|
||||||
serieData.labelObject.SetPosition(SerieLabelHelper.GetRealLabelPosition(serie, serieData, serieLabel, labelLine));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vector3 GetRealLabelPosition(Serie serie, SerieData serieData, LabelStyle label, LabelLine labelLine)
|
|
||||||
{
|
|
||||||
if (label == null || labelLine == null)
|
|
||||||
return serieData.context.labelPosition;
|
|
||||||
var isOutside = label.position == LabelStyle.Position.Outside ||
|
|
||||||
label.position == LabelStyle.Position.Default;
|
|
||||||
if (isOutside && labelLine.lineType != LabelLine.LineType.HorizontalLine)
|
|
||||||
{
|
|
||||||
var currAngle = serieData.context.halfAngle;
|
|
||||||
var offset = labelLine.lineLength2 + serieData.labelObject.GetTextWidth() / 2;
|
|
||||||
var angle = (currAngle - serie.context.startAngle) % 360;
|
|
||||||
var isLeft = angle > 180 || (angle == 0 && serieData.context.startAngle > 0);
|
|
||||||
if (isLeft)
|
|
||||||
return serieData.context.labelPosition + new Vector3(-offset, 0, 0);
|
|
||||||
else
|
|
||||||
return serieData.context.labelPosition + new Vector3(offset, 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return serieData.context.labelPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,33 @@ namespace XCharts.Runtime
|
|||||||
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
|
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
|
||||||
{
|
{
|
||||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||||
return SerieLabelHelper.GetRealLabelPosition(serie, serieData, label, labelLine);
|
if (labelLine != null && labelLine.show && serieData.labelObject != null)
|
||||||
|
{
|
||||||
|
var currAngle = serieData.context.halfAngle - serie.context.startAngle;
|
||||||
|
var isRight = currAngle % 360 < 180;
|
||||||
|
var textOffset = serieData.labelObject.text.GetPreferredWidth() / 2;
|
||||||
|
return serieData.context.labelPosition + (isRight ? Vector3.right : Vector3.left) * textOffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return serieData.context.labelPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector3 GetSerieDataLabelOffset(SerieData serieData, LabelStyle label)
|
||||||
|
{
|
||||||
|
var offset = label.GetOffset(serie.context.insideRadius);
|
||||||
|
if (label.autoOffset)
|
||||||
|
{
|
||||||
|
var currAngle = serieData.context.halfAngle - serie.context.startAngle;
|
||||||
|
var isRight = currAngle % 360 < 180;
|
||||||
|
if (isRight) return offset;
|
||||||
|
else return new Vector3(-offset.x, offset.y, offset.z);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)
|
public override Vector3 GetSerieDataTitlePosition(SerieData serieData, TitleStyle titleStyle)
|
||||||
@@ -213,10 +239,10 @@ namespace XCharts.Runtime
|
|||||||
serieData.context.insideRadius = serie.context.insideRadius;
|
serieData.context.insideRadius = serie.context.insideRadius;
|
||||||
serieData.context.canShowLabel = serieData.context.currentAngle >= serieData.context.halfAngle;
|
serieData.context.canShowLabel = serieData.context.currentAngle >= serieData.context.halfAngle;
|
||||||
UpdateSerieDataRadius(serieData, value);
|
UpdateSerieDataRadius(serieData, value);
|
||||||
SerieLabelHelper.UpdatePieLabelPosition(serie, serieData);
|
UpdatePieLabelPosition(serie, serieData);
|
||||||
startDegree = serieData.context.toAngle;
|
startDegree = serieData.context.toAngle;
|
||||||
}
|
}
|
||||||
SerieLabelHelper.AvoidLabelOverlap(serie, chart.theme.common);
|
AvoidLabelOverlap(serie, chart.theme.common);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateSerieDataRadius(SerieData serieData, double value)
|
private void UpdateSerieDataRadius(SerieData serieData, double value)
|
||||||
@@ -380,140 +406,119 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAnyPieClickOffset()
|
private static void UpdatePieLabelPosition(Serie serie, SerieData serieData)
|
||||||
{
|
{
|
||||||
foreach (var serie in chart.series)
|
if (serieData.labelObject == null) return;
|
||||||
|
var startAngle = serie.context.startAngle;
|
||||||
|
var currAngle = serieData.context.halfAngle;
|
||||||
|
var currRad = currAngle * Mathf.Deg2Rad;
|
||||||
|
var offsetRadius = serieData.context.offsetRadius;
|
||||||
|
var insideRadius = serieData.context.insideRadius;
|
||||||
|
var outsideRadius = serieData.context.outsideRadius;
|
||||||
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
|
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||||
|
var center = serieData.context.offsetCenter;
|
||||||
|
var interact = false;
|
||||||
|
serieData.interact.TryGetValueAndColor(ref outsideRadius, ref center, ref interact, serie.animation.GetInteractionDuration());
|
||||||
|
var diffAngle = (currAngle - startAngle) % 360;
|
||||||
|
var isLeft = diffAngle > 180 || (diffAngle == 0 && serieData.context.startAngle > 0);
|
||||||
|
switch (serieLabel.position)
|
||||||
{
|
{
|
||||||
if (serie is Pie && serie.pieClickOffset)
|
case LabelStyle.Position.Center:
|
||||||
return true;
|
serieData.context.labelPosition = serie.context.center;
|
||||||
|
break;
|
||||||
|
case LabelStyle.Position.Inside:
|
||||||
|
case LabelStyle.Position.Middle:
|
||||||
|
var labelRadius = offsetRadius + insideRadius + (outsideRadius - insideRadius) / 2 + serieLabel.distance;
|
||||||
|
var labelCenter = new Vector2(center.x + labelRadius * Mathf.Sin(currRad),
|
||||||
|
center.y + labelRadius * Mathf.Cos(currRad));
|
||||||
|
UpdateLabelPosition(serie, serieData, labelLine, labelCenter, isLeft);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//LabelStyle.Position.Outside
|
||||||
|
var startPos = new Vector2(center.x + outsideRadius * Mathf.Sin(currRad),
|
||||||
|
center.y + outsideRadius * Mathf.Cos(currRad));
|
||||||
|
UpdateLabelPosition(serie, serieData, labelLine, startPos, isLeft);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsAnyPieDataHighlight()
|
private static void UpdateLabelPosition(Serie serie, SerieData serieData, LabelLine labelLine, Vector3 startPosition, bool isLeft)
|
||||||
{
|
{
|
||||||
foreach (var serie in chart.series)
|
serieData.context.labelLinePosition = startPosition;
|
||||||
|
if (labelLine == null || !labelLine.show)
|
||||||
{
|
{
|
||||||
if (serie is Pie)
|
serieData.context.labelPosition = startPosition;
|
||||||
{
|
return;
|
||||||
foreach (var serieData in serie.data)
|
|
||||||
{
|
|
||||||
if (serieData.context.highlight)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
var dire = isLeft ? Vector3.left : Vector3.right;
|
||||||
|
var rad = Mathf.Deg2Rad * serieData.context.halfAngle;
|
||||||
|
var lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);
|
||||||
|
var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
||||||
|
var pos1 = startPosition;
|
||||||
|
var pos2 = pos1 + new Vector3(Mathf.Sin(rad) * lineLength1, Mathf.Cos(rad) * lineLength1);
|
||||||
|
var pos5 = labelLine.lineType == LabelLine.LineType.HorizontalLine
|
||||||
|
? pos1 + dire * (lineLength1 + lineLength2) + labelLine.GetEndSymbolOffset()
|
||||||
|
: pos2 + dire * lineLength2 + labelLine.GetEndSymbolOffset();
|
||||||
|
if (labelLine.lineEndX != 0)
|
||||||
|
{
|
||||||
|
pos5.x = isLeft ? -Mathf.Abs(labelLine.lineEndX) : Mathf.Abs(labelLine.lineEndX);
|
||||||
|
}
|
||||||
|
serieData.context.labelLinePosition2 = pos2;
|
||||||
|
serieData.context.labelPosition = pos5;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie, bool drawHightlight)
|
private void DrawPieLabelLine(VertexHelper vh, Serie serie, bool isTop)
|
||||||
{
|
{
|
||||||
foreach (var serieData in serie.data)
|
foreach (var serieData in serie.data)
|
||||||
{
|
{
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
if (drawHightlight && !serieData.context.highlight) continue;
|
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||||
if (!drawHightlight && serieData.context.highlight) continue;
|
|
||||||
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
|
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
|
||||||
{
|
{
|
||||||
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
|
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
|
||||||
Color color = chart.theme.GetColor(colorIndex);
|
if (serieLabel != null && serieLabel.show &&
|
||||||
DrawPieLabelLine(vh, serie, serieData, color);
|
labelLine != null && labelLine.show)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawPieLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color color)
|
|
||||||
{
|
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
|
||||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
|
||||||
if (serieLabel != null && serieLabel.show &&
|
|
||||||
labelLine != null && labelLine.show &&
|
|
||||||
(serieLabel.IsDefaultPosition(LabelStyle.Position.Outside)))
|
|
||||||
{
|
|
||||||
var insideRadius = serieData.context.insideRadius;
|
|
||||||
var outSideRadius = serieData.context.outsideRadius;
|
|
||||||
var center = serieData.context.offsetCenter;
|
|
||||||
var interact = false;
|
|
||||||
serieData.interact.TryGetValueAndColor(ref outSideRadius, ref center, ref interact, serie.animation.GetInteractionDuration());
|
|
||||||
var currAngle = serieData.context.halfAngle;
|
|
||||||
if (!ChartHelper.IsClearColor(labelLine.lineColor))
|
|
||||||
color = labelLine.lineColor;
|
|
||||||
else if (labelLine.lineType == LabelLine.LineType.HorizontalLine)
|
|
||||||
color *= color;
|
|
||||||
|
|
||||||
float currSin = Mathf.Sin(currAngle * Mathf.Deg2Rad);
|
|
||||||
float currCos = Mathf.Cos(currAngle * Mathf.Deg2Rad);
|
|
||||||
var radius1 = labelLine.lineType == LabelLine.LineType.HorizontalLine ?
|
|
||||||
serie.context.outsideRadius : outSideRadius;
|
|
||||||
var radius3 = insideRadius + (outSideRadius - insideRadius) / 2;
|
|
||||||
if (radius1 < serie.context.insideRadius) radius1 = serie.context.insideRadius;
|
|
||||||
radius1 -= 0.1f;
|
|
||||||
var pos0 = new Vector3(center.x + radius3 * currSin, center.y + radius3 * currCos);
|
|
||||||
var pos1 = new Vector3(center.x + radius1 * currSin, center.y + radius1 * currCos);
|
|
||||||
var pos2 = serieData.context.labelPosition;
|
|
||||||
Vector3 pos4, pos6;
|
|
||||||
var horizontalLineCircleRadius = labelLine.lineWidth * 4f;
|
|
||||||
var lineCircleDiff = horizontalLineCircleRadius - 0.3f;
|
|
||||||
var startAngle = serie.context.startAngle;
|
|
||||||
if (currAngle < 90)
|
|
||||||
{
|
|
||||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
|
||||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
|
||||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
|
||||||
pos4 = pos6 + Vector3.right * r4;
|
|
||||||
}
|
|
||||||
else if (currAngle < 180)
|
|
||||||
{
|
|
||||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos * radius3, 2)) - currSin * radius3;
|
|
||||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
|
||||||
pos6 = pos0 + Vector3.right * lineCircleDiff;
|
|
||||||
pos4 = pos6 + Vector3.right * r4;
|
|
||||||
}
|
|
||||||
else if (currAngle < 270)
|
|
||||||
{
|
|
||||||
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
|
|
||||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
|
||||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
|
||||||
pos4 = pos6 + Vector3.left * r4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var currSin1 = Mathf.Sin((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
var currCos1 = Mathf.Cos((360 - currAngle) * Mathf.Deg2Rad);
|
|
||||||
var r4 = Mathf.Sqrt(radius1 * radius1 - Mathf.Pow(currCos1 * radius3, 2)) - currSin1 * radius3;
|
|
||||||
r4 += labelLine.lineLength1 - lineCircleDiff;
|
|
||||||
pos6 = pos0 + Vector3.left * lineCircleDiff;
|
|
||||||
pos4 = pos6 + Vector3.left * r4;
|
|
||||||
}
|
|
||||||
var diffAngle = (currAngle - startAngle) % 360;
|
|
||||||
var isLeft = diffAngle > 180 || (diffAngle == 0 && serieData.context.startAngle > 0);
|
|
||||||
var pos5X = isLeft ? pos2.x - labelLine.lineLength2 : pos2.x + labelLine.lineLength2;
|
|
||||||
var pos5 = new Vector3(pos5X, pos2.y);
|
|
||||||
var angle = Vector3.Angle(pos1 - center, pos2 - pos1);
|
|
||||||
if (angle > 15)
|
|
||||||
{
|
|
||||||
UGL.DrawLine(vh, pos1, pos5, labelLine.lineWidth, color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (labelLine.lineType)
|
|
||||||
{
|
{
|
||||||
case LabelLine.LineType.BrokenLine:
|
if (serieLabel.position == LabelStyle.Position.Inside || serieLabel.position == LabelStyle.Position.Middle)
|
||||||
UGL.DrawLine(vh, pos1, pos2, pos5, labelLine.lineWidth, color);
|
{
|
||||||
break;
|
if (!isTop) continue;
|
||||||
case LabelLine.LineType.Curves:
|
}
|
||||||
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, labelLine.lineWidth, color,
|
else
|
||||||
chart.settings.lineSmoothness);
|
{
|
||||||
break;
|
if (isTop && !labelLine.startSymbol.show) continue;
|
||||||
case LabelLine.LineType.HorizontalLine:
|
}
|
||||||
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
|
var color = ChartHelper.IsClearColor(labelLine.lineColor) ?
|
||||||
UGL.DrawLine(vh, pos6, pos4, labelLine.lineWidth, color);
|
chart.theme.GetColor(colorIndex) :
|
||||||
break;
|
labelLine.lineColor;
|
||||||
|
switch (labelLine.lineType)
|
||||||
|
{
|
||||||
|
case LabelLine.LineType.BrokenLine:
|
||||||
|
UGL.DrawLine(vh, serieData.context.labelLinePosition, serieData.context.labelLinePosition2,
|
||||||
|
serieData.context.labelPosition, labelLine.lineWidth, color);
|
||||||
|
break;
|
||||||
|
case LabelLine.LineType.Curves:
|
||||||
|
if (serieData.context.labelLinePosition2 == serieData.context.labelPosition)
|
||||||
|
{
|
||||||
|
UGL.DrawCurves(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,
|
||||||
|
serieData.context.labelLinePosition, (serieData.context.labelLinePosition + serieData.context.labelPosition) * 0.6f,
|
||||||
|
labelLine.lineWidth, color, chart.settings.lineSmoothness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UGL.DrawCurves(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,
|
||||||
|
serieData.context.labelLinePosition, serieData.context.labelLinePosition2,
|
||||||
|
labelLine.lineWidth, color, chart.settings.lineSmoothness);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LabelLine.LineType.HorizontalLine:
|
||||||
|
UGL.DrawLine(vh, serieData.context.labelLinePosition, serieData.context.labelPosition,
|
||||||
|
labelLine.lineWidth, color);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DrawLabelLineSymbol(vh, labelLine, serieData.context.labelLinePosition, serieData.context.labelPosition, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DrawLabelLineSymbol(vh, labelLine, pos1, pos5, color);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,5 +590,131 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
return toAngle;
|
return toAngle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AvoidLabelOverlap(Serie serie, ComponentTheme theme)
|
||||||
|
{
|
||||||
|
if (!serie.avoidLabelOverlap) return;
|
||||||
|
var lastCheckPos = Vector3.zero;
|
||||||
|
var lastX = 0f;
|
||||||
|
var data = serie.data;
|
||||||
|
var splitCount = 0;
|
||||||
|
for (int n = 0; n < data.Count; n++)
|
||||||
|
{
|
||||||
|
var serieData = data[n];
|
||||||
|
if (serieData.context.labelPosition.x != 0 && serieData.context.labelPosition.x < serie.context.center.x)
|
||||||
|
{
|
||||||
|
splitCount = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var limitX = float.MinValue;
|
||||||
|
for (int n = 0; n < splitCount; n++)
|
||||||
|
{
|
||||||
|
CheckSerieDataLabel(serie, data[n], splitCount, false, n == splitCount - 1, theme, ref lastCheckPos, ref lastX, ref limitX);
|
||||||
|
}
|
||||||
|
lastCheckPos = Vector3.zero;
|
||||||
|
limitX = float.MaxValue;
|
||||||
|
for (int n = data.Count - 1; n >= splitCount; n--)
|
||||||
|
{
|
||||||
|
CheckSerieDataLabel(serie, data[n], data.Count - splitCount, true, n == splitCount, theme, ref lastCheckPos, ref lastX, ref limitX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CheckSerieDataLabel(Serie serie, SerieData serieData, int total, bool isLeft, bool isLastOne, ComponentTheme theme,
|
||||||
|
ref Vector3 lastCheckPos, ref float lastX, ref float limitX)
|
||||||
|
{
|
||||||
|
if (!serieData.context.canShowLabel)
|
||||||
|
{
|
||||||
|
serieData.SetLabelActive(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!serieData.show) return;
|
||||||
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
|
if (serieLabel == null) return;
|
||||||
|
if (!serieLabel.show) return;
|
||||||
|
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||||
|
var fontSize = serieData.labelObject.GetHeight();
|
||||||
|
var lineLength1 = 0f;
|
||||||
|
var lineLength2 = 0f;
|
||||||
|
if (labelLine != null && labelLine.show)
|
||||||
|
{
|
||||||
|
lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);
|
||||||
|
lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
||||||
|
}
|
||||||
|
if (lastCheckPos == Vector3.zero)
|
||||||
|
{
|
||||||
|
lastCheckPos = serieData.context.labelPosition;
|
||||||
|
}
|
||||||
|
else if (serieData.context.labelPosition.x != 0)
|
||||||
|
{
|
||||||
|
if (lastCheckPos.y - serieData.context.labelPosition.y < fontSize)
|
||||||
|
{
|
||||||
|
var labelRadius = serie.context.outsideRadius + lineLength1;
|
||||||
|
var y1 = lastCheckPos.y - fontSize;
|
||||||
|
var cy = serie.context.center.y;
|
||||||
|
var diff = Mathf.Abs(y1 - cy);
|
||||||
|
var diffX = labelRadius * labelRadius - diff * diff;
|
||||||
|
diffX = diffX <= 0 ? 0 : diffX;
|
||||||
|
var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
|
||||||
|
var newPos = new Vector3(x1, y1);
|
||||||
|
serieData.context.labelLinePosition2 = newPos;
|
||||||
|
if (isLeft)
|
||||||
|
{
|
||||||
|
if (x1 < limitX)
|
||||||
|
{
|
||||||
|
limitX = x1;
|
||||||
|
serieData.context.labelPosition = new Vector3(newPos.x - lineLength2, newPos.y);
|
||||||
|
lastX = serieData.context.labelPosition.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serieData.context.labelPosition = new Vector3(lastX, y1);
|
||||||
|
lastX += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (x1 > limitX)
|
||||||
|
{
|
||||||
|
limitX = x1;
|
||||||
|
serieData.context.labelPosition = new Vector3(newPos.x + lineLength2, newPos.y);
|
||||||
|
lastX = serieData.context.labelPosition.x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serieData.context.labelPosition = new Vector3(lastX, y1);
|
||||||
|
lastX -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (labelLine != null && labelLine.show && labelLine.lineEndX != 0)
|
||||||
|
{
|
||||||
|
serieData.context.labelPosition.x = isLeft ? -Mathf.Abs(labelLine.lineEndX) : Mathf.Abs(labelLine.lineEndX);
|
||||||
|
}
|
||||||
|
if (!isLastOne && serieData.context.labelPosition.y < serieData.context.labelLinePosition.y)
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition2 = serieData.context.labelPosition;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isLeft && serieData.context.labelLinePosition2.x > serieData.context.labelLinePosition.x)
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition2.x = serieData.context.labelLinePosition.x;
|
||||||
|
}
|
||||||
|
else if (!isLeft && serieData.context.labelLinePosition2.x < serieData.context.labelLinePosition.x)
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition2.x = serieData.context.labelLinePosition.x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastX = serieData.context.labelPosition.x;
|
||||||
|
}
|
||||||
|
lastCheckPos = serieData.context.labelPosition;
|
||||||
|
UpdateLabelPosition(serieData, serieLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,6 +111,8 @@ namespace XCharts.Runtime
|
|||||||
|
|
||||||
private Vector3 GetLabelLineEndPosition(Serie serie, SerieData serieData, LabelLine labelLine)
|
private Vector3 GetLabelLineEndPosition(Serie serie, SerieData serieData, LabelLine labelLine)
|
||||||
{
|
{
|
||||||
|
if (labelLine == null || !labelLine.show)
|
||||||
|
return serieData.context.labelLinePosition;
|
||||||
var isRight = !serie.clockwise;
|
var isRight = !serie.clockwise;
|
||||||
var dire = isRight ? Vector3.right : Vector3.left;
|
var dire = isRight ? Vector3.right : Vector3.left;
|
||||||
var rad = Mathf.Deg2Rad * (isRight ? labelLine.lineAngle : 180 - labelLine.lineAngle);
|
var rad = Mathf.Deg2Rad * (isRight ? labelLine.lineAngle : 180 - labelLine.lineAngle);
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ namespace XCharts.Runtime
|
|||||||
{
|
{
|
||||||
public Vector3 labelPosition;
|
public Vector3 labelPosition;
|
||||||
public Vector3 labelLinePosition;
|
public Vector3 labelLinePosition;
|
||||||
|
public Vector3 labelLinePosition2;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始角度
|
/// 开始角度
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -564,7 +564,7 @@ namespace XCharts.Runtime
|
|||||||
m_EndLabel.isAnimationEnd = serie.animation.IsFinish();
|
m_EndLabel.isAnimationEnd = serie.animation.IsFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
protected void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
||||||
{
|
{
|
||||||
var labelPosition = GetSerieDataLabelPosition(serieData, currLabel);
|
var labelPosition = GetSerieDataLabelPosition(serieData, currLabel);
|
||||||
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
var offset = GetSerieDataLabelOffset(serieData, currLabel);
|
||||||
|
|||||||
Reference in New Issue
Block a user