diff --git a/Editor/PropertyDrawers/LegendDrawer.cs b/Editor/PropertyDrawers/LegendDrawer.cs
index 09dc977a..a84378f3 100644
--- a/Editor/PropertyDrawers/LegendDrawer.cs
+++ b/Editor/PropertyDrawers/LegendDrawer.cs
@@ -20,6 +20,7 @@ namespace XCharts
if (MakeFoldout(prop, "m_Show"))
{
++EditorGUI.indentLevel;
+ PropertyField(prop, "m_IconType");
PropertyField(prop, "m_ItemWidth");
PropertyField(prop, "m_ItemHeight");
PropertyField(prop, "m_ItemGap");
diff --git a/Editor/PropertyDrawers/SettingsDrawer.cs b/Editor/PropertyDrawers/SettingsDrawer.cs
index 016492be..9ff7f66f 100644
--- a/Editor/PropertyDrawers/SettingsDrawer.cs
+++ b/Editor/PropertyDrawers/SettingsDrawer.cs
@@ -20,7 +20,7 @@ namespace XCharts
if (MakeFoldout(prop, ""))
{
var btnWidth = 50;
- var btnRect = new Rect(pos.x + pos.width - btnWidth, pos.y, btnWidth, EditorGUIUtility.singleLineHeight);
+ var btnRect = new Rect(pos.x + pos.width - btnWidth, pos.y, btnWidth, EditorGUIUtility.singleLineHeight);
if (GUI.Button(btnRect, new GUIContent("Reset", "Reset to default settings")))
{
var chart = prop.serializedObject.targetObject as BaseChart;
@@ -32,7 +32,8 @@ namespace XCharts
PropertyField(prop, "m_LineSmoothness");
PropertyField(prop, "m_LineSegmentDistance");
PropertyField(prop, "m_CicleSmoothness");
-
+ PropertyField(prop, "m_LegendIconLineWidth");
+ PropertyListField(prop, "m_LegendIconCornerRadius", true);
--EditorGUI.indentLevel;
}
}
diff --git a/Runtime/Component/Main/Legend.cs b/Runtime/Component/Main/Legend.cs
index f4bb1336..a20e273b 100644
--- a/Runtime/Component/Main/Legend.cs
+++ b/Runtime/Component/Main/Legend.cs
@@ -19,6 +19,37 @@ namespace XCharts
[System.Serializable]
public class Legend : MainComponent, IPropertyChanged
{
+ public enum Type
+ {
+ ///
+ /// 自动匹配。
+ ///
+ Auto,
+ ///
+ /// 自定义图标。
+ ///
+ Custom,
+ ///
+ /// 空心圆。
+ ///
+ EmptyCircle,
+ ///
+ /// 圆形。
+ ///
+ Circle,
+ ///
+ /// 正方形。可通过Setting的legendIconCornerRadius参数调整圆角。
+ ///
+ Rect,
+ ///
+ /// 三角形。
+ ///
+ Triangle,
+ ///
+ /// 菱形。
+ ///
+ Diamond,
+ }
///
/// Selected mode of legend, which controls whether series can be toggled displaying by clicking legends.
/// 图例选择的模式,控制是否可以通过点击图例改变系列的显示状态。默认开启图例选择,可以设成 None 关闭。
@@ -39,10 +70,11 @@ namespace XCharts
None
}
[SerializeField] private bool m_Show = true;
+ [SerializeField] private Type m_IconType;
[SerializeField] private SelectedMode m_SelectedMode;
[SerializeField] private Orient m_Orient = Orient.Horizonal;
[SerializeField] private Location m_Location = Location.defaultRight;
- [SerializeField] private float m_ItemWidth = 24.0f;
+ [SerializeField] private float m_ItemWidth = 25.0f;
[SerializeField] private float m_ItemHeight = 12.0f;
[SerializeField] private float m_ItemGap = 10f;
[SerializeField] private bool m_ItemAutoColor = true;
@@ -64,11 +96,20 @@ namespace XCharts
set { if (PropertyUtil.SetStruct(ref m_Show, value)) SetComponentDirty(); }
}
///
+ /// Type of legend.
+ /// 图例类型。
+ /// [default:Type.Auto]
+ ///
+ public Type iconType
+ {
+ get { return m_IconType; }
+ set { if (PropertyUtil.SetStruct(ref m_IconType, value)) SetAllDirty(); }
+ }
+ ///
/// Selected mode of legend, which controls whether series can be toggled displaying by clicking legends.
/// 选择模式。控制是否可以通过点击图例改变系列的显示状态。默认开启图例选择,可以设成 None 关闭。
/// [default:SelectedMode.Multiple]
///
- ///
public SelectedMode selectedMode
{
get { return m_SelectedMode; }
@@ -226,11 +267,12 @@ namespace XCharts
{
var legend = new Legend
{
+ m_IconType = Type.Auto,
m_Show = false,
m_SelectedMode = SelectedMode.Multiple,
m_Orient = Orient.Horizonal,
m_Location = Location.defaultTop,
- m_ItemWidth = 24.0f,
+ m_ItemWidth = 25.0f,
m_ItemHeight = 12.0f,
m_ItemGap = 10f,
};
@@ -336,6 +378,7 @@ namespace XCharts
{
m_DataBtnList[name] = item;
int index = m_DataBtnList.Values.Count;
+ item.SetIconActive(iconType == Type.Custom);
item.SetActive(show);
}
diff --git a/Runtime/Component/Main/Settings.cs b/Runtime/Component/Main/Settings.cs
index d81c6737..98e5c6bb 100644
--- a/Runtime/Component/Main/Settings.cs
+++ b/Runtime/Component/Main/Settings.cs
@@ -22,6 +22,8 @@ namespace XCharts
[SerializeField] [Range(1f, 20)] protected float m_LineSmoothness = 2f;
[SerializeField] [Range(1f, 20)] protected float m_LineSegmentDistance = 3f;
[SerializeField] [Range(1, 10)] protected float m_CicleSmoothness = 2f;
+ [SerializeField] protected float m_LegendIconLineWidth = 2;
+ [SerializeField] private float[] m_LegendIconCornerRadius = new float[] { 0.25f, 0.25f, 0.25f, 0.25f };
///
/// max painter.
@@ -75,6 +77,26 @@ namespace XCharts
set { if (PropertyUtil.SetStruct(ref m_CicleSmoothness, value < 0 ? 1f : value)) SetVerticesDirty(); }
}
+ ///
+ /// the width of line serie legend.
+ /// Line类型图例图标的线条宽度。
+ ///
+ public float legendIconLineWidth
+ {
+ get { return m_LegendIconLineWidth; }
+ set { if (PropertyUtil.SetStruct(ref m_LegendIconLineWidth, value)) SetVerticesDirty(); }
+ }
+
+ ///
+ /// The radius of rounded corner. Its unit is px. Use array to respectively specify the 4 corner radiuses((clockwise upper left, upper right, bottom right and bottom left)).
+ /// 图例圆角半径。用数组分别指定4个圆角半径(顺时针左上,右上,右下,左下)。
+ ///
+ public float[] legendIconCornerRadius
+ {
+ get { return m_LegendIconCornerRadius; }
+ set { if (PropertyUtil.SetClass(ref m_LegendIconCornerRadius, value, true)) SetVerticesDirty(); }
+ }
+
public void Copy(Settings settings)
{
m_MaxPainter = settings.maxPainter;
@@ -82,6 +104,8 @@ namespace XCharts
m_LineSmoothness = settings.lineSmoothness;
m_LineSegmentDistance = settings.lineSegmentDistance;
m_CicleSmoothness = settings.cicleSmoothness;
+ m_LegendIconLineWidth = settings.legendIconLineWidth;
+ ChartHelper.CopyArray(m_LegendIconCornerRadius, settings.legendIconCornerRadius);
}
public void Reset()
@@ -100,6 +124,8 @@ namespace XCharts
m_LineSmoothness = XChartsSettings.lineSmoothness,
m_LineSegmentDistance = XChartsSettings.lineSegmentDistance,
m_CicleSmoothness = XChartsSettings.cicleSmoothness,
+ m_LegendIconLineWidth = 2,
+ m_LegendIconCornerRadius = new float[] { 0.25f, 0.25f, 0.25f, 0.25f }
};
}
}
diff --git a/Runtime/Internal/BaseChart.cs b/Runtime/Internal/BaseChart.cs
index 1dcf8298..246b3986 100644
--- a/Runtime/Internal/BaseChart.cs
+++ b/Runtime/Internal/BaseChart.cs
@@ -815,6 +815,7 @@ namespace XCharts
vh.Clear();
DrawBackground(vh);
DrawPainterBase(vh);
+ DrawLegend(vh);
foreach (var drawSerie in m_DrawSeries) drawSerie.DrawBase(vh);
}
@@ -868,6 +869,81 @@ namespace XCharts
UGL.DrawQuadrilateral(vh, p1, p2, p3, p4, backgroundColor);
}
+ protected virtual void DrawLegend(VertexHelper vh)
+ {
+ if (m_Series.Count == 0) return;
+ foreach (var legend in m_Legends)
+ {
+ if (!legend.show) continue;
+ if (legend.iconType == Legend.Type.Custom) continue;
+ foreach (var kv in legend.buttonList)
+ {
+ var item = kv.Value;
+ var rect = item.GetIconRect();
+ var radius = Mathf.Min(rect.width, rect.height) / 2;
+ var color = item.GetIconColor();
+ var iconType = legend.iconType;
+ if (legend.iconType == Legend.Type.Auto)
+ {
+ var serie = m_Series.GetSerie(item.legendName);
+ if (serie != null && serie.type == SerieType.Line)
+ {
+ var sp = new Vector3(rect.center.x - rect.width / 2, rect.center.y);
+ var ep = new Vector3(rect.center.x + rect.width / 2, rect.center.y);
+ UGL.DrawLine(vh, sp, ep, m_Settings.legendIconLineWidth, color);
+ if (!serie.symbol.show) continue;
+ switch (serie.symbol.type)
+ {
+ case SerieSymbolType.None:
+ continue;
+ case SerieSymbolType.Circle:
+ iconType = Legend.Type.Circle;
+ break;
+ case SerieSymbolType.Diamond:
+ iconType = Legend.Type.Diamond;
+ break;
+ case SerieSymbolType.EmptyCircle:
+ iconType = Legend.Type.EmptyCircle;
+ break;
+ case SerieSymbolType.Rect:
+ iconType = Legend.Type.Rect;
+ break;
+ case SerieSymbolType.Triangle:
+ iconType = Legend.Type.Triangle;
+ break;
+ }
+ }
+ else
+ {
+ iconType = Legend.Type.Rect;
+ }
+ }
+ switch (iconType)
+ {
+ case Legend.Type.Rect:
+ var cornerRadius = m_Settings.legendIconCornerRadius;
+ UGL.DrawRoundRectangle(vh, rect.center, rect.width, rect.height, color, color,
+ 0, cornerRadius, false, 0.5f);
+ break;
+ case Legend.Type.Circle:
+ UGL.DrawCricle(vh, rect.center, radius, color);
+ break;
+ case Legend.Type.Diamond:
+ UGL.DrawDiamond(vh, rect.center, radius, color);
+ break;
+ case Legend.Type.EmptyCircle:
+ var backgroundColor = ThemeHelper.GetBackgroundColor(m_Theme, m_Background);
+ UGL.DrawEmptyCricle(vh, rect.center, radius, 2 * m_Settings.legendIconLineWidth,
+ color, color, backgroundColor, 1f);
+ break;
+ case Legend.Type.Triangle:
+ UGL.DrawTriangle(vh, rect.center, 1.2f * radius, color);
+ break;
+ }
+ }
+ }
+ }
+
public void DrawSymbol(VertexHelper vh, SerieSymbolType type, float symbolSize,
float tickness, Vector3 pos, Color32 color, Color32 toColor, float gap, float[] cornerRadius)
{
diff --git a/Runtime/Internal/Object/LegendItem.cs b/Runtime/Internal/Object/LegendItem.cs
index 40b81be9..4a5acde6 100644
--- a/Runtime/Internal/Object/LegendItem.cs
+++ b/Runtime/Internal/Object/LegendItem.cs
@@ -105,6 +105,28 @@ namespace XCharts
}
}
+ public Rect GetIconRect()
+ {
+ if (m_GameObject && m_IconRect)
+ {
+ var pos = m_GameObject.transform.localPosition;
+ var sizeDelta = m_IconRect.sizeDelta;
+ var y = pos.y - (m_Rect.sizeDelta.y - sizeDelta.y) / 2 - sizeDelta.y;
+ return new Rect(pos.x, y, m_IconRect.sizeDelta.x, m_IconRect.sizeDelta.y);
+ }
+ else
+ {
+ return Rect.zero;
+ }
+ }
+
+ public Color GetIconColor()
+ {
+ if (m_Icon) return m_Icon.color;
+ else return Color.clear;
+ }
+
+
public void SetIconColor(Color color)
{
if (m_Icon)
@@ -121,6 +143,14 @@ namespace XCharts
}
}
+ public void SetIconActive(bool active)
+ {
+ if (m_Icon)
+ {
+ m_Icon.gameObject.SetActive(active);
+ }
+ }
+
public void SetContentColor(Color color)
{
if (m_Text != null)
diff --git a/Runtime/Internal/Utility/ChartDrawer.cs b/Runtime/Internal/Utility/ChartDrawer.cs
index 62fbde61..2a13fe40 100644
--- a/Runtime/Internal/Utility/ChartDrawer.cs
+++ b/Runtime/Internal/Utility/ChartDrawer.cs
@@ -52,7 +52,6 @@ namespace XCharts
}
else
{
- //UGL.DrawPolygon(vh, pos, symbolSize, color, toColor);
UGL.DrawRoundRectangle(vh, pos, symbolSize, symbolSize, color, color, 0, cornerRadius, true);
}
break;
diff --git a/Runtime/Internal/Utility/ChartHelper.cs b/Runtime/Internal/Utility/ChartHelper.cs
index d7514332..25b43555 100644
--- a/Runtime/Internal/Utility/ChartHelper.cs
+++ b/Runtime/Internal/Utility/ChartHelper.cs
@@ -621,6 +621,16 @@ namespace XCharts
foreach (var item in fromList) toList.Add(item);
return true;
}
+ public static bool CopyArray(T[] toList, T[] fromList)
+ {
+ if (toList == null || fromList == null) return false;
+ if (toList.Length != fromList.Length)
+ {
+ toList = new T[fromList.Length];
+ }
+ for (int i = 0; i < fromList.Length; i++) toList[i] = fromList[i];
+ return true;
+ }
public static List ParseFloatFromString(string jsonData)
{
diff --git a/Runtime/XUGL/UGL.cs b/Runtime/XUGL/UGL.cs
index 84935c94..3dd25405 100644
--- a/Runtime/XUGL/UGL.cs
+++ b/Runtime/XUGL/UGL.cs
@@ -566,7 +566,8 @@ namespace XUGL
///
///
public static void DrawRoundRectangle(VertexHelper vh, Vector3 center, float rectWidth, float rectHeight,
- Color32 color, Color32 toColor, float rotate = 0, float[] cornerRadius = null, bool isYAxis = false)
+ Color32 color, Color32 toColor, float rotate = 0, float[] cornerRadius = null, bool isYAxis = false,
+ float smoothness = 2)
{
var isGradient = !UGLHelper.IsValueEqualsColor(color, toColor);
var halfWid = rectWidth / 2;
@@ -645,10 +646,10 @@ namespace XUGL
if (roundRbLeft.x < roundLb.x) roundRbLeft.x = roundLb.x;
if (!isGradient)
{
- DrawSector(vh, roundLt, brLt, color, color, 270, 360, 1, isYAxis);
- DrawSector(vh, roundRt, brRt, toColor, toColor, 0, 90, 1, isYAxis);
- DrawSector(vh, roundRb, brRb, toColor, toColor, 90, 180, 1, isYAxis);
- DrawSector(vh, roundLb, brLb, color, color, 180, 270, 1, isYAxis);
+ DrawSector(vh, roundLt, brLt, color, color, 270, 360, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRt, brRt, toColor, toColor, 0, 90, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRb, brRb, toColor, toColor, 90, 180, 1, isYAxis, smoothness);
+ DrawSector(vh, roundLb, brLb, color, color, 180, 270, 1, isYAxis, smoothness);
DrawQuadrilateral(vh, ltIn, ltInRight, lbInRight, lbIn, color, color);
DrawQuadrilateral(vh, lbIn2, roundLb, roundLbRight, lbIn2Right, color, color);
@@ -677,10 +678,10 @@ namespace XUGL
var upRightColor = Color32.Lerp(tempRightColor, toColor, (maxRight - brRt) / maxRight);
var downRightColor = Color32.Lerp(tempRightColor, toColor, (maxRight - brRb) / maxRight);
- DrawSector(vh, roundLt, brLt, color, upLeftColor, 270, 360, 1, isYAxis);
- DrawSector(vh, roundRt, brRt, upRightColor, toColor, 0, 90, 1, isYAxis);
- DrawSector(vh, roundRb, brRb, downRightColor, toColor, 90, 180, 1, isYAxis);
- DrawSector(vh, roundLb, brLb, color, downLeftColor, 180, 270, 1, isYAxis);
+ DrawSector(vh, roundLt, brLt, color, upLeftColor, 270, 360, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRt, brRt, upRightColor, toColor, 0, 90, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRb, brRb, downRightColor, toColor, 90, 180, 1, isYAxis, smoothness);
+ DrawSector(vh, roundLb, brLb, color, downLeftColor, 180, 270, 1, isYAxis, smoothness);
DrawQuadrilateral(vh, lbIn, ltIn, ltInRight, lbInRight, color, tempLeftColor);
DrawQuadrilateral(vh, lbIn2, roundLb, roundLbRight, lbIn2Right, downLeftColor,
@@ -739,10 +740,10 @@ namespace XUGL
if (!isGradient)
{
- DrawSector(vh, roundLt, brLt, toColor, toColor, 270, 360, 1, isYAxis);
- DrawSector(vh, roundRt, brRt, toColor, toColor, 0, 90, 1, isYAxis);
- DrawSector(vh, roundRb, brRb, color, color, 90, 180, 1, isYAxis);
- DrawSector(vh, roundLb, brLb, color, color, 180, 270, 1, isYAxis);
+ DrawSector(vh, roundLt, brLt, toColor, toColor, 270, 360, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRt, brRt, toColor, toColor, 0, 90, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRb, brRb, color, color, 90, 180, 1, isYAxis, smoothness);
+ DrawSector(vh, roundLb, brLb, color, color, 180, 270, 1, isYAxis, smoothness);
DrawQuadrilateral(vh, ltIn2, rtIn, rtInDown, ltIn2Down, toColor, toColor);
DrawQuadrilateral(vh, ltIn, roundLt, roundLtDown, ltInDown, toColor, toColor);
@@ -765,10 +766,10 @@ namespace XUGL
var leftDownColor = Color32.Lerp(color, tempDownColor, brLb / maxdown);
var rightDownColor = Color32.Lerp(color, tempDownColor, brRb / maxdown);
- DrawSector(vh, roundLt, brLt, leftUpColor, toColor, 270, 360, 1, isYAxis);
- DrawSector(vh, roundRt, brRt, rightUpColor, toColor, 0, 90, 1, isYAxis);
- DrawSector(vh, roundRb, brRb, rightDownColor, color, 90, 180, 1, isYAxis);
- DrawSector(vh, roundLb, brLb, leftDownColor, color, 180, 270, 1, isYAxis);
+ DrawSector(vh, roundLt, brLt, leftUpColor, toColor, 270, 360, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRt, brRt, rightUpColor, toColor, 0, 90, 1, isYAxis, smoothness);
+ DrawSector(vh, roundRb, brRb, rightDownColor, color, 90, 180, 1, isYAxis, smoothness);
+ DrawSector(vh, roundLb, brLb, leftDownColor, color, 180, 270, 1, isYAxis, smoothness);
DrawQuadrilateral(vh, ltIn2, rtIn, rtInDown, ltIn2Down, toColor, tempUpColor);
DrawQuadrilateral(vh, ltIn, roundLt, roundLtDown, ltInDown, leftUpColor,