[optimize][pie] avoid label overlap (#56)

This commit is contained in:
monitor1394
2022-06-28 13:23:32 +08:00
parent 6c9528cf19
commit 0f2f55e436
5 changed files with 69 additions and 27 deletions

View File

@@ -54,6 +54,7 @@
## master
* (2022.06.28) 优化`Pie`设置`avoidLabelOverlap`时的文本表现 (#56)
* (2022.06.25) 优化`Line`的平滑曲线表现 (#169)
* (2022.06.25) 修复`DataZoom`开启时`Tooltip`显示数据不一致的问题 (#203)
* (2022.06.25) 修复`Toolip`在类目轴无数据时绘制异常的问题 (#204)

View File

@@ -11,10 +11,10 @@ namespace XCharts.Runtime
public class Padding : ChildComponent
{
[SerializeField] protected bool m_Show = true;
[SerializeField] protected float m_Top = 2;
[SerializeField] protected float m_Right = 4;
[SerializeField] protected float m_Left = 4;
[SerializeField] protected float m_Bottom = 2;
[SerializeField] protected float m_Top = 0;
[SerializeField] protected float m_Right = 2f;
[SerializeField] protected float m_Left = 2f;
[SerializeField] protected float m_Bottom = 0;
public Padding() { }

View File

@@ -161,7 +161,7 @@ namespace XCharts.Runtime
/// {d:0.##} indicates that a formatted string with a value specified separately is 0.## (used for percentage, reserved 2 valid digits while avoiding the situation similar to "100.00%" when using f2 ).</br>
/// Example: "{a}, {c}", "{a1}, {c1: f1}", "{a1}, {c1:0: f1}", "{a1} : {c1:1-1: f1}"</br>
/// |提示框单个serie或数据项内容的字符串模版格式器。支持用 \n 换行。
/// 模板变量有{.}、{a}、{b}、{c}、{d}、{e}。</br>
/// 模板变量有{.}、{a}、{b}、{c}、{d}、{e}、{f}。</br>
/// {.}为当前所指示或index为0的serie的对应颜色的圆点。</br>
/// {a}为当前所指示或index为0的serie的系列名name。</br>
/// {b}为当前所指示或index为0的serie的数据项serieData的name或者类目值如折线图的X轴。</br>

View File

@@ -132,6 +132,7 @@ namespace XCharts.Runtime
{
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++)
@@ -143,19 +144,20 @@ namespace XCharts.Runtime
break;
}
}
for (int n = 0; n < splitCount; n++)
{
CheckSerieDataLabel(serie, data[n], false, theme, ref lastCheckPos);
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], true, theme, ref lastCheckPos);
CheckSerieDataLabel(serie, data[n], data.Count - splitCount, true, theme, ref lastCheckPos, ref lastX);
}
}
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, bool isLeft, ComponentTheme theme,
ref Vector3 lastCheckPos)
private static void CheckSerieDataLabel(Serie serie, SerieData serieData, int total, bool isLeft, ComponentTheme theme,
ref Vector3 lastCheckPos, ref float lastX)
{
if (!serieData.context.canShowLabel)
{
@@ -164,12 +166,12 @@ namespace XCharts.Runtime
}
if (!serieData.show) return;
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
var labelLine = SerieHelper.GetSerieLabelLine(serie, serieData);
var fontSize = serieLabel.textStyle.GetFontSize(theme);
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;
@@ -185,7 +187,25 @@ namespace XCharts.Runtime
var diffX = labelRadius * labelRadius - diff * diff;
diffX = diffX <= 0 ? 0 : diffX;
var x1 = serie.context.center.x + Mathf.Sqrt(diffX) * (isLeft ? -1 : 1);
serieData.context.labelPosition = new Vector3(x1, y1);
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));

View File

@@ -15,11 +15,22 @@ namespace XCharts.Runtime
UpdateSerieContext();
}
public override void DrawBase(VertexHelper vh)
{
UpdateRuntimeData(serie);
DrawPieLabelLine(vh, serie, false);
}
public override void DrawSerie(VertexHelper vh)
{
UpdateRuntimeData(serie);
DrawPieLabelLine(vh, serie);
DrawPie(vh, serie);
chart.RefreshBasePainter();
}
public override void DrawUpper(VertexHelper vh)
{
DrawPieLabelLine(vh, serie, true);
}
public override void UpdateTooltipSerieParams(int dataIndex, bool showCategory, string category,
@@ -390,11 +401,13 @@ namespace XCharts.Runtime
return false;
}
private void DrawPieLabelLine(VertexHelper vh, Serie serie)
private void DrawPieLabelLine(VertexHelper vh, Serie serie, bool drawHightlight)
{
foreach (var serieData in serie.data)
{
var serieLabel = SerieHelper.GetSerieLabel(serie, serieData);
if (drawHightlight && !serieData.context.highlight) continue;
if (!drawHightlight && serieData.context.highlight) continue;
if (SerieLabelHelper.CanShowLabel(serie, serieData, serieLabel, 1))
{
int colorIndex = chart.m_LegendRealShowName.IndexOf(serieData.name);
@@ -435,7 +448,7 @@ namespace XCharts.Runtime
var pos2 = serieData.context.labelPosition;
if (pos2.x == 0)
{
pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
//pos2 = new Vector3(center.x + radius2 * currSin, center.y + radius2 * currCos);
}
Vector3 pos4, pos6;
var horizontalLineCircleRadius = labelLine.lineWidth * 4f;
@@ -476,19 +489,27 @@ namespace XCharts.Runtime
var pos5X = (currAngle - startAngle) % 360 > 180 ?
pos2.x - labelLine.lineLength2 : pos2.x + labelLine.lineLength2;
var pos5 = new Vector3(pos5X, pos2.y);
switch (labelLine.lineType)
var angle = Vector3.Angle(pos1 - center, pos2 - pos1);
if (angle > 15)
{
case LabelLine.LineType.BrokenLine:
UGL.DrawLine(vh, pos1, pos2, pos5, labelLine.lineWidth, color);
break;
case LabelLine.LineType.Curves:
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, labelLine.lineWidth, color,
chart.settings.lineSmoothness);
break;
case LabelLine.LineType.HorizontalLine:
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
UGL.DrawLine(vh, pos6, pos4, labelLine.lineWidth, color);
break;
UGL.DrawLine(vh, pos1, pos5, labelLine.lineWidth, color);
}
else
{
switch (labelLine.lineType)
{
case LabelLine.LineType.BrokenLine:
UGL.DrawLine(vh, pos1, pos2, pos5, labelLine.lineWidth, color);
break;
case LabelLine.LineType.Curves:
UGL.DrawCurves(vh, pos1, pos5, pos1, pos2, labelLine.lineWidth, color,
chart.settings.lineSmoothness);
break;
case LabelLine.LineType.HorizontalLine:
UGL.DrawCricle(vh, pos0, horizontalLineCircleRadius, color);
UGL.DrawLine(vh, pos6, pos4, labelLine.lineWidth, color);
break;
}
}
}
}