支持多数据密集图表

This commit is contained in:
monitor1394
2019-04-02 00:24:57 +08:00
parent 3a48b06d34
commit 0b515a9afc
12 changed files with 5413 additions and 11143 deletions

View File

@@ -26,8 +26,8 @@ public class BarChartDemo : MonoBehaviour
rect.sizeDelta = new Vector2(wid, hig);
xchart.GetComponent<RectTransform>().sizeDelta = new Vector2(wid, hig);
bigdataChart = xchart.Find("barchart_bigdata").GetComponent<BarChart>();
GenerateData(2000, bigdataChart);
bigdataChart = xchart.Find("barchart_multidata").GetComponent<BarChart>();
GenerateData(5000, bigdataChart);
}
void Update()
@@ -66,20 +66,20 @@ public class BarChartDemo : MonoBehaviour
for (var i = 0; i < count; i++)
{
chart.AddXAxisCategory(time.ToString("yyyy-MM-dd hh:mm:ss"));
chart.XAxis.AddMultiData(time.ToString("hh:mm:ss"));
smallBaseValue = i % 30 == 0
? UnityEngine.Random.Range(0, 700)
: (smallBaseValue + UnityEngine.Random.Range(0, 500) - 250);
baseValue += UnityEngine.Random.Range(0, 20) - 10;
//float value = Mathf.Max(
// 0,
// Mathf.Round(baseValue + smallBaseValue) + 3000
//);
var index = i % 100;
var value = (Mathf.Sin(index / 5) * (index / 5 - 10) + index / 6) * 5;
float value = Mathf.Max(
0,
Mathf.Round(baseValue + smallBaseValue) + 3000
);
//var index = i % 100;
//var value = (Mathf.Sin(index / 5) * (index / 5 - 10) + index / 6) * 5;
value = Mathf.Abs(value);
chart.AddData(0, value);
chart.AddMultiData(0, value);
time = time.AddSeconds(1);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -51,13 +51,13 @@ namespace xcharts
Series series = seriesList[j];
Color color = themeInfo.GetColor(j);
int startIndex = 0;
if (series.showDataNumber > 0 && series.dataList.Count > series.showDataNumber)
if (series.showDataNumber > 0 && series.DataList.Count > series.showDataNumber)
{
startIndex = series.dataList.Count - series.showDataNumber;
startIndex = series.DataList.Count - series.showDataNumber;
}
for (int i = startIndex; i < series.dataList.Count; i++)
for (int i = startIndex; i < series.DataList.Count; i++)
{
float data = series.dataList[i];
float data = series.DataList[i];
float pX = zeroX + coordinate.tickness;
float pY = zeroY + i * scaleWid;
if (!yAxis.boundaryGap) pY -= scaleWid / 2;
@@ -80,12 +80,13 @@ namespace xcharts
float max = GetMaxValue();
if (tooltip.show && tooltip.DataIndex > 0)
{
float tooltipSplitWid = scaleWid < 1 ? 1 : scaleWid;
float pX = zeroX + scaleWid * (tooltip.DataIndex - 1);
float pY = zeroY + coordinateHig;
Vector3 p1 = new Vector3(pX, zeroY);
Vector3 p2 = new Vector3(pX, pY);
Vector3 p3 = new Vector3(pX + scaleWid, pY);
Vector3 p4 = new Vector3(pX + scaleWid, zeroY);
Vector3 p3 = new Vector3(pX + tooltipSplitWid, pY);
Vector3 p4 = new Vector3(pX + tooltipSplitWid, zeroY);
ChartUtils.DrawPolygon(vh, p1, p2, p3, p4, themeInfo.tooltipFlagAreaColor);
}
for (int j = 0; j < seriesCount; j++)
@@ -94,13 +95,13 @@ namespace xcharts
Series series = seriesList[j];
Color color = themeInfo.GetColor(j);
int startIndex = 0;
if (series.showDataNumber > 0 && series.dataList.Count > series.showDataNumber)
if (series.showDataNumber > 0 && series.DataList.Count > series.showDataNumber)
{
startIndex = series.dataList.Count - series.showDataNumber;
startIndex = series.DataList.Count - series.showDataNumber;
}
for (int i = startIndex; i < series.dataList.Count; i++)
for (int i = startIndex; i < series.DataList.Count; i++)
{
float data = series.dataList[i];
float data = series.DataList[i];
float pX = zeroX + i * scaleWid;
if (!xAxis.boundaryGap) pX -= scaleWid / 2;
float pY = zeroY + coordinate.tickness;

View File

@@ -44,7 +44,18 @@ namespace xcharts
public bool showSplitLine = true;
public SplitLineType splitLineType = SplitLineType.dashed;
public bool boundaryGap = true;
public List<string> data;
[SerializeField]
private List<string> data;
private List<string> multidata = new List<string>();
private List<string> Data
{
get
{
if (multidata.Count > 0) return multidata;
else return data;
}
}
public void AddData(string category)
{
@@ -55,26 +66,26 @@ namespace xcharts
data.Add(category);
}
public string GetData(int index,float maxData = 0)
public void AddMultiData(string category)
{
if(type == AxisType.value)
if (multidata.Count >= maxSplitNumber && maxSplitNumber != 0)
{
return ((int)(maxData * index / GetSplitNumber())).ToString();
multidata.RemoveAt(0);
}
int dataCount = data.Count;
if (dataCount <= 0) return "";
float rate = dataCount / GetScaleNumber();
if (rate < 1) rate = 1;
int newIndex = (int)(index * rate >= dataCount - 1 ? dataCount - 1 : index * rate);
return data[newIndex];
multidata.Add(category);
}
public string GetData(int index)
{
return Data[index];
}
public int GetSplitNumber()
{
if (data.Count > 2 * splitNumber || data.Count <= 0)
if (Data.Count > 2 * splitNumber || Data.Count <= 0)
return splitNumber;
else
return data.Count;
return Data.Count;
}
public float GetSplitWidth(float coordinateWidth)
@@ -84,20 +95,34 @@ namespace xcharts
public int GetDataNumber()
{
return data.Count;
return Data.Count;
}
public float GetDataWidth(float coordinateWidth)
{
return coordinateWidth / (boundaryGap ? data.Count : data.Count - 1);
return coordinateWidth / (boundaryGap ? Data.Count : Data.Count - 1);
}
public string GetScaleName(int index, float maxData = 0)
{
if (type == AxisType.value)
{
return ((int)(maxData * index / GetSplitNumber())).ToString();
}
int dataCount = Data.Count;
if (dataCount <= 0) return "";
float rate = dataCount / GetScaleNumber();
if (rate < 1) rate = 1;
int newIndex = (int)(index * rate >= dataCount - 1 ? dataCount - 1 : index * rate);
return Data[newIndex];
}
public int GetScaleNumber()
{
if (data.Count > 2 * splitNumber || data.Count <= 0)
if (Data.Count > 2 * splitNumber || Data.Count <= 0)
return boundaryGap ? splitNumber + 1 : splitNumber;
else
return boundaryGap ? data.Count + 1 : data.Count;
return boundaryGap ? Data.Count + 1 : Data.Count;
}
public float GetScaleWidth(float coordinateWidth)
@@ -148,6 +173,9 @@ namespace xcharts
protected float coordinateWid { get { return chartWid - coordinate.left - coordinate.right; } }
protected float coordinateHig { get { return chartHig - coordinate.top - coordinate.bottom; } }
public Axis XAxis { get { return xAxis; } }
public Axis YAxis { get { return yAxis; } }
protected override void Awake()
{
base.Awake();
@@ -251,10 +279,6 @@ namespace xcharts
base.RefreshTooltip();
int index = tooltip.DataIndex - 1;
Axis tempAxis = xAxis.type == AxisType.value ? (Axis)yAxis : (Axis)xAxis;
if (index > tempAxis.data.Count - 1)
{
index = tempAxis.data.Count - 1;
}
if (index < 0)
{
tooltip.SetActive(false);
@@ -263,17 +287,17 @@ namespace xcharts
tooltip.SetActive(true);
if (seriesList.Count == 1)
{
string txt = tempAxis.GetData(index) + ": " + seriesList[0].dataList[index];
string txt = tempAxis.GetData(index) + ": " + seriesList[0].DataList[index];
tooltip.UpdateTooltipText(txt);
}
else
{
StringBuilder sb = new StringBuilder(tempAxis.data[index]);
StringBuilder sb = new StringBuilder(tempAxis.GetData(index));
for (int i = 0; i < seriesList.Count; i++)
{
string strColor = ColorUtility.ToHtmlStringRGBA(themeInfo.GetColor(i));
string key = seriesList[i].name;
float value = seriesList[i].dataList[index];
float value = seriesList[i].DataList[index];
sb.Append("\n");
sb.AppendFormat("<color=#{0}>● </color>", strColor);
sb.AppendFormat("{0}: {1}", key, value);
@@ -347,7 +371,7 @@ namespace xcharts
new Vector2(1, 0.5f),
new Vector2(coordinate.left, 20));
txt.transform.localPosition = GetYScalePosition(scaleWid, i);
txt.text = yAxis.GetData(i, max);
txt.text = yAxis.GetScaleName(i, max);
txt.gameObject.SetActive(coordinate.show);
yScaleTextList.Add(txt);
}
@@ -366,7 +390,7 @@ namespace xcharts
new Vector2(scaleWid, 20));
txt.transform.localPosition = GetXScalePosition(scaleWid, i);
txt.text = xAxis.GetData(i, max);
txt.text = xAxis.GetScaleName(i, max);
txt.gameObject.SetActive(coordinate.show);
xScaleTextList.Add(txt);
}

View File

@@ -16,6 +16,7 @@ namespace xcharts
{
public bool show = true;
public string text = "Chart Title";
public string subText = "";
public Align align = Align.center;
public float left;
public float right;
@@ -171,14 +172,21 @@ namespace xcharts
{
public string name;
public int showDataNumber = 0;
public List<float> dataList = new List<float>();
[SerializeField]
private List<float> dataList = new List<float>();
private List<float> multiDataList = new List<float>();
public List<float> DataList
{
get { return multiDataList.Count > 0 ? multiDataList : dataList; }
}
public float Max
{
get
{
float max = 0;
foreach (var data in dataList)
foreach (var data in DataList)
{
if (data > max)
{
@@ -194,7 +202,7 @@ namespace xcharts
get
{
float total = 0;
foreach (var data in dataList)
foreach (var data in DataList)
{
total += data;
}
@@ -211,27 +219,45 @@ namespace xcharts
dataList.Add(value);
}
public void AddMultiData(float value)
{
if (multiDataList.Count >= showDataNumber && showDataNumber != 0)
{
multiDataList.RemoveAt(0);
}
multiDataList.Add(value);
}
public float GetData(int index)
{
if (index >= 0 && index <= dataList.Count - 1)
if (index >= 0 && index <= DataList.Count - 1)
{
return dataList[index];
return DataList[index];
}
return 0;
}
public void UpdataData(int index, float value)
public void UpdateData(int index, float value)
{
if (index >= 0 && index <= dataList.Count - 1)
{
dataList[index] = value;
}
}
public void UpdateMultiData(int index, float value)
{
if (index >= 0 && index <= multiDataList.Count - 1)
{
multiDataList[index] = value;
}
}
}
public class BaseChart : MaskableGraphic
{
private const string TILTE_TEXT = "title";
private const string SUB_TILTE_TEXT = "sub_title";
private const string LEGEND_TEXT = "legend";
[SerializeField]
protected Theme theme = Theme.Dark;
@@ -252,7 +278,6 @@ namespace xcharts
private float checkWid = 0;
private float checkHig = 0;
protected Text titleText;
protected List<Text> legendTextList = new List<Text>();
protected float chartWid { get { return rectTransform.sizeDelta.x; } }
protected float chartHig { get { return rectTransform.sizeDelta.y; } }
@@ -301,18 +326,36 @@ namespace xcharts
RefreshChart();
}
public void AddMultiData(string legend, float value)
{
for (int i = 0; i < seriesList.Count; i++)
{
if (seriesList[i].name.Equals(legend))
{
seriesList[i].AddMultiData(value);
break;
}
}
RefreshChart();
}
public void AddData(int legend,float value)
{
seriesList[legend].AddData(value);
}
public void AddMultiData(int legend, float value)
{
seriesList[legend].AddMultiData(value);
}
public void UpdateData(string legend, float value, int dataIndex = 0)
{
for (int i = 0; i < seriesList.Count; i++)
{
if (seriesList[i].name.Equals(legend))
{
seriesList[i].UpdataData(dataIndex, value);
seriesList[i].UpdateData(dataIndex, value);
break;
}
}
@@ -325,7 +368,33 @@ namespace xcharts
{
if (i == legendIndex)
{
seriesList[i].UpdataData(dataIndex, value);
seriesList[i].UpdateData(dataIndex, value);
break;
}
}
RefreshChart();
}
public void UpdateMultiData(string legend, float value, int dataIndex = 0)
{
for (int i = 0; i < seriesList.Count; i++)
{
if (seriesList[i].name.Equals(legend))
{
seriesList[i].UpdateMultiData(dataIndex, value);
break;
}
}
RefreshChart();
}
public void UpdateMultiData(int legendIndex, float value, int dataIndex = 0)
{
for (int i = 0; i < seriesList.Count; i++)
{
if (i == legendIndex)
{
seriesList[i].UpdateMultiData(dataIndex, value);
break;
}
}
@@ -384,13 +453,21 @@ namespace xcharts
titlePosition = new Vector3(0, -title.top, 0);
break;
}
titleText = ChartUtils.AddTextObject(TILTE_TEXT, transform, themeInfo.font,
Text 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);
titleText.transform.localPosition = titlePosition;
titleText.text = title.text;
Text subText = ChartUtils.AddTextObject(SUB_TILTE_TEXT, transform, themeInfo.font,
themeInfo.textColor, anchor, anchorMin, anchorMax, new Vector2(0, 1),
new Vector2(titleWid, titleHig), 14);
subText.alignment = anchor;
subText.gameObject.SetActive(title.show && !string.IsNullOrEmpty(title.subText));
subText.transform.localPosition = titlePosition - new Vector3(0,15,0);
subText.text = title.subText;
}
private void InitLegend()

View File

@@ -54,13 +54,13 @@ namespace xcharts
float startX = zeroX + (xAxis.boundaryGap ? scaleWid / 2 : 0);
int showDataNumber = series.showDataNumber;
int startIndex = 0;
if (series.showDataNumber > 0 && series.dataList.Count > series.showDataNumber)
if (series.showDataNumber > 0 && series.DataList.Count > series.showDataNumber)
{
startIndex = series.dataList.Count - series.showDataNumber;
startIndex = series.DataList.Count - series.showDataNumber;
}
for (int i = startIndex; i < series.dataList.Count; i++)
for (int i = startIndex; i < series.DataList.Count; i++)
{
float value = series.dataList[i];
float value = series.DataList[i];
np = new Vector3(startX + i * scaleWid, zeroY + value * coordinateHig / max);
if (i > 0)
@@ -93,9 +93,9 @@ namespace xcharts
// draw point
if (lineInfo.showPoint)
{
for (int i = 0; i < series.dataList.Count; i++)
for (int i = 0; i < series.DataList.Count; i++)
{
float value = series.dataList[i];
float value = series.DataList[i];
Vector3 p = new Vector3(startX + i * scaleWid,
zeroY + value * coordinateHig / max);

View File

@@ -57,7 +57,7 @@ namespace xcharts
angleList.Add(0);
continue;
}
float value = seriesList[i].dataList[0];
float value = seriesList[i].DataList[0];
float degree = totalDegree * value / dataTotal;
float toDegree = startDegree + degree;
@@ -194,7 +194,7 @@ namespace xcharts
tooltip.SetActive(true);
string strColor = ColorUtility.ToHtmlStringRGBA(themeInfo.GetColor(index));
string key = legend.dataList[index];
float value = seriesList[index].dataList[0];
float value = seriesList[index].DataList[0];
string txt = "";
if (!string.IsNullOrEmpty(pieInfo.name))
{

View File

@@ -193,7 +193,7 @@ namespace xcharts
dataPosList.Add(new List<Vector3>());
continue;
}
var dataList = seriesList[i].dataList;
var dataList = seriesList[i].DataList;
var color = themeInfo.GetColor(i);
var areaColor = new Color(color.r, color.g, color.b, color.a * 0.7f);
var max = radarInfo.indicatorList[i].max > 0 ?
@@ -369,7 +369,7 @@ namespace xcharts
for (int i = 0; i < radarInfo.indicatorList.Count; i++)
{
string key = radarInfo.indicatorList[i].name;
float value = seriesList[index].dataList[i];
float value = seriesList[index].DataList[i];
sb.Append("\n");
sb.AppendFormat("{0}: {1}", key, value);
}

BIN
Doc/multidata.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -2,14 +2,16 @@
A Simple UGUI Charting Library for Unity
# 特性
1. 支持折线图(`LineChart`)、柱状图(`BarChart`)、饼图(`PieChart`)、雷达图(`RadarChart`)等
1. 支持折线图(`LineChart`)、柱状图(`BarChart`)、饼图(`PieChart`)、雷达图(`RadarChart`)等常用图表
2. 支持`Default``Light``Dark`三种主题切换
3. 参数可视化配置,效果实时预览
3. 参数可视化配置,效果实时预览,纯源码绘制
4. 折线图通过参数可配置出:折线图、曲线图、区域图等
5. 饼图通过参数可配置出:饼图、环形图、南丁格尔玫瑰图等
6. 支持多数据密集图表
# TODO
1. ~~`tooltip`~~2019.3.21完成)
2. ~~多数据支持~~2019.4.1完成)
2. 旭日图`sunburst`
3. 动画效果
@@ -20,7 +22,8 @@ A Simple UGUI Charting Library for Unity
![Light](Doc/light.png)
3.`Dark`主题
![Dark](Doc/dark.png)
4.多数据支持
![Multidata](Doc/multidata.png)
# 配置项手册
* `Theme` 主题
+ `theme`:主题,`Default``Light``Dark`三种可选主题