3.0 - unitypackage

This commit is contained in:
monitor1394
2022-01-05 21:40:48 +08:00
parent c160867765
commit 228a4b2840
846 changed files with 105 additions and 467693 deletions

View File

@@ -0,0 +1,414 @@

using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
/// <summary>
/// Legend component.The legend component shows different sets of tags, colors, and names.
/// You can control which series are not displayed by clicking on the legend.
/// 图例组件。
/// 图例组件展现了不同系列的标记,颜色和名字。可以通过点击图例控制哪些系列不显示。
/// </summary>
[System.Serializable]
[ComponentHandler(typeof(LegendHandler), true)]
public class Legend : MainComponent, IPropertyChanged
{
public enum Type
{
/// <summary>
/// 自动匹配。
/// </summary>
Auto,
/// <summary>
/// 自定义图标。
/// </summary>
Custom,
/// <summary>
/// 空心圆。
/// </summary>
EmptyCircle,
/// <summary>
/// 圆形。
/// </summary>
Circle,
/// <summary>
/// 正方形。可通过Setting的legendIconCornerRadius参数调整圆角。
/// </summary>
Rect,
/// <summary>
/// 三角形。
/// </summary>
Triangle,
/// <summary>
/// 菱形。
/// </summary>
Diamond,
}
/// <summary>
/// Selected mode of legend, which controls whether series can be toggled displaying by clicking legends.
/// 图例选择的模式,控制是否可以通过点击图例改变系列的显示状态。默认开启图例选择,可以设成 None 关闭。
/// </summary>
public enum SelectedMode
{
/// <summary>
/// 多选。
/// </summary>
Multiple,
/// <summary>
/// 单选。
/// </summary>
Single,
/// <summary>
/// 无法选择。
/// </summary>
None
};
[SerializeField] private bool m_Show = true;
[SerializeField] private Type m_IconType = Type.Auto;
[SerializeField] private SelectedMode m_SelectedMode = SelectedMode.Multiple;
[SerializeField] private Orient m_Orient = Orient.Horizonal;
[SerializeField] private Location m_Location = new Location() { align = Location.Align.TopCenter, top = 0.125f };
[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;
[SerializeField] private bool m_TextAutoColor = false;
[SerializeField] private string m_Formatter;
[SerializeField] private TextStyle m_TextStyle = new TextStyle() { offset = new Vector2(2f, 0), fontSize = 0 };
[SerializeField] private List<string> m_Data = new List<string>();
[SerializeField] private List<Sprite> m_Icons = new List<Sprite>();
public LegendContext context = new LegendContext();
/// <summary>
/// Whether to show legend component.
/// 是否显示图例组件。
/// </summary>
public bool show
{
get { return m_Show; }
set { if (PropertyUtil.SetStruct(ref m_Show, value)) SetComponentDirty(); }
}
/// <summary>
/// Type of legend.
/// 图例类型。
/// [default:Type.Auto]
/// </summary>
public Type iconType
{
get { return m_IconType; }
set { if (PropertyUtil.SetStruct(ref m_IconType, value)) SetAllDirty(); }
}
/// <summary>
/// Selected mode of legend, which controls whether series can be toggled displaying by clicking legends.
/// 选择模式。控制是否可以通过点击图例改变系列的显示状态。默认开启图例选择,可以设成 None 关闭。
/// [default:SelectedMode.Multiple]
/// </summary>
public SelectedMode selectedMode
{
get { return m_SelectedMode; }
set { if (PropertyUtil.SetStruct(ref m_SelectedMode, value)) SetComponentDirty(); }
}
/// <summary>
/// Specify whether the layout of legend component is horizontal or vertical.
/// 布局方式是横还是竖。
/// [default:Orient.Horizonal]
/// </summary>
public Orient orient
{
get { return m_Orient; }
set { if (PropertyUtil.SetStruct(ref m_Orient, value)) SetComponentDirty(); }
}
/// <summary>
/// The location of legend.
/// 图例显示的位置。
/// [default:Location.defaultTop]
/// </summary>
public Location location
{
get { return m_Location; }
set { if (PropertyUtil.SetClass(ref m_Location, value)) SetComponentDirty(); }
}
/// <summary>
/// Image width of legend symbol.
/// 图例标记的图形宽度。
/// [default:24f]
/// </summary>
public float itemWidth
{
get { return m_ItemWidth; }
set { if (PropertyUtil.SetStruct(ref m_ItemWidth, value)) SetComponentDirty(); }
}
/// <summary>
/// Image height of legend symbol.
/// 图例标记的图形高度。
/// [default:12f]
/// </summary>
public float itemHeight
{
get { return m_ItemHeight; }
set { if (PropertyUtil.SetStruct(ref m_ItemHeight, value)) SetComponentDirty(); }
}
/// <summary>
/// The distance between each legend, horizontal distance in horizontal layout, and vertical distance in vertical layout.
/// 图例每项之间的间隔。横向布局时为水平间隔,纵向布局时为纵向间隔。
/// [default:10f]
/// </summary>
public float itemGap
{
get { return m_ItemGap; }
set { if (PropertyUtil.SetStruct(ref m_ItemGap, value)) SetComponentDirty(); }
}
/// <summary>
/// Whether the legend symbol matches the color automatically.
/// 图例标记的图形是否自动匹配颜色。
/// [default:true]
/// </summary>
public bool itemAutoColor
{
get { return m_ItemAutoColor; }
set { if (PropertyUtil.SetStruct(ref m_ItemAutoColor, value)) SetComponentDirty(); }
}
/// <summary>
/// Whether the legend text matches the color automatically.
/// 图例标记的文本是否自动匹配颜色。
/// [default:false]
/// </summary>
public bool textAutoColor
{
get { return m_TextAutoColor; }
set { if (PropertyUtil.SetStruct(ref m_TextAutoColor, value)) SetComponentDirty(); }
}
/// <summary>
/// Legend content string template formatter. Support for wrapping lines with \n. Template:{name}.
/// 图例内容字符串模版格式器。支持用 \n 换行。
/// 模板变量为图例名称 {name}。
/// [default:null]
/// </summary>
public string formatter
{
get { return m_Formatter; }
set { if (PropertyUtil.SetClass(ref m_Formatter, value)) SetComponentDirty(); }
}
/// <summary>
/// the style of text.
/// 文本样式。
/// </summary>
public TextStyle textStyle
{
get { return m_TextStyle; }
set { if (PropertyUtil.SetClass(ref m_TextStyle, value)) SetComponentDirty(); }
}
/// <summary>
/// Data array of legend. An array item is usually a name representing string. (If it is a pie chart,
/// it could also be the name of a single data in the pie chart) of a series.
/// If data is not specified, it will be auto collected from series.
/// 图例的数据数组。数组项通常为一个字符串,每一项代表一个系列的 name如果是饼图也可以是饼图单个数据的 name
/// 如果 data 没有被指定会自动从当前系列中获取。指定data时里面的数据项和serie匹配时才会生效。
/// </summary>
public List<string> data
{
get { return m_Data; }
set { if (value != null) { m_Data = value; SetComponentDirty(); } }
}
/// <summary>
/// 自定义的图例标记图形。
/// </summary>
public List<Sprite> icons
{
get { return m_Icons; }
set { if (value != null) { m_Icons = value; SetComponentDirty(); } }
}
/// <summary>
/// 图表是否需要刷新(图例组件不需要刷新图表)
/// </summary>
public override bool vertsDirty { get { return false; } }
/// <summary>
/// 组件是否需要刷新
/// </summary>
public override bool componentDirty
{
get { return m_ComponentDirty || location.componentDirty || textStyle.componentDirty; }
}
public override void ClearComponentDirty()
{
base.ClearComponentDirty();
location.ClearComponentDirty();
textStyle.ClearComponentDirty();
}
/// <summary>
/// Clear legend data.
/// 清空。
/// </summary>
public override void ClearData()
{
m_Data.Clear();
SetComponentDirty();
}
/// <summary>
/// Whether include in legend data by the specified name.
/// 是否包括由指定名字的图例
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
public bool ContainsData(string name)
{
return m_Data.Contains(name);
}
/// <summary>
/// Removes the legend with the specified name.
/// 移除指定名字的图例。
/// </summary>
/// <param name="name"></param>
public void RemoveData(string name)
{
if (m_Data.Contains(name))
{
m_Data.Remove(name);
SetComponentDirty();
}
}
/// <summary>
/// Add legend data.
/// 添加图例。
/// </summary>
/// <param name="name"></param>
public void AddData(string name)
{
if (!m_Data.Contains(name) && !string.IsNullOrEmpty(name))
{
m_Data.Add(name);
SetComponentDirty();
}
}
/// <summary>
/// Gets the legend for the specified index.
/// 获得指定索引的图例。
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public string GetData(int index)
{
if (index >= 0 && index < m_Data.Count)
{
return m_Data[index];
}
return null;
}
/// <summary>
/// Gets the index of the specified legend.
/// 获得指定图例的索引。
/// </summary>
/// <param name="legendName"></param>
/// <returns></returns>
public int GetIndex(string legendName)
{
return m_Data.IndexOf(legendName);
}
/// <summary>
/// Remove all legend buttons.
/// 移除所有图例按钮。
/// </summary>
public void RemoveButton()
{
context.buttonList.Clear();
}
/// <summary>
/// Bind buttons to legends.
/// 给图例绑定按钮。
/// </summary>
/// <param name="name"></param>
/// <param name="btn"></param>
/// <param name="total"></param>
public void SetButton(string name, LegendItem item, int total)
{
context.buttonList[name] = item;
int index = context.buttonList.Values.Count;
item.SetIconActive(iconType == Type.Custom);
item.SetActive(show);
}
/// <summary>
/// Update the legend button color.
/// 更新图例按钮颜色。
/// </summary>
/// <param name="name"></param>
/// <param name="color"></param>
public void UpdateButtonColor(string name, Color color)
{
if (context.buttonList.ContainsKey(name))
{
context.buttonList[name].SetIconColor(color);
}
}
/// <summary>
/// Update the text color of legend.
/// 更新图例文字颜色。
/// </summary>
/// <param name="name"></param>
/// <param name="color"></param>
public void UpdateContentColor(string name, Color color)
{
if (context.buttonList.ContainsKey(name))
{
context.buttonList[name].SetContentColor(color);
}
}
/// <summary>
/// Gets the legend button for the specified index.
/// 获得指定索引的图例按钮。
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Sprite GetIcon(int index)
{
if (index >= 0 && index < m_Icons.Count)
{
return m_Icons[index];
}
else
{
return null;
}
}
/// <summary>
/// Callback handling when parameters change.
/// 参数变更时的回调处理。
/// </summary>
public void OnChanged()
{
m_Location.OnChanged();
}
/// <summary>
/// 获得图例格式化后的显示内容。
/// </summary>
/// <param name="category"></param>
/// <returns></returns>
public string GetFormatterContent(string category)
{
if (string.IsNullOrEmpty(m_Formatter))
return category;
else
{
var content = m_Formatter.Replace("{name}", category);
content = content.Replace("\\n", "\n");
content = content.Replace("<br/>", "\n");
return content;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c53210fe487d047b6a51bacc0d3e7a71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,32 @@
using System.Collections.Generic;
using UnityEngine;
namespace XCharts
{
public class LegendContext : MainComponentContext
{
/// <summary>
/// 运行时图例的总宽度
/// </summary>
public float width { get; internal set; }
/// <summary>
/// 运行时图例的总高度
/// </summary>
public float height { get; internal set; }
/// <summary>
/// the button list of legend.
/// 图例按钮列表。
/// </summary>
internal Dictionary<string, LegendItem> buttonList = new Dictionary<string, LegendItem>();
/// <summary>
/// 多列时每列的宽度
/// </summary>
internal Dictionary<int, float> eachWidthDict = new Dictionary<int, float>();
/// <summary>
/// 单列高度
/// </summary>
internal float eachHeight { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c62c17c9d5b2b4a0fb260103c3ceb5ac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,218 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using XUGL;
namespace XCharts
{
[UnityEngine.Scripting.Preserve]
internal sealed class LegendHandler : MainComponentHandler<Legend>
{
private static readonly string s_LegendObjectName = "legend";
public override void InitComponent()
{
InitLegend(component);
}
public override void CheckComponent(System.Text.StringBuilder sb)
{
var legend = component;
if (ChartHelper.IsColorAlphaZero(legend.textStyle.color))
sb.AppendFormat("warning:legend{0}->textStyle->color alpha is 0\n", legend.index);
var serieNameList = SeriesHelper.GetLegalSerieNameList(chart.series);
if (serieNameList.Count == 0)
sb.AppendFormat("warning:legend{0} need serie.serieName or serieData.name not empty\n", legend.index);
foreach (var category in legend.data)
{
if (!serieNameList.Contains(category))
{
sb.AppendFormat("warning:legend{0} [{1}] is invalid, must be one of serie.serieName or serieData.name\n",
legend.index, category);
}
}
}
public override void DrawTop(VertexHelper vh)
{
DrawLegend(vh);
}
private void InitLegend(Legend legend)
{
legend.painter = null; // legend component does not need to paint
legend.refreshComponent = delegate ()
{
legend.OnChanged();
var legendObject = ChartHelper.AddObject(s_LegendObjectName + legend.index, chart.transform, chart.chartMinAnchor,
chart.chartMaxAnchor, chart.chartPivot, chart.chartSizeDelta);
legend.gameObject = legendObject;
legendObject.hideFlags = chart.chartHideFlags;
SeriesHelper.UpdateSerieNameList(chart, ref chart.m_LegendRealShowName);
List<string> datas;
if (legend.show && legend.data.Count > 0)
{
datas = new List<string>();
for (int i = 0; i < chart.m_LegendRealShowName.Count; i++)
{
if (legend.data.Contains(chart.m_LegendRealShowName[i])) datas.Add(chart.m_LegendRealShowName[i]);
}
}
else
{
datas = chart.m_LegendRealShowName;
}
int totalLegend = 0;
for (int i = 0; i < datas.Count; i++)
{
if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
totalLegend++;
}
legend.RemoveButton();
ChartHelper.HideAllObject(legendObject);
if (!legend.show) return;
for (int i = 0; i < datas.Count; i++)
{
if (!SeriesHelper.IsLegalLegendName(datas[i])) continue;
string legendName = legend.GetFormatterContent(datas[i]);
var readIndex = chart.m_LegendRealShowName.IndexOf(datas[i]);
var active = chart.IsActiveByLegend(datas[i]);
var bgColor = LegendHelper.GetIconColor(chart, legend, readIndex, datas[i], active);
var item = LegendHelper.AddLegendItem(legend, i, datas[i], legendObject.transform, chart.theme,
legendName, bgColor, active, readIndex);
legend.SetButton(legendName, item, totalLegend);
ChartHelper.ClearEventListener(item.button.gameObject);
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerDown, (data) =>
{
if (data.selectedObject == null || legend.selectedMode == Legend.SelectedMode.None) return;
var temp = data.selectedObject.name.Split('_');
string selectedName = temp[1];
int clickedIndex = int.Parse(temp[0]);
if (legend.selectedMode == Legend.SelectedMode.Multiple)
{
chart.OnLegendButtonClick(clickedIndex, selectedName, !chart.IsActiveByLegend(selectedName));
}
else
{
var btnList = legend.context.buttonList.Values.ToArray();
if (btnList.Length == 1)
{
chart.OnLegendButtonClick(0, selectedName, !chart.IsActiveByLegend(selectedName));
}
else
{
for (int n = 0; n < btnList.Length; n++)
{
temp = btnList[n].name.Split('_');
selectedName = btnList[n].legendName;
var index = btnList[n].index;
chart.OnLegendButtonClick(n, selectedName, index == clickedIndex ? true : false);
}
}
}
});
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerEnter, (data) =>
{
if (item.button == null) return;
var temp = item.button.name.Split('_');
string selectedName = temp[1];
int index = int.Parse(temp[0]);
chart.OnLegendButtonEnter(index, selectedName);
});
ChartHelper.AddEventListener(item.button.gameObject, EventTriggerType.PointerExit, (data) =>
{
if (item.button == null) return;
var temp = item.button.name.Split('_');
string selectedName = temp[1];
int index = int.Parse(temp[0]);
chart.OnLegendButtonExit(index, selectedName);
});
}
if (legend.selectedMode == Legend.SelectedMode.Single)
{
for (int n = 0; n < chart.m_LegendRealShowName.Count; n++)
{
chart.OnLegendButtonClick(n, chart.m_LegendRealShowName[n], n == 0 ? true : false);
}
}
LegendHelper.ResetItemPosition(legend, chart.chartPosition, chart.chartWidth, chart.chartHeight);
};
legend.refreshComponent();
}
private void DrawLegend(VertexHelper vh)
{
if (chart.series.Count == 0) return;
var legend = component;
if (!legend.show) return;
if (legend.iconType == Legend.Type.Custom) return;
foreach (var kv in legend.context.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 = chart.GetSerie(item.legendName);
if (serie != null && serie is 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, chart.settings.legendIconLineWidth, color);
if (!serie.symbol.show) continue;
switch (serie.symbol.type)
{
case SymbolType.None:
continue;
case SymbolType.Circle:
iconType = Legend.Type.Circle;
break;
case SymbolType.Diamond:
iconType = Legend.Type.Diamond;
break;
case SymbolType.EmptyCircle:
iconType = Legend.Type.EmptyCircle;
break;
case SymbolType.Rect:
iconType = Legend.Type.Rect;
break;
case SymbolType.Triangle:
iconType = Legend.Type.Triangle;
break;
}
}
else
{
iconType = Legend.Type.Rect;
}
}
switch (iconType)
{
case Legend.Type.Rect:
var cornerRadius = chart.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 = chart.theme.GetBackgroundColor(chart.GetChartComponent<Background>());
UGL.DrawEmptyCricle(vh, rect.center, radius, 2 * chart.settings.legendIconLineWidth,
color, color, backgroundColor, 1f);
break;
case Legend.Type.Triangle:
UGL.DrawTriangle(vh, rect.center, 1.2f * radius, color);
break;
}
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d05c7e75b9d3c4a839099bf152752af1
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,276 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
namespace XCharts
{
public static class LegendHelper
{
public static Color GetContentColor(int legendIndex, Legend legend, ThemeStyle theme, bool active)
{
var textStyle = legend.textStyle;
if (active)
{
if (legend.textAutoColor) return theme.GetColor(legendIndex);
else return !ChartHelper.IsClearColor(textStyle.color) ? textStyle.color : theme.legend.textColor;
}
else return theme.legend.unableColor;
}
public static Color GetIconColor(BaseChart chart, Legend legend, int readIndex, string legendName, bool active)
{
if (active)
{
if (legend.itemAutoColor || legend.GetIcon(readIndex) == null)
{
return SeriesHelper.GetNameColor(chart, readIndex, legendName);
}
else
return Color.white;
}
else return chart.theme.legend.unableColor;
}
public static LegendItem AddLegendItem(Legend legend, int i, string legendName, Transform parent,
ThemeStyle theme, string content, Color itemColor, bool active, int legendIndex)
{
var objName = i + "_" + legendName;
var anchorMin = new Vector2(0, 0.5f);
var anchorMax = new Vector2(0, 0.5f);
var pivot = new Vector2(0, 0.5f);
var sizeDelta = new Vector2(100, 30);
var iconSizeDelta = new Vector2(legend.itemWidth, legend.itemHeight);
var textStyle = legend.textStyle;
var contentColor = GetContentColor(legendIndex, legend, theme, active);
var objAnchorMin = new Vector2(0, 1);
var objAnchorMax = new Vector2(0, 1);
var objPivot = new Vector2(0, 1);
var btnObj = ChartHelper.AddObject(objName, parent, objAnchorMin, objAnchorMax, objPivot, sizeDelta, i);
var iconObj = ChartHelper.AddObject("icon", btnObj.transform, anchorMin, anchorMax, pivot, iconSizeDelta);
var contentObj = ChartHelper.AddObject("content", btnObj.transform, anchorMin, anchorMax, pivot, sizeDelta);
var img = ChartHelper.GetOrAddComponent<Image>(btnObj);
img.color = Color.clear;
ChartHelper.GetOrAddComponent<Button>(btnObj);
ChartHelper.GetOrAddComponent<Image>(iconObj);
ChartHelper.GetOrAddComponent<Image>(contentObj);
var txt = ChartHelper.AddTextObject("Text", contentObj.transform, anchorMin, anchorMax, pivot, sizeDelta,
textStyle, theme.legend);
txt.SetAlignment(textStyle.GetAlignment(TextAnchor.MiddleLeft));
txt.SetColor(contentColor);
var item = new LegendItem();
item.index = i;
item.name = objName;
item.legendName = legendName;
item.SetObject(btnObj);
item.SetIconSize(legend.itemWidth, legend.itemHeight);
item.SetIconColor(itemColor);
item.SetIconImage(legend.GetIcon(i));
item.SetContentPosition(textStyle.offsetv3);
item.SetContent(content);
item.SetContentBackgroundColor(textStyle.backgroundColor);
return item;
}
public static void ResetItemPosition(Legend legend, Vector3 chartPos, float chartWidth, float chartHeight)
{
legend.location.UpdateRuntimeData(chartWidth, chartHeight);
var startX = 0f;
var startY = 0f;
var legendMaxWidth = chartWidth - legend.location.runtimeLeft - legend.location.runtimeRight;
var legendMaxHeight = chartHeight - legend.location.runtimeTop - legend.location.runtimeBottom;
UpdateLegendWidthAndHeight(legend, legendMaxWidth, legendMaxHeight);
var legendRuntimeWidth = legend.context.width;
var legendRuntimeHeight = legend.context.height;
var isVertical = legend.orient == Orient.Vertical;
switch (legend.location.align)
{
case Location.Align.TopCenter:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + chartHeight - legend.location.runtimeTop;
break;
case Location.Align.TopLeft:
startX = chartPos.x + legend.location.runtimeLeft;
startY = chartPos.y + chartHeight - legend.location.runtimeTop;
break;
case Location.Align.TopRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
startY = chartPos.y + chartHeight - legend.location.runtimeTop;
break;
case Location.Align.Center:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.CenterLeft:
startX = chartPos.x + legend.location.runtimeLeft;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.CenterRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
startY = chartPos.y + chartHeight / 2 + legendRuntimeHeight / 2;
break;
case Location.Align.BottomCenter:
startX = chartPos.x + chartWidth / 2 - legendRuntimeWidth / 2;
startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
break;
case Location.Align.BottomLeft:
startX = chartPos.x + legend.location.runtimeLeft;
startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
break;
case Location.Align.BottomRight:
startX = chartPos.x + chartWidth - legendRuntimeWidth - legend.location.runtimeRight;
startY = chartPos.y + legendRuntimeHeight + legend.location.runtimeBottom;
break;
}
if (isVertical) SetVerticalItemPosition(legend, legendMaxHeight, startX, startY);
else SetHorizonalItemPosition(legend, legendMaxWidth, startX, startY);
}
private static void SetVerticalItemPosition(Legend legend, float legendMaxHeight, float startX, float startY)
{
var currHeight = 0f;
var offsetX = 0f;
var row = 0;
foreach (var kv in legend.context.buttonList)
{
var item = kv.Value;
if (currHeight + item.height > legendMaxHeight)
{
currHeight = 0;
offsetX += legend.context.eachWidthDict[row];
row++;
}
item.SetPosition(new Vector3(startX + offsetX, startY - currHeight));
currHeight += item.height + legend.itemGap;
}
}
private static void SetHorizonalItemPosition(Legend legend, float legendMaxWidth, float startX, float startY)
{
var currWidth = 0f;
var offsetY = 0f;
foreach (var kv in legend.context.buttonList)
{
var item = kv.Value;
if (currWidth + item.width > legendMaxWidth)
{
currWidth = 0;
offsetY += legend.context.eachHeight;
}
item.SetPosition(new Vector3(startX + currWidth, startY - offsetY));
currWidth += item.width + legend.itemGap;
}
}
private static void UpdateLegendWidthAndHeight(Legend legend, float maxWidth, float maxHeight)
{
var width = 0f;
var height = 0f;
var realHeight = 0f;
var realWidth = 0f;
legend.context.eachWidthDict.Clear();
legend.context.eachHeight = 0;
if (legend.orient == Orient.Horizonal)
{
foreach (var kv in legend.context.buttonList)
{
if (width + kv.Value.width > maxWidth)
{
realWidth = width - legend.itemGap;
realHeight += height + legend.itemGap;
if (legend.context.eachHeight < height + legend.itemGap)
{
legend.context.eachHeight = height + legend.itemGap;
}
height = 0;
width = 0;
}
width += kv.Value.width + legend.itemGap;
if (kv.Value.height > height)
height = kv.Value.height;
}
width -= legend.itemGap;
legend.context.height = realHeight + height;
legend.context.width = realWidth > 0 ? realWidth : width;
}
else
{
var row = 0;
foreach (var kv in legend.context.buttonList)
{
if (height + kv.Value.height > maxHeight)
{
realHeight = height - legend.itemGap;
realWidth += width + legend.itemGap;
legend.context.eachWidthDict[row] = width + legend.itemGap;
row++;
height = 0;
width = 0;
}
height += kv.Value.height + legend.itemGap;
if (kv.Value.width > width)
width = kv.Value.width;
}
height -= legend.itemGap;
legend.context.height = realHeight > 0 ? realHeight : height;
legend.context.width = realWidth + width;
}
}
private static bool IsBeyondWidth(Legend legend, float maxWidth)
{
var totalWidth = 0f;
foreach (var kv in legend.context.buttonList)
{
var item = kv.Value;
totalWidth += item.width + legend.itemGap;
if (totalWidth > maxWidth) return true;
}
return false;
}
public static bool CheckDataShow(Serie serie, string legendName, bool show)
{
bool needShow = false;
if (legendName.Equals(serie.serieName))
{
serie.show = show;
serie.highlight = false;
if (serie.show) needShow = true;
}
else
{
foreach (var data in serie.data)
{
if (legendName.Equals(data.name))
{
data.show = show;
data.context.highlight = false;
if (data.show) needShow = true;
}
}
}
return needShow;
}
public static bool CheckDataHighlighted(Serie serie, string legendName, bool heighlight)
{
bool show = false;
if (legendName.Equals(serie.serieName))
{
serie.highlight = heighlight;
}
else
{
foreach (var data in serie.data)
{
if (legendName.Equals(data.name))
{
data.context.highlight = heighlight;
if (data.context.highlight) show = true;
}
}
}
return show;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc1c14527667e4475a275768371b3b9a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: