mirror of
https://github.com/XCharts-Team/XCharts.git
synced 2026-05-27 03:10:11 +00:00
[enhancement][line] line support end label
This commit is contained in:
@@ -30,4 +30,10 @@ namespace XCharts.Editor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CustomPropertyDrawer(typeof(EndLabelStyle), true)]
|
||||||
|
public class EndLabelStyleDrawer : LabelStyleDrawer
|
||||||
|
{
|
||||||
|
public override string ClassName { get { return "EndLabel"; } }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -490,6 +490,22 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double GetAxisPositionValue(GridCoord grid, Axis axis, Vector3 pos)
|
||||||
|
{
|
||||||
|
if (axis is YAxis)
|
||||||
|
return GetAxisPositionValue(pos.y, grid.context.height, axis.context.minMaxRange, grid.context.y, axis.context.offset);
|
||||||
|
else if (axis is XAxis)
|
||||||
|
return GetAxisPositionValue(pos.x, grid.context.width, axis.context.minMaxRange, grid.context.x, axis.context.offset);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double GetAxisPositionValue(float xy, float axisLength, double axisRange, float axisStart, float axisOffset)
|
||||||
|
{
|
||||||
|
var yRate = axisRange / axisLength;
|
||||||
|
return yRate * (xy - axisStart - axisOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获得数值value在坐标轴上的坐标位置
|
/// 获得数值value在坐标轴上的坐标位置
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -7,5 +7,12 @@ namespace XCharts.Runtime
|
|||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
public class EndLabelStyle : LabelStyle
|
public class EndLabelStyle : LabelStyle
|
||||||
{
|
{
|
||||||
|
public EndLabelStyle()
|
||||||
|
{
|
||||||
|
m_Offset = new Vector3(5, 0, 0);
|
||||||
|
m_TextStyle.alignment = TextAnchor.MiddleLeft;
|
||||||
|
m_NumericFormatter = "f0";
|
||||||
|
m_Formatter = "{a}:{c}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,20 +67,20 @@ namespace XCharts.Runtime
|
|||||||
End
|
End
|
||||||
}
|
}
|
||||||
|
|
||||||
[SerializeField] private bool m_Show = true;
|
[SerializeField] protected bool m_Show = true;
|
||||||
[SerializeField] Position m_Position = Position.Outside;
|
[SerializeField] Position m_Position = Position.Outside;
|
||||||
[SerializeField] private Vector3 m_Offset;
|
[SerializeField] protected Vector3 m_Offset;
|
||||||
[SerializeField] private float m_Distance;
|
[SerializeField] protected float m_Distance;
|
||||||
[SerializeField] private string m_Formatter;
|
[SerializeField] protected string m_Formatter;
|
||||||
[SerializeField] private float m_PaddingLeftRight = 2f;
|
[SerializeField] protected float m_PaddingLeftRight = 2f;
|
||||||
[SerializeField] private float m_PaddingTopBottom = 2f;
|
[SerializeField] protected float m_PaddingTopBottom = 2f;
|
||||||
[SerializeField] private float m_BackgroundWidth = 0;
|
[SerializeField] protected float m_BackgroundWidth = 0;
|
||||||
[SerializeField] private float m_BackgroundHeight = 0;
|
[SerializeField] protected float m_BackgroundHeight = 0;
|
||||||
[SerializeField] private string m_NumericFormatter = "";
|
[SerializeField] protected string m_NumericFormatter = "";
|
||||||
[SerializeField] private bool m_AutoOffset = false;
|
[SerializeField] protected bool m_AutoOffset = false;
|
||||||
|
|
||||||
[SerializeField] private TextStyle m_TextStyle = new TextStyle();
|
[SerializeField] protected TextStyle m_TextStyle = new TextStyle();
|
||||||
private SerieLabelFormatterFunction m_FormatterFunction;
|
protected SerieLabelFormatterFunction m_FormatterFunction;
|
||||||
|
|
||||||
public void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace XCharts.Runtime
|
namespace XCharts.Runtime
|
||||||
@@ -16,5 +17,6 @@ namespace XCharts.Runtime
|
|||||||
public float bottom;
|
public float bottom;
|
||||||
public float top;
|
public float top;
|
||||||
public bool isPointerEnter;
|
public bool isPointerEnter;
|
||||||
|
public List<ChartLabel> endLabelList = new List<ChartLabel>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace XCharts.Runtime
|
|||||||
public class ChartLabel : Image
|
public class ChartLabel : Image
|
||||||
{
|
{
|
||||||
[SerializeField] private ChartText m_LabelText;
|
[SerializeField] private ChartText m_LabelText;
|
||||||
|
|
||||||
private bool m_AutoHideIconWhenLabelEmpty = false;
|
private bool m_AutoHideIconWhenLabelEmpty = false;
|
||||||
private bool m_LabelAutoSize = true;
|
private bool m_LabelAutoSize = true;
|
||||||
private float m_LabelPaddingLeftRight = 3f;
|
private float m_LabelPaddingLeftRight = 3f;
|
||||||
@@ -43,6 +43,7 @@ namespace XCharts.Runtime
|
|||||||
|
|
||||||
public bool autoHideIconWhenLabelEmpty { set { m_AutoHideIconWhenLabelEmpty = value; } }
|
public bool autoHideIconWhenLabelEmpty { set { m_AutoHideIconWhenLabelEmpty = value; } }
|
||||||
public bool isIconActive { get; private set; }
|
public bool isIconActive { get; private set; }
|
||||||
|
public bool isAnimationEnd { get; internal set; }
|
||||||
|
|
||||||
protected override void Awake()
|
protected override void Awake()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -266,6 +266,10 @@ namespace XCharts.Runtime
|
|||||||
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
m_SerieGrid = chart.GetChartComponent<GridCoord>(axis.gridIndex);
|
||||||
if (m_SerieGrid == null)
|
if (m_SerieGrid == null)
|
||||||
return;
|
return;
|
||||||
|
if (m_EndLabel != null && !m_SerieGrid.context.endLabelList.Contains(m_EndLabel))
|
||||||
|
{
|
||||||
|
m_SerieGrid.context.endLabelList.Add(m_EndLabel);
|
||||||
|
}
|
||||||
|
|
||||||
var visualMap = chart.GetVisualMapOfSerie(serie);
|
var visualMap = chart.GetVisualMapOfSerie(serie);
|
||||||
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
var dataZoom = chart.GetDataZoomOfAxis(axis);
|
||||||
|
|||||||
@@ -60,5 +60,39 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void RefreshEndLabelInternal()
|
||||||
|
{
|
||||||
|
base.RefreshEndLabelInternal();
|
||||||
|
if (m_SerieGrid == null) return;
|
||||||
|
if (!serie.animation.IsFinish()) return;
|
||||||
|
var endLabelList = m_SerieGrid.context.endLabelList;
|
||||||
|
if (endLabelList.Count <= 1) return;
|
||||||
|
|
||||||
|
endLabelList.Sort(delegate (ChartLabel a, ChartLabel b)
|
||||||
|
{
|
||||||
|
return b.transform.position.y.CompareTo(a.transform.position.y);
|
||||||
|
});
|
||||||
|
var lastY = float.NaN;
|
||||||
|
for (int i = 0; i < endLabelList.Count; i++)
|
||||||
|
{
|
||||||
|
var label = endLabelList[i];
|
||||||
|
if (!label.isAnimationEnd) continue;
|
||||||
|
var labelPosition = label.transform.localPosition;
|
||||||
|
if (float.IsNaN(lastY))
|
||||||
|
{
|
||||||
|
lastY = labelPosition.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var labelHeight = label.GetLabelHeight();
|
||||||
|
if (labelPosition.y + labelHeight > lastY)
|
||||||
|
{
|
||||||
|
label.SetPosition(new Vector3(labelPosition.x, lastY - labelHeight, labelPosition.z));
|
||||||
|
}
|
||||||
|
lastY = label.transform.localPosition.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,6 +295,14 @@ namespace XCharts.Runtime
|
|||||||
{
|
{
|
||||||
AddLineVertToVertexHelper(vh, ltp, lbp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
AddLineVertToVertexHelper(vh, ltp, lbp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, false, lastDataIsIgnore, isIgnore);
|
visualMap, serie.lineStyle, grid, axis, relativedAxis, false, lastDataIsIgnore, isIgnore);
|
||||||
|
if (dataCount == 2 || isBreak)
|
||||||
|
{
|
||||||
|
AddLineVertToVertexHelper(vh, clp, crp, lineColor, isVisualMapGradient, isLineStyleGradient,
|
||||||
|
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||||
|
serie.context.lineEndPostion = cp;
|
||||||
|
serie.context.lineEndValue = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bitp == bibp)
|
if (bitp == bibp)
|
||||||
@@ -327,6 +335,8 @@ namespace XCharts.Runtime
|
|||||||
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
visualMap, serie.lineStyle, grid, axis, relativedAxis, true, lastDataIsIgnore, isIgnore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
serie.context.lineEndPostion = cp;
|
||||||
|
serie.context.lineEndValue = AxisHelper.GetAxisPositionValue(grid, relativedAxis, cp);
|
||||||
lastDataIsIgnore = isIgnore;
|
lastDataIsIgnore = isIgnore;
|
||||||
if (isBreak)
|
if (isBreak)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ namespace XCharts.Runtime
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Vector3 center;
|
public Vector3 center;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// 线段终点
|
||||||
|
/// </summary>
|
||||||
|
public Vector3 lineEndPostion;
|
||||||
|
public double lineEndValue;
|
||||||
|
/// <summary>
|
||||||
/// 内半径
|
/// 内半径
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float insideRadius;
|
public float insideRadius;
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ namespace XCharts.Runtime
|
|||||||
private static readonly string s_SerieLabelObjectName = "label";
|
private static readonly string s_SerieLabelObjectName = "label";
|
||||||
private static readonly string s_SerieTitleObjectName = "title";
|
private static readonly string s_SerieTitleObjectName = "title";
|
||||||
private static readonly string s_SerieRootObjectName = "serie";
|
private static readonly string s_SerieRootObjectName = "serie";
|
||||||
|
private static readonly string s_SerieEndLabelObjectName = "end_label";
|
||||||
protected GameObject m_SerieRoot;
|
protected GameObject m_SerieRoot;
|
||||||
protected GameObject m_SerieLabelRoot;
|
protected GameObject m_SerieLabelRoot;
|
||||||
protected bool m_InitedLabel;
|
protected bool m_InitedLabel;
|
||||||
@@ -55,6 +56,7 @@ namespace XCharts.Runtime
|
|||||||
protected bool m_LastCheckContextFlag = false;
|
protected bool m_LastCheckContextFlag = false;
|
||||||
protected bool m_LegendEnter = false;
|
protected bool m_LegendEnter = false;
|
||||||
protected int m_LegendEnterIndex;
|
protected int m_LegendEnterIndex;
|
||||||
|
protected ChartLabel m_EndLabel;
|
||||||
|
|
||||||
public T serie { get; internal set; }
|
public T serie { get; internal set; }
|
||||||
public GameObject labelObject { get { return m_SerieLabelRoot; } }
|
public GameObject labelObject { get { return m_SerieLabelRoot; } }
|
||||||
@@ -77,8 +79,8 @@ namespace XCharts.Runtime
|
|||||||
if (m_RefreshLabel)
|
if (m_RefreshLabel)
|
||||||
{
|
{
|
||||||
m_RefreshLabel = false;
|
m_RefreshLabel = false;
|
||||||
if (m_InitedLabel)
|
RefreshLabelInternal();
|
||||||
RefreshLabelInternal();
|
RefreshEndLabelInternal();
|
||||||
}
|
}
|
||||||
if (serie.dataDirty)
|
if (serie.dataDirty)
|
||||||
{
|
{
|
||||||
@@ -91,6 +93,12 @@ namespace XCharts.Runtime
|
|||||||
serie.labelDirty = false;
|
serie.labelDirty = false;
|
||||||
serie.label.ClearComponentDirty();
|
serie.label.ClearComponentDirty();
|
||||||
InitSerieLabel();
|
InitSerieLabel();
|
||||||
|
InitSerieEndLabel();
|
||||||
|
}
|
||||||
|
if (serie.endLabel != null && serie.endLabel.componentDirty)
|
||||||
|
{
|
||||||
|
serie.endLabel.ClearComponentDirty();
|
||||||
|
InitSerieEndLabel();
|
||||||
}
|
}
|
||||||
if (serie.titleStyle != null && (serie.titleDirty || serie.titleStyle.componentDirty))
|
if (serie.titleStyle != null && (serie.titleDirty || serie.titleStyle.componentDirty))
|
||||||
{
|
{
|
||||||
@@ -126,6 +134,7 @@ namespace XCharts.Runtime
|
|||||||
InitRoot();
|
InitRoot();
|
||||||
InitSerieLabel();
|
InitSerieLabel();
|
||||||
InitSerieTitle();
|
InitSerieTitle();
|
||||||
|
InitSerieEndLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RemoveComponent()
|
public override void RemoveComponent()
|
||||||
@@ -265,6 +274,46 @@ namespace XCharts.Runtime
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitSerieEndLabel()
|
||||||
|
{
|
||||||
|
if (serie.endLabel == null)
|
||||||
|
{
|
||||||
|
if (m_EndLabel != null)
|
||||||
|
{
|
||||||
|
m_EndLabel.SetActive(false);
|
||||||
|
m_EndLabel = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_SerieRoot == null)
|
||||||
|
InitRoot();
|
||||||
|
var serieLabel = serie.endLabel;
|
||||||
|
var textStyle = serieLabel.textStyle;
|
||||||
|
var dataAutoColor = (Color)chart.theme.GetColor(serie.index);
|
||||||
|
|
||||||
|
var color = serieLabel.textStyle.autoColor ? dataAutoColor : chart.theme.common.textColor;
|
||||||
|
|
||||||
|
var anchorMin = new Vector2(0f, 0.5f);
|
||||||
|
var anchorMax = new Vector2(0f, 0.5f);
|
||||||
|
var pivot = new Vector2(0f, 0.5f);
|
||||||
|
var sizeDelta = new Vector2(50, textStyle.GetFontSize(chart.theme.common) + 2);
|
||||||
|
var labelObj = ChartHelper.AddObject(s_SerieEndLabelObjectName, m_SerieRoot.transform, anchorMin, anchorMax, pivot, sizeDelta);
|
||||||
|
var txt = ChartHelper.AddTextObject("Text", labelObj.transform, anchorMin, anchorMax, pivot, sizeDelta, textStyle,
|
||||||
|
chart.theme.common);
|
||||||
|
txt.SetColor(color);
|
||||||
|
txt.SetAlignment(textStyle.alignment);
|
||||||
|
txt.SetText("Text");
|
||||||
|
txt.SetLocalPosition(new Vector2(0, 0));
|
||||||
|
txt.SetLocalEulerAngles(Vector3.zero);
|
||||||
|
|
||||||
|
var isAutoSize = serieLabel.backgroundWidth == 0 || serieLabel.backgroundHeight == 0;
|
||||||
|
m_EndLabel = ChartHelper.GetOrAddComponent<ChartLabel>(labelObj);
|
||||||
|
m_EndLabel.SetLabel(labelObj, isAutoSize, serieLabel.paddingLeftRight, serieLabel.paddingTopBottom);
|
||||||
|
m_EndLabel.SetIconActive(false);
|
||||||
|
m_EndLabel.SetActive(true);
|
||||||
|
RefreshEndLabelInternal();
|
||||||
|
}
|
||||||
|
|
||||||
private void InitSerieTitle()
|
private void InitSerieTitle()
|
||||||
{
|
{
|
||||||
if (m_SerieRoot == null)
|
if (m_SerieRoot == null)
|
||||||
@@ -367,6 +416,27 @@ namespace XCharts.Runtime
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual void RefreshEndLabelInternal()
|
||||||
|
{
|
||||||
|
if (m_EndLabel == null)
|
||||||
|
return;
|
||||||
|
var endLabelStyle = serie.endLabel;
|
||||||
|
if (endLabelStyle == null)
|
||||||
|
return;
|
||||||
|
var dataCount = serie.context.drawPoints.Count;
|
||||||
|
var active = endLabelStyle.show && dataCount > 0;
|
||||||
|
m_EndLabel.SetActive(active);
|
||||||
|
if (active)
|
||||||
|
{
|
||||||
|
var value = serie.context.lineEndValue;
|
||||||
|
var content = SerieLabelHelper.GetFormatterContent(serie, null, value, 0,
|
||||||
|
endLabelStyle, Color.clear);
|
||||||
|
m_EndLabel.SetText(content);
|
||||||
|
m_EndLabel.SetPosition(serie.context.lineEndPostion + endLabelStyle.offset);
|
||||||
|
}
|
||||||
|
m_EndLabel.isAnimationEnd = serie.animation.IsFinish();
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
private void UpdateLabelPosition(SerieData serieData, LabelStyle currLabel)
|
||||||
{
|
{
|
||||||
var isNeedInvertPositionSerie = serie is Line;
|
var isNeedInvertPositionSerie = serie is Line;
|
||||||
|
|||||||
@@ -289,20 +289,25 @@ namespace XUGL
|
|||||||
ref Vector3 ntp, ref Vector3 nbp,
|
ref Vector3 ntp, ref Vector3 nbp,
|
||||||
ref Vector3 itp, ref Vector3 ibp,
|
ref Vector3 itp, ref Vector3 ibp,
|
||||||
ref Vector3 clp, ref Vector3 crp,
|
ref Vector3 clp, ref Vector3 crp,
|
||||||
ref bool bitp, ref bool bibp, int debugIndex = 0
|
ref bool bitp, ref bool bibp, int debugIndex = 0)
|
||||||
)
|
|
||||||
{
|
{
|
||||||
var dir1 = (cp - lp).normalized;
|
var dir1 = (cp - lp).normalized;
|
||||||
var dir2 = (cp - np).normalized;
|
|
||||||
var dir1v = Vector3.Cross(dir1, Vector3.forward).normalized * width;
|
var dir1v = Vector3.Cross(dir1, Vector3.forward).normalized * width;
|
||||||
var dir2v = Vector3.Cross(dir2, Vector3.back).normalized * width;
|
|
||||||
|
|
||||||
ltp = lp - dir1v;
|
ltp = lp - dir1v;
|
||||||
lbp = lp + dir1v;
|
lbp = lp + dir1v;
|
||||||
|
if (debugIndex == 1 && cp == np)
|
||||||
|
{
|
||||||
|
ntp = np - dir1v;
|
||||||
|
nbp = np + dir1v;
|
||||||
|
clp = cp - dir1v;
|
||||||
|
crp = cp + dir1v;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dir2 = (cp - np).normalized;
|
||||||
|
var dir2v = Vector3.Cross(dir2, Vector3.back).normalized * width;
|
||||||
ntp = np - dir2v;
|
ntp = np - dir2v;
|
||||||
nbp = np + dir2v;
|
nbp = np + dir2v;
|
||||||
|
|
||||||
clp = cp - dir2v;
|
clp = cp - dir2v;
|
||||||
crp = cp + dir2v;
|
crp = cp + dir2v;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user