UnityUI中繪制線狀統(tǒng)計圖
先來個效果圖
覺得不好看可以自己調(diào)整
1.繪制數(shù)據(jù)點
線狀圖一般由數(shù)據(jù)點和連線組成
在繪制連線之前,我們先標出數(shù)據(jù)點
這里我選擇用Image圖片來繪制數(shù)據(jù)點
新建Canvas,添加空物體Graph
在Graph上添加空物體 GraphContainer 和 Image BackGround
在 GraphContainer 上添加 Image BackGround
修改兩個BackGround的大小和顏色制作背景
注意:這里GraphContainer 錨點為左下角
左下角默認為原點(0,0),之后所有的圖形繪制都會在GraphContainer之內(nèi)
在Graph上新建腳本MyGraph
public class MyGraph : MonoBehaviour { [SerializeField] private Sprite circleSprite; //需要畫的圖像,這里賦值為了一個Unity自帶的圓形,也可改為其它圖形 private RectTransform graphContainer; //聲明一個 RectTransform,用于修改圖片的大小 private void Awake() { //獲取graphContainer的RectTransform并賦值,為內(nèi)側(cè)的小矩形,會作為我們的畫板 graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>(); CreateCircle(new Vector2(200, 200)); //在(200,200)的地方創(chuàng)建圓,用于測試 } private void CreateCircle(Vector2 anchoredPosition) { GameObject gameObject = new GameObject("circle", typeof(Image)); //生成新物體,該物體包含一個圖片組件 gameObject.transform.SetParent(graphContainer, false); //將圖片設(shè)為graphContainer的子物體 gameObject.GetComponent<Image>().sprite = circleSprite; //將圖片賦值為Inspector中設(shè)置的圖片 //獲取新建圖片物體的RectTransform并賦值 RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); rectTransform.anchoredPosition = anchoredPosition; //設(shè)置圖片位置 rectTransform.sizeDelta = new Vector2(20, 20); //設(shè)置圖片大小,可設(shè)為公共變量來修改 //下面兩句將生成圖片的錨點設(shè)為了父物體左下角(原點) rectTransform.anchorMin = new Vector2(0, 0); rectTransform.anchorMax = new Vector2(0, 0); } }
運行后便會出現(xiàn)一個點
2.根據(jù)List列表輸入繪制出多個圓點
繼續(xù)修改MyGraph
public class MyGraph : MonoBehaviour { //[SerializeField] //private Sprite circleSprite; //private RectTransform graphContainer; private void Awake() { //graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>(); //聲明一個列表用于測試 List<int> valueList = new List<int>() { 1, 2, 4, 9, 16, 25, 36, 49, 64, 81, 100, 80, 50, 20, 10 }; ShowGraph(valueList); } private void CreateCircle(Vector2 anchoredPosition) { ...... } private void ShowGraph(List<int> valueList) { int maxValue = 0; foreach (int value in valueList) //找出列表中的最大值 { if (maxValue <= value) { maxValue = value; } } float graphWidth = graphContainer.sizeDelta.x; //獲取畫布graphContainer的寬度 float graphHeight = graphContainer.sizeDelta.y; //獲取畫布graphContainer的高度 float xSpace = graphWidth / (valueList.Count - 1); //數(shù)據(jù)點x坐標的間距 float ySpace = graphHeight / maxValue; //數(shù)據(jù)的y坐標的比例 for (int i = 0; i < valueList.Count; i++) { float xPos = i * xSpace; //x坐標為線性固定增長 float yPos = ySpace * valueList[i]; //y坐標是以列表中最大值為畫布高度,按值的大小與最大值的比例取高度 CreateCircle(new Vector2(xPos, yPos)); //畫出點 } } }
運行顯示結(jié)果
為了好看點,可以將內(nèi)側(cè)灰色的背景放大點
所有點都在 GraphContainer 之內(nèi),點在x坐標平均分布,最高點為列表中的最大值
3.繪制點之間的連線
這里點之間的連線我仍然使用Image,只要Image足夠細就能夠看作線條
之后我會嘗試能否使用LineRenderer
這里畫線的想法是在兩點中點創(chuàng)建一個線條狀的Image,然后旋轉(zhuǎn)一定角度
繼續(xù)修改MyGraph
public class MyGraph : MonoBehaviour { ...... private void ShowGraph(List<int> valueList) { ...... float xSpace = graphWidth / (valueList.Count - 1); float ySpace = graphHeight / maxValue; GameObject lastPoint = null; //用于保存上一個點,畫出上一個點到現(xiàn)在點的連線,這樣就不用管最后一個點 for (int i = 0; i < valueList.Count; i++) { //float xPos = i * xSpace; //float yPos = ySpace * valueList[i]; GameObject circleGameobject = CreateCircle(new Vector2(xPos, yPos));//獲取創(chuàng)建的點 if (lastPoint != null) { //畫線,參數(shù)為上一個點的位置,和當前點的位置 DrawLine(lastPoint.GetComponent<RectTransform>().anchoredPosition, circleGameobject.GetComponent<RectTransform>().anchoredPosition); } lastPoint = circleGameobject; //畫完連線之后,變?yōu)樯弦粋€點 } } private void DrawLine(Vector2 pointA, Vector2 pointB) //畫線方法 { GameObject gameObject = new GameObject("line", typeof(Image));//新建一個物體包含一個Image組件 gameObject.transform.SetParent(graphContainer, false); //將該圖片設(shè)為graphContainer的子物體 //就是在畫板內(nèi)畫線 RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); //獲取 RectTransform 組件 Vector2 dir = pointB - pointA; //兩點間的向量 //同樣將線段錨點設(shè)為畫板左下角(原點) rectTransform.anchorMin = new Vector2(0, 0); rectTransform.anchorMax = new Vector2(0, 0); rectTransform.sizeDelta = new Vector2(dir.magnitude, 3f); //線段的長寬,長為兩點間向量的長度,就是兩點間距離 rectTransform.anchoredPosition = pointA + dir / 2; //線段的中心點,為兩點間的中心點 float angle = RotateAngle(dir.x, dir.y); //線段的旋轉(zhuǎn)角度 rectTransform.localEulerAngles = new Vector3(0, 0, angle); //旋轉(zhuǎn)線段 } private float RotateAngle(float x, float y) //旋轉(zhuǎn)方法 { float angle = Mathf.Atan2(y, x) * 180 / 3.14f;//Atan2返回的是弧度,需要乘以180/PI得到角度,這里PI直接用了3.14 return angle; } }
在RotateAngle()
方法中Mathf.Atan2會返回角θ的弧度
圖片所示情況會返回正數(shù),如果右邊的點更矮則是負數(shù),可以直接用于旋轉(zhuǎn)
運行后顯示效果:
實際自己需要輸入的數(shù)據(jù)列表建議自己進行修改
線狀圖2.0會加上坐標軸
到此這篇關(guān)于UnityUI中繪制線狀統(tǒng)計圖的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#設(shè)計模式之Template模板方法模式實現(xiàn)ASP.NET自定義控件 密碼強度檢測功能
這篇文章主要介紹了C#設(shè)計模式之Template模板方法模式實現(xiàn)ASP.NET自定義控件 密碼強度檢測功能,簡單介紹了模板方法模式的定義、原理及檢測密碼強度的相關(guān)使用技巧,需要的朋友可以參考下2017-09-09Winform圓形環(huán)繞的Loading動畫實現(xiàn)代碼
這篇文章主要介紹了Winform圓形環(huán)繞的Loading動畫實現(xiàn)代碼,有需要的朋友可以參考一下2014-01-01C#用遞歸算法實現(xiàn):一列數(shù)的規(guī)則如下: 1、1、2、3、5、8、13、21、34,求第30位數(shù)是多少
本文主要介紹三種方法,解決面試中常見的問題,求第30位數(shù)是多少的問題,希望能給大家一個參考。2016-06-06