mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-26 10:50:08 +00:00
增加Ring的avoidLabelOverlap避免文本堆叠的支持 (#247)
This commit is contained in:
@@ -13,6 +13,7 @@ namespace XCharts.Editor
|
|||||||
PropertyField("m_Gap");
|
PropertyField("m_Gap");
|
||||||
PropertyField("m_RoundCap");
|
PropertyField("m_RoundCap");
|
||||||
PropertyField("m_Clockwise");
|
PropertyField("m_Clockwise");
|
||||||
|
PropertyField("m_AvoidLabelOverlap");
|
||||||
|
|
||||||
PropertyField("m_ItemStyle");
|
PropertyField("m_ItemStyle");
|
||||||
PropertyField("m_Animation");
|
PropertyField("m_Animation");
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ namespace XCharts.Runtime
|
|||||||
[UnityEngine.Scripting.Preserve]
|
[UnityEngine.Scripting.Preserve]
|
||||||
internal sealed class RingHandler : SerieHandler<Ring>
|
internal sealed class RingHandler : SerieHandler<Ring>
|
||||||
{
|
{
|
||||||
|
|
||||||
public override int defaultDimension { get { return 0; } }
|
public override int defaultDimension { get { return 0; } }
|
||||||
|
|
||||||
public override void Update()
|
public override void Update()
|
||||||
@@ -110,57 +109,6 @@ namespace XCharts.Runtime
|
|||||||
paramList.Add(param);
|
paramList.Add(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Vector3 GetSerieDataLabelPosition(SerieData serieData, LabelStyle label)
|
|
||||||
{
|
|
||||||
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
|
||||||
var centerRadius = (serieData.context.outsideRadius + serieData.context.insideRadius) / 2;
|
|
||||||
var startAngle = serieData.context.startAngle;
|
|
||||||
var toAngle = serieData.context.toAngle;
|
|
||||||
switch (label.position)
|
|
||||||
{
|
|
||||||
case LabelStyle.Position.Bottom:
|
|
||||||
case LabelStyle.Position.Start:
|
|
||||||
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
|
|
||||||
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
|
|
||||||
var xDiff = serie.clockwise ? -label.distance : label.distance;
|
|
||||||
|
|
||||||
if (labelLine != null && labelLine.show)
|
|
||||||
{
|
|
||||||
serieData.context.labelLinePosition = serie.context.center + new Vector3(px1, py1) + labelLine.GetStartSymbolOffset();
|
|
||||||
serieData.context.labelPosition = GetLabelLineEndPosition(serie, serieData, labelLine) + new Vector3(xDiff, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serieData.context.labelLinePosition = serie.context.center + new Vector3(px1 + xDiff, py1);
|
|
||||||
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LabelStyle.Position.Top:
|
|
||||||
case LabelStyle.Position.End:
|
|
||||||
startAngle += serie.clockwise ? -label.distance : label.distance;
|
|
||||||
toAngle += serie.clockwise ? label.distance : -label.distance;
|
|
||||||
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
|
|
||||||
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
|
|
||||||
|
|
||||||
if (labelLine != null && labelLine.show)
|
|
||||||
{
|
|
||||||
serieData.context.labelLinePosition = serie.context.center + new Vector3(px2, py2) + labelLine.GetStartSymbolOffset();
|
|
||||||
serieData.context.labelPosition = GetLabelLineEndPosition(serie, serieData, labelLine);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serieData.context.labelLinePosition = serie.context.center + new Vector3(px2, py2);
|
|
||||||
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: //LabelStyle.Position.Center
|
|
||||||
serieData.context.labelLinePosition = serie.context.center + label.offset;
|
|
||||||
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return serieData.context.labelPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector3 GetLabelLineEndPosition(Serie serie, SerieData serieData, LabelLine labelLine)
|
private Vector3 GetLabelLineEndPosition(Serie serie, SerieData serieData, LabelLine labelLine)
|
||||||
{
|
{
|
||||||
var isRight = !serie.clockwise;
|
var isRight = !serie.clockwise;
|
||||||
@@ -170,16 +118,22 @@ namespace XCharts.Runtime
|
|||||||
var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
||||||
var pos1 = serieData.context.labelLinePosition;
|
var pos1 = serieData.context.labelLinePosition;
|
||||||
var pos2 = pos1 + new Vector3(Mathf.Cos(rad) * lineLength1, Mathf.Sin(rad) * lineLength1);
|
var pos2 = pos1 + new Vector3(Mathf.Cos(rad) * lineLength1, Mathf.Sin(rad) * lineLength1);
|
||||||
var pos5 = pos2 + dire * lineLength2;
|
var pos5 = labelLine.lineType == LabelLine.LineType.HorizontalLine
|
||||||
return pos5 + labelLine.GetEndSymbolOffset();
|
? pos1 + dire * (lineLength1 + lineLength2) + labelLine.GetEndSymbolOffset()
|
||||||
|
: pos2 + dire * lineLength2 + labelLine.GetEndSymbolOffset();
|
||||||
|
if (labelLine.lineEndX != 0)
|
||||||
|
{
|
||||||
|
pos5.x = labelLine.lineEndX;
|
||||||
|
}
|
||||||
|
return pos5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DrawSerie(VertexHelper vh)
|
public override void DrawSerie(VertexHelper vh)
|
||||||
{
|
{
|
||||||
if (!serie.show || serie.animation.HasFadeOut()) return;
|
if (!serie.show || serie.animation.HasFadeOut()) return;
|
||||||
|
UpdateRuntimeData();
|
||||||
var data = serie.data;
|
var data = serie.data;
|
||||||
serie.animation.InitProgress(serie.startAngle, serie.startAngle + 360);
|
serie.animation.InitProgress(serie.startAngle, serie.startAngle + 360);
|
||||||
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
|
||||||
var ringWidth = serie.context.outsideRadius - serie.context.insideRadius;
|
var ringWidth = serie.context.outsideRadius - serie.context.insideRadius;
|
||||||
var dataChanging = false;
|
var dataChanging = false;
|
||||||
for (int j = 0; j < data.Count; j++)
|
for (int j = 0; j < data.Count; j++)
|
||||||
@@ -203,18 +157,21 @@ namespace XCharts.Runtime
|
|||||||
var borderWidth = itemStyle.borderWidth;
|
var borderWidth = itemStyle.borderWidth;
|
||||||
var borderColor = itemStyle.borderColor;
|
var borderColor = itemStyle.borderColor;
|
||||||
var roundCap = serie.roundCap && insideRadius > 0;
|
var roundCap = serie.roundCap && insideRadius > 0;
|
||||||
|
|
||||||
serieData.context.startAngle = startDegree;
|
|
||||||
serieData.context.toAngle = toDegree;
|
|
||||||
serieData.context.insideRadius = insideRadius;
|
|
||||||
serieData.context.outsideRadius = serieData.radius > 0 ? serieData.radius : outsideRadius;
|
|
||||||
DrawBackground(vh, serie, serieData, j, insideRadius, outsideRadius);
|
DrawBackground(vh, serie, serieData, j, insideRadius, outsideRadius);
|
||||||
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemColor, itemToColor,
|
UGL.DrawDoughnut(vh, serie.context.center, insideRadius, outsideRadius, itemColor, itemToColor,
|
||||||
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
|
Color.clear, startDegree, toDegree, borderWidth, borderColor, 0, chart.settings.cicleSmoothness,
|
||||||
roundCap, serie.clockwise);
|
roundCap, serie.clockwise);
|
||||||
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
|
DrawCenter(vh, serie, serieData, insideRadius, j == data.Count - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < data.Count; j++)
|
||||||
|
{
|
||||||
|
var serieData = data[j];
|
||||||
|
if (!serieData.show) continue;
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
|
var colorIndex = chart.GetLegendRealShowNameIndex(serieData.legendName);
|
||||||
|
Color32 itemColor, itemToColor;
|
||||||
|
SerieHelper.GetItemColor(out itemColor, out itemToColor, serie, serieData, chart.theme, colorIndex);
|
||||||
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 0))
|
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 0))
|
||||||
{
|
{
|
||||||
DrawRingLabelLine(vh, serie, serieData, itemColor);
|
DrawRingLabelLine(vh, serie, serieData, itemColor);
|
||||||
@@ -231,6 +188,32 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateRuntimeData()
|
||||||
|
{
|
||||||
|
var data = serie.data;
|
||||||
|
SerieHelper.UpdateCenter(serie, chart.chartPosition, chart.chartWidth, chart.chartHeight);
|
||||||
|
var ringWidth = serie.context.outsideRadius - serie.context.insideRadius;
|
||||||
|
for (int j = 0; j < data.Count; j++)
|
||||||
|
{
|
||||||
|
var serieData = data[j];
|
||||||
|
if (!serieData.show) continue;
|
||||||
|
var outsideRadius = serie.context.outsideRadius - j * (ringWidth + serie.gap);
|
||||||
|
if (outsideRadius < 0) continue;
|
||||||
|
var value = serieData.GetCurrData(0, serie.animation, false, false);
|
||||||
|
var max = serieData.GetLastData();
|
||||||
|
var degree = (float)(360 * value / max);
|
||||||
|
var startDegree = GetStartAngle(serie);
|
||||||
|
var toDegree = GetToAngle(serie, degree);
|
||||||
|
var insideRadius = outsideRadius - ringWidth;
|
||||||
|
serieData.context.startAngle = startDegree;
|
||||||
|
serieData.context.toAngle = toDegree;
|
||||||
|
serieData.context.insideRadius = insideRadius;
|
||||||
|
serieData.context.outsideRadius = serieData.radius > 0 ? serieData.radius : outsideRadius;
|
||||||
|
UpdateLabelPosition(serieData);
|
||||||
|
}
|
||||||
|
AvoidLabelOverlap();
|
||||||
|
}
|
||||||
|
|
||||||
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
public override void OnLegendButtonClick(int index, string legendName, bool show)
|
||||||
{
|
{
|
||||||
if (!serie.IsLegendName(legendName))
|
if (!serie.IsLegendName(legendName))
|
||||||
@@ -372,6 +355,85 @@ namespace XCharts.Runtime
|
|||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void UpdateLabelPosition(SerieData serieData)
|
||||||
|
{
|
||||||
|
if (serieData.labelObject == null) return;
|
||||||
|
var label = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
|
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
|
||||||
|
var centerRadius = (serieData.context.outsideRadius + serieData.context.insideRadius) / 2;
|
||||||
|
var startAngle = serieData.context.startAngle;
|
||||||
|
var toAngle = serieData.context.toAngle;
|
||||||
|
switch (label.position)
|
||||||
|
{
|
||||||
|
case LabelStyle.Position.Bottom:
|
||||||
|
case LabelStyle.Position.Start:
|
||||||
|
var px1 = Mathf.Sin(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||||
|
var py1 = Mathf.Cos(startAngle * Mathf.Deg2Rad) * centerRadius;
|
||||||
|
var xDiff = serie.clockwise ? -label.distance : label.distance;
|
||||||
|
|
||||||
|
if (labelLine != null && labelLine.show)
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition = serie.context.center + new Vector3(px1, py1) + labelLine.GetStartSymbolOffset();
|
||||||
|
serieData.context.labelPosition = GetLabelLineEndPosition(serie, serieData, labelLine) + new Vector3(xDiff, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition = serie.context.center + new Vector3(px1 + xDiff, py1);
|
||||||
|
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LabelStyle.Position.Top:
|
||||||
|
case LabelStyle.Position.End:
|
||||||
|
case LabelStyle.Position.Outside:
|
||||||
|
startAngle += serie.clockwise ? -label.distance : label.distance;
|
||||||
|
toAngle += serie.clockwise ? label.distance : -label.distance;
|
||||||
|
var px2 = Mathf.Sin(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||||
|
var py2 = Mathf.Cos(toAngle * Mathf.Deg2Rad) * centerRadius;
|
||||||
|
|
||||||
|
if (labelLine != null && labelLine.show)
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition = serie.context.center + new Vector3(px2, py2) + labelLine.GetStartSymbolOffset();
|
||||||
|
serieData.context.labelPosition = GetLabelLineEndPosition(serie, serieData, labelLine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serieData.context.labelLinePosition = serie.context.center + new Vector3(px2, py2);
|
||||||
|
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: //LabelStyle.Position.Center
|
||||||
|
serieData.context.labelLinePosition = serie.context.center + label.offset;
|
||||||
|
serieData.context.labelPosition = serieData.context.labelLinePosition;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AvoidLabelOverlap()
|
||||||
|
{
|
||||||
|
if (!serie.avoidLabelOverlap) return;
|
||||||
|
serie.context.sortedData.Clear();
|
||||||
|
foreach (var serieData in serie.data)
|
||||||
|
{
|
||||||
|
serie.context.sortedData.Add(serieData);
|
||||||
|
}
|
||||||
|
serie.context.sortedData.Sort(delegate (SerieData a, SerieData b)
|
||||||
|
{
|
||||||
|
if (a == null || b == null) return 0;
|
||||||
|
return a.context.labelPosition.y.CompareTo(b.context.labelPosition.y);
|
||||||
|
});
|
||||||
|
var startY = serie.context.sortedData[0].context.labelPosition.y;
|
||||||
|
for (int i = 1; i < serie.context.sortedData.Count; i++)
|
||||||
|
{
|
||||||
|
var serieData = serie.context.sortedData[i];
|
||||||
|
var fontSize = serieData.labelObject.GetHeight();
|
||||||
|
if (serieData.context.labelPosition.y - startY < fontSize)
|
||||||
|
{
|
||||||
|
serieData.context.labelPosition.y = startY + fontSize;
|
||||||
|
}
|
||||||
|
startY = serieData.context.labelPosition.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawRingLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color32 defaltColor)
|
private void DrawRingLabelLine(VertexHelper vh, Serie serie, SerieData serieData, Color32 defaltColor)
|
||||||
{
|
{
|
||||||
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
|
||||||
@@ -386,11 +448,9 @@ namespace XCharts.Runtime
|
|||||||
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);
|
||||||
var lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);
|
var lineLength1 = ChartHelper.GetActualValue(labelLine.lineLength1, serie.context.outsideRadius);
|
||||||
var lineLength2 = ChartHelper.GetActualValue(labelLine.lineLength2, serie.context.outsideRadius);
|
|
||||||
var pos1 = serieData.context.labelLinePosition;
|
var pos1 = serieData.context.labelLinePosition;
|
||||||
var pos2 = pos1 + new Vector3(Mathf.Cos(rad) * lineLength1, Mathf.Sin(rad) * lineLength1);
|
var pos2 = pos1 + new Vector3(Mathf.Cos(rad) * lineLength1, Mathf.Sin(rad) * lineLength1);
|
||||||
var pos5 = pos2 + dire * lineLength2 + labelLine.GetEndSymbolOffset();
|
var pos5 = serieData.context.labelPosition;
|
||||||
serieData.context.labelPosition = pos5;
|
|
||||||
switch (labelLine.lineType)
|
switch (labelLine.lineType)
|
||||||
{
|
{
|
||||||
case LabelLine.LineType.BrokenLine:
|
case LabelLine.LineType.BrokenLine:
|
||||||
@@ -401,8 +461,6 @@ namespace XCharts.Runtime
|
|||||||
chart.settings.lineSmoothness, UGL.Direction.XAxis);
|
chart.settings.lineSmoothness, UGL.Direction.XAxis);
|
||||||
break;
|
break;
|
||||||
case LabelLine.LineType.HorizontalLine:
|
case LabelLine.LineType.HorizontalLine:
|
||||||
pos5 = pos1 + dire * (lineLength1 + lineLength2);
|
|
||||||
serieData.context.labelPosition = pos5;
|
|
||||||
UGL.DrawLine(vh, pos1, pos5, labelLine.lineWidth, color);
|
UGL.DrawLine(vh, pos1, pos5, labelLine.lineWidth, color);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1463,7 +1463,8 @@ namespace XCharts.Runtime
|
|||||||
serieData.name = name;
|
serieData.name = name;
|
||||||
serieData.index = m_Data.Count;
|
serieData.index = m_Data.Count;
|
||||||
serieData.id = id;
|
serieData.id = id;
|
||||||
serieData.data = new List<double>() { m_Data.Count, value };
|
serieData.data.Add(m_Data.Count);
|
||||||
|
serieData.data.Add(value);
|
||||||
AddChildData(parent, serieData);
|
AddChildData(parent, serieData);
|
||||||
return serieData;
|
return serieData;
|
||||||
}
|
}
|
||||||
@@ -1474,7 +1475,7 @@ namespace XCharts.Runtime
|
|||||||
serieData.name = name;
|
serieData.name = name;
|
||||||
serieData.index = m_Data.Count;
|
serieData.index = m_Data.Count;
|
||||||
serieData.id = id;
|
serieData.id = id;
|
||||||
serieData.data = new List<double>(value);
|
serieData.data.AddRange(value);
|
||||||
AddChildData(parent, serieData);
|
AddChildData(parent, serieData);
|
||||||
return serieData;
|
return serieData;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user