diff --git a/Scripts/BarChart.cs b/Scripts/BarChart.cs index 27a5b4a6..113f6066 100644 --- a/Scripts/BarChart.cs +++ b/Scripts/BarChart.cs @@ -13,7 +13,7 @@ namespace xcharts public class BarChart : BaseAxesChart { [SerializeField] - private BarInfo barInfo; + private BarInfo barInfo = new BarInfo(); protected override void Awake() { @@ -40,7 +40,7 @@ namespace xcharts { if (!legend.IsShowSeries(j)) continue; Series series = seriesList[j]; - Color color = legend.GetColor(j); + Color color = themeInfo.GetColor(j); int startIndex = 0; if (series.showDataNumber > 0 && series.dataList.Count > series.showDataNumber) { @@ -73,7 +73,7 @@ namespace xcharts { if (!legend.IsShowSeries(j)) continue; Series series = seriesList[j]; - Color color = legend.GetColor(j); + Color color = themeInfo.GetColor(j); int startIndex = 0; if (series.showDataNumber > 0 && series.dataList.Count > series.showDataNumber) { diff --git a/Scripts/BaseAxesChart.cs b/Scripts/BaseAxesChart.cs index fc42a8fd..aadcd185 100644 --- a/Scripts/BaseAxesChart.cs +++ b/Scripts/BaseAxesChart.cs @@ -11,10 +11,10 @@ namespace xcharts { public bool show = true; public float left = 40f; - public float right = 10f; - public float top = 10; - public float bottom = 20f; - public float tickness = 0.8f; + public float right = 30f; + public float top = 40; + public float bottom = 25f; + public float tickness = 0.6f; public float scaleLen = 5.0f; } @@ -27,13 +27,21 @@ namespace xcharts log } + public enum SplitLineType + { + solid, + dashed, + dotted + } + [System.Serializable] public class Axis { public AxisType type; public int splitNumber = 5; public int maxSplitNumber = 5; - public bool showSplitLine; + public bool showSplitLine = true; + public SplitLineType splitLineType = SplitLineType.dashed; public bool boundaryGap = true; public List data; @@ -64,11 +72,11 @@ namespace xcharts private const string XSCALE_TEXT_PREFIX = "xScale"; [SerializeField] - protected Coordinate coordinate; + protected Coordinate coordinate = new Coordinate(); [SerializeField] - protected XAxis xAxis; + protected XAxis xAxis = new XAxis(); [SerializeField] - protected YAxis yAxis; + protected YAxis yAxis = new YAxis(); private float lastXMaxValue; private float lastYMaxValue; @@ -112,6 +120,13 @@ namespace xcharts DrawCoordinate(vh); } + protected override void OnThemeChanged() + { + base.OnThemeChanged(); + InitXScale(); + InitYScale(); + } + public void AddXAxisCategory(string category) { xAxis.AddCategory(category); @@ -134,8 +149,9 @@ namespace xcharts yAxis.splitNumber = DEFAULT_YSACLE_NUM; for (int i = 0; i < yAxis.splitNumber; i++) { - Text txt = ChartUtils.AddTextObject(YSCALE_TEXT_PREFIX + i, transform, font, - TextAnchor.MiddleRight, Vector2.zero, Vector2.zero, new Vector2(1, 0.5f), + Text txt = ChartUtils.AddTextObject(YSCALE_TEXT_PREFIX + i, transform, themeInfo.font, + themeInfo.textColor, TextAnchor.MiddleRight, Vector2.zero, Vector2.zero, + new Vector2(1, 0.5f), new Vector2(coordinate.left, 20)); txt.transform.localPosition = GetYScalePosition(i); txt.text = ((int)(max * i / yAxis.splitNumber)).ToString(); @@ -148,8 +164,9 @@ namespace xcharts yAxis.splitNumber = yAxis.boundaryGap ? yAxis.data.Count + 1 : yAxis.data.Count; for (int i = 0; i < yAxis.data.Count; i++) { - Text txt = ChartUtils.AddTextObject(YSCALE_TEXT_PREFIX + i, transform, font, - TextAnchor.MiddleRight, Vector2.zero, Vector2.zero, new Vector2(1, 0.5f), + Text txt = ChartUtils.AddTextObject(YSCALE_TEXT_PREFIX + i, transform, themeInfo.font, + themeInfo.textColor, TextAnchor.MiddleRight, Vector2.zero, Vector2.zero, + new Vector2(1, 0.5f), new Vector2(coordinate.left, 20)); txt.transform.localPosition = GetYScalePosition(i); txt.text = yAxis.data[i]; @@ -170,8 +187,9 @@ namespace xcharts float scaleWid = coordinateWid / (xAxis.splitNumber - 1); for (int i = 0; i < xAxis.splitNumber; i++) { - Text txt = ChartUtils.AddTextObject(XSCALE_TEXT_PREFIX + i, transform, font, - TextAnchor.MiddleCenter, Vector2.zero, Vector2.zero, new Vector2(1, 0.5f), + Text txt = ChartUtils.AddTextObject(XSCALE_TEXT_PREFIX + i, transform, themeInfo.font, + themeInfo.textColor, TextAnchor.MiddleCenter, Vector2.zero, Vector2.zero, + new Vector2(1, 0.5f), new Vector2(scaleWid, 20)); txt.transform.localPosition = GetXScalePosition(i); txt.text = ((int)(max * i / xAxis.splitNumber)).ToString(); @@ -185,8 +203,9 @@ namespace xcharts float scaleWid = coordinateWid / (xAxis.data.Count - 1); for (int i = 0; i < xAxis.data.Count; i++) { - Text txt = ChartUtils.AddTextObject(XSCALE_TEXT_PREFIX + i, transform, font, - TextAnchor.MiddleCenter, Vector2.zero, Vector2.zero, new Vector2(1, 0.5f), + Text txt = ChartUtils.AddTextObject(XSCALE_TEXT_PREFIX + i, transform, themeInfo.font, + themeInfo.textColor, TextAnchor.MiddleCenter, Vector2.zero, Vector2.zero, + new Vector2(1, 0.5f), new Vector2(scaleWid, 20)); txt.transform.localPosition = GetXScalePosition(i); txt.text = xAxis.data[i]; @@ -364,7 +383,7 @@ namespace xcharts private void DrawCoordinate(VertexHelper vh) { if (!coordinate.show) return; - // draw scale + // draw splitline for (int i = 1; i < yAxis.splitNumber; i++) { float pX = zeroX - coordinate.scaleLen; @@ -373,8 +392,8 @@ namespace xcharts Color.white); if (yAxis.showSplitLine) { - ChartUtils.DrawLine(vh, new Vector3(zeroX, pY), - new Vector3(zeroX + coordinateWid, pY), coordinate.tickness, Color.grey); + DrawSplitLine(vh, true,yAxis.splitLineType, new Vector3(zeroX, pY), + new Vector3(zeroX + coordinateWid, pY)); } } for (int i = 1; i < xAxis.splitNumber; i++) @@ -385,15 +404,52 @@ namespace xcharts Color.white); if (xAxis.showSplitLine) { - ChartUtils.DrawLine(vh, new Vector3(pX, zeroY), new Vector3(pX, zeroY + coordinateHig), - coordinate.tickness, Color.grey); + DrawSplitLine(vh, false,xAxis.splitLineType, new Vector3(pX, zeroY), + new Vector3(pX, zeroY + coordinateHig)); } } //draw x,y axis ChartUtils.DrawLine(vh, new Vector3(zeroX, zeroY - coordinate.scaleLen), - new Vector3(zeroX, zeroY + coordinateHig + 2), coordinate.tickness, Color.white); + new Vector3(zeroX, zeroY + coordinateHig + 2), coordinate.tickness, themeInfo.axisLineColor); ChartUtils.DrawLine(vh, new Vector3(zeroX - coordinate.scaleLen, zeroY), - new Vector3(zeroX + coordinateWid + 2, zeroY), coordinate.tickness, Color.white); + new Vector3(zeroX + coordinateWid + 2, zeroY), coordinate.tickness, themeInfo.axisLineColor); + } + + private void DrawSplitLine(VertexHelper vh,bool isYAxis,SplitLineType type,Vector3 startPos,Vector3 endPos) + { + switch (type) + { + case SplitLineType.dashed: + case SplitLineType.dotted: + var startX = startPos.x; + var startY = startPos.y; + var dashLen = type == SplitLineType.dashed ? 6 : 2.5f; + var count = isYAxis ? (endPos.x - startPos.x) / (dashLen * 2): + (endPos.y - startPos.y) / (dashLen * 2); + for (int i = 0; i < count; i++) + { + if (isYAxis) + { + var toX = startX + dashLen; + ChartUtils.DrawLine(vh, new Vector3(startX, startY), new Vector3(toX, startY), + coordinate.tickness, themeInfo.axisSplitLineColor); + startX += dashLen * 2; + } + else + { + var toY = startY + dashLen; + ChartUtils.DrawLine(vh, new Vector3(startX, startY), new Vector3(startX, toY), + coordinate.tickness, themeInfo.axisSplitLineColor); + startY += dashLen * 2; + } + + } + break; + case SplitLineType.solid: + ChartUtils.DrawLine(vh, startPos, endPos, coordinate.tickness, + themeInfo.axisSplitLineColor); + break; + } } } } diff --git a/Scripts/BaseChart.cs b/Scripts/BaseChart.cs index da7f8ec2..4c98cf96 100644 --- a/Scripts/BaseChart.cs +++ b/Scripts/BaseChart.cs @@ -15,12 +15,11 @@ namespace xcharts public class Title { public bool show = true; - public string text; - public Color color; - public Align align; + public string text ="Chart Title"; + public Align align = Align.center; public float left; public float right; - public float top; + public float top = 5; public float bottom; } @@ -52,7 +51,6 @@ namespace xcharts public ChartType type; public string key; public string text; - public Color color; public Button button { get; set; } } @@ -60,22 +58,16 @@ namespace xcharts public class Legend { public bool show = true; - public Location location; + public Location location = Location.right; public float dataWid = 50.0f; public float dataHig = 20.0f; - public float dataSpace; + public float dataSpace = 5; public float left; - public float right; + public float right = 5; public float top; public float bottom; public List dataList = new List(); - public Color GetColor(int seriesIndex) - { - if (seriesIndex < 0 || seriesIndex >= dataList.Count) seriesIndex = 0; - return dataList[seriesIndex].color; - } - public bool IsShowSeries(int seriesIndex) { if (seriesIndex < 0 || seriesIndex >= dataList.Count) seriesIndex = 0; @@ -147,16 +139,17 @@ namespace xcharts private const string TILTE_TEXT = "title"; private const string LEGEND_TEXT = "legend"; [SerializeField] - protected Font font; + protected Theme theme = Theme.Dark; [SerializeField] - protected Color backgroundColor = Color.black; + protected ThemeInfo themeInfo = new ThemeInfo(); [SerializeField] - protected Title title; + protected Title title = new Title(); [SerializeField] - protected Legend legend; + protected Legend legend = new Legend(); [SerializeField] protected List seriesList = new List(); - + + private Theme checkTheme = 0; private Title checkTitle = new Title(); private Legend checkLegend = new Legend(); @@ -165,9 +158,9 @@ namespace xcharts protected float chartWid { get { return rectTransform.sizeDelta.x; } } protected float chartHig { get { return rectTransform.sizeDelta.y; } } - protected override void Awake() { + themeInfo = ThemeInfo.Dark; rectTransform.anchorMax = Vector2.zero; rectTransform.anchorMin = Vector2.zero; rectTransform.pivot = Vector2.zero; @@ -177,10 +170,19 @@ namespace xcharts protected virtual void Update() { + CheckTheme(); CheckTile(); CheckLegend(); } + protected override void OnDestroy() + { + for(int i = transform.childCount - 1; i >= 0; i--) + { + DestroyImmediate(transform.GetChild(i).gameObject); + } + } + public void AddData(string legend, string key, float value) { for (int i = 0; i < seriesList.Count; i++) @@ -238,8 +240,8 @@ namespace xcharts titlePosition = new Vector3(0, -title.top, 0); break; } - titleText = ChartUtils.AddTextObject(TILTE_TEXT, transform, font, - anchor, anchorMin, anchorMax, new Vector2(0, 1), + titleText = ChartUtils.AddTextObject(TILTE_TEXT, transform, themeInfo.font, + themeInfo.textColor, anchor, anchorMin, anchorMax, new Vector2(0, 1), new Vector2(titleWid, titleHig), 16); titleText.alignment = anchor; titleText.gameObject.SetActive(title.show); @@ -252,10 +254,11 @@ namespace xcharts for (int i = 0; i < legend.dataList.Count; i++) { LegendData data = legend.dataList[i]; - Button btn = ChartUtils.AddButtonObject(LEGEND_TEXT + i, transform, font, Vector2.zero, - Vector2.zero, Vector2.zero, new Vector2(legend.dataWid, legend.dataHig)); + Button btn = ChartUtils.AddButtonObject(LEGEND_TEXT + i, transform, themeInfo.font, + themeInfo.textColor, Vector2.zero,Vector2.zero, Vector2.zero, + new Vector2(legend.dataWid, legend.dataHig)); legend.dataList[i].button = btn; - Color bcolor = data.show ? data.color : Color.grey; + Color bcolor = data.show ? themeInfo.GetColor(i) : Color.grey; btn.gameObject.SetActive(legend.show); btn.transform.localPosition = GetLegendPosition(i); btn.GetComponent().color = bcolor; @@ -263,7 +266,7 @@ namespace xcharts btn.onClick.AddListener(delegate () { data.show = !data.show; - btn.GetComponent().color = data.show ? data.color : Color.grey; + btn.GetComponent().color = data.show ? themeInfo.GetColor(i) : Color.grey; OnYMaxValueChanged(); OnLegendButtonClicked(); RefreshChart(); @@ -317,6 +320,15 @@ namespace xcharts return bigger < 10 ? bigger : bigger - bigger % 10; } + private void CheckTheme() + { + if(checkTheme != theme) + { + checkTheme = theme; + OnThemeChanged(); + } + } + private void CheckTile() { if (checkTitle.align != title.align || @@ -357,6 +369,24 @@ namespace xcharts } } + protected virtual void OnThemeChanged() + { + switch (theme) + { + case Theme.Dark: + themeInfo.Copy(ThemeInfo.Dark); + break; + case Theme.Default: + themeInfo.Copy(ThemeInfo.Default); + break; + case Theme.Light: + themeInfo.Copy(ThemeInfo.Light); + break; + } + InitTitle(); + InitLegend(); + } + protected virtual void OnTitleChanged() { InitTitle(); @@ -404,7 +434,7 @@ namespace xcharts Vector3 p2 = new Vector3(chartWid, chartHig); Vector3 p3 = new Vector3(chartWid, 0); Vector3 p4 = new Vector3(0, 0); - ChartUtils.DrawPolygon(vh, p1, p2, p3, p4, backgroundColor); + ChartUtils.DrawPolygon(vh, p1, p2, p3, p4, themeInfo.backgroundColor); } } } \ No newline at end of file diff --git a/Scripts/ChartTheme.cs b/Scripts/ChartTheme.cs new file mode 100644 index 00000000..747c1c3d --- /dev/null +++ b/Scripts/ChartTheme.cs @@ -0,0 +1,157 @@ +using UnityEngine; +using System.Collections; + +namespace xcharts +{ + [System.Serializable] + public enum Theme + { + Default = 1, + Light, + Dark + } + + [System.Serializable] + public class ThemeInfo + { + public Font font; + public Color backgroundColor; + public Color contrastColor; + public Color textColor; + public Color subTextColor; + + public Color axisLineColor; + public Color axisSplitLineColor; + + public Color[] colorPalette; + + public Color GetColor(int index) + { + if(index < 0) + { + index = 0; + } + index = index % colorPalette.Length; + return colorPalette[index]; + } + + public void Copy(ThemeInfo theme) + { + font = theme.font; + backgroundColor = theme.backgroundColor; + contrastColor = theme.contrastColor; + textColor = theme.textColor; + subTextColor = theme.subTextColor; + axisLineColor = theme.axisLineColor; + axisSplitLineColor = theme.axisSplitLineColor; + colorPalette = new Color[theme.colorPalette.Length]; + for(int i = 0; i < theme.colorPalette.Length; i++) + { + colorPalette[i] = theme.colorPalette[i]; + } + } + + public static ThemeInfo Default + { + get + { + return new ThemeInfo() + { + font = Resources.GetBuiltinResource("Arial.ttf"), + backgroundColor = new Color32(255, 255, 255, 255), + contrastColor = GetColor("#514D4D"), + textColor = GetColor("#514D4D"), + subTextColor = GetColor("#514D4D"), + axisLineColor = GetColor("#514D4D"), + axisSplitLineColor = GetColor("#AB9999"), + colorPalette = new Color[] + { + new Color32(194, 53, 49, 255), + new Color32(47, 69, 84, 255), + new Color32(97, 160, 168, 255), + new Color32(212, 130, 101, 255), + new Color32(145, 199, 174, 255), + new Color32(116, 159, 131, 255), + new Color32(202, 134, 34, 255), + new Color32(189, 162, 154, 255), + new Color32(110, 112, 116, 255), + new Color32(84, 101, 112, 255), + new Color32(196, 204, 211, 255) + } + }; + } + } + + public static ThemeInfo Light + { + get + { + return new ThemeInfo() + { + font = Resources.GetBuiltinResource("Arial.ttf"), + backgroundColor = new Color32(255, 255, 255, 255), + contrastColor = GetColor("#514D4D"), + textColor = GetColor("#514D4D"), + subTextColor = GetColor("#514D4D"), + axisLineColor = GetColor("#514D4D"), + axisSplitLineColor = GetColor("#AB9999"), + colorPalette = new Color[] + { + new Color32(55, 162, 218, 255), + new Color32(50, 197, 233, 255), + new Color32(103, 224, 227, 255), + new Color32(159, 230, 184, 255), + new Color32(255, 219, 92, 255), + new Color32(255, 159, 127, 255), + new Color32(251, 114, 147, 255), + new Color32(224, 98, 174, 255), + new Color32(230, 144, 209, 255), + new Color32(230, 188, 243, 255), + new Color32(157, 150, 245, 255), + new Color32(131, 120, 234, 255), + new Color32(150, 191, 255, 255) + } + }; + } + } + + public static ThemeInfo Dark + { + get + { + return new ThemeInfo() + { + font = Resources.GetBuiltinResource("Arial.ttf"), + backgroundColor = new Color32(34, 34, 34, 255), + contrastColor = GetColor("#eee"), + textColor = GetColor("#eee"), + subTextColor = GetColor("#eee"), + axisLineColor = GetColor("#eee"), + axisSplitLineColor = GetColor("#aaa"), + colorPalette = new Color[] + { + new Color32(221, 107, 102, 255), + new Color32(117, 154, 160, 255), + new Color32(230, 157, 135, 255), + new Color32(141, 193, 169, 255), + new Color32(234, 126, 83, 255), + new Color32(238, 221, 120, 255), + new Color32(115, 163, 115, 255), + new Color32(115, 185, 188, 255), + new Color32(114, 137, 171, 255), + new Color32(145, 202, 140, 255), + new Color32(244, 159, 66, 255) + } + }; + } + } + + public static Color GetColor(string hexColorStr) + { + Color color; + ColorUtility.TryParseHtmlString(hexColorStr,out color); + return color; + } + } +} + diff --git a/Scripts/ChartTheme.cs.meta b/Scripts/ChartTheme.cs.meta new file mode 100644 index 00000000..fb3ce576 --- /dev/null +++ b/Scripts/ChartTheme.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 6c6931b54797f3f46b892afcfb70c79d +timeCreated: 1538089241 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/ChartUtils.cs b/Scripts/ChartUtils.cs index 4141ee6a..6755487b 100644 --- a/Scripts/ChartUtils.cs +++ b/Scripts/ChartUtils.cs @@ -7,7 +7,7 @@ namespace xcharts public static class ChartUtils { private static float CRICLE_SMOOTHNESS = 1f; - public static Text AddTextObject(string name, Transform parent, Font font, TextAnchor anchor, + public static Text AddTextObject(string name, Transform parent, Font font, Color color,TextAnchor anchor, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta, int fontSize = 14) { GameObject txtObj; @@ -33,6 +33,7 @@ namespace xcharts txt.alignment = anchor; txt.horizontalOverflow = HorizontalWrapMode.Overflow; txt.verticalOverflow = VerticalWrapMode.Overflow; + txt.color = color; txtObj.GetComponent().alignment = anchor; RectTransform rect = txtObj.GetComponent(); @@ -44,7 +45,7 @@ namespace xcharts return txtObj.GetComponent(); } - public static Button AddButtonObject(string name, Transform parent, Font font, + public static Button AddButtonObject(string name, Transform parent, Font font,Color color, Vector2 anchorMin, Vector2 anchorMax, Vector2 pivot, Vector2 sizeDelta) { GameObject btnObj; @@ -63,7 +64,7 @@ namespace xcharts btnObj.AddComponent(); btnObj.AddComponent