UnityUI中繪制線狀統(tǒng)計(jì)圖
先來個(gè)效果圖

覺得不好看可以自己調(diào)整
1.繪制數(shù)據(jù)點(diǎn)
線狀圖一般由數(shù)據(jù)點(diǎn)和連線組成
在繪制連線之前,我們先標(biāo)出數(shù)據(jù)點(diǎn)
這里我選擇用Image圖片來繪制數(shù)據(jù)點(diǎn)
新建Canvas,添加空物體Graph
在Graph上添加空物體 GraphContainer 和 Image BackGround
在 GraphContainer 上添加 Image BackGround

修改兩個(gè)BackGround的大小和顏色制作背景

注意:這里GraphContainer 錨點(diǎn)為左下角
左下角默認(rèn)為原點(diǎn)(0,0),之后所有的圖形繪制都會在GraphContainer之內(nèi)


在Graph上新建腳本MyGraph
public class MyGraph : MonoBehaviour
{
[SerializeField]
private Sprite circleSprite; //需要畫的圖像,這里賦值為了一個(gè)Unity自帶的圓形,也可改為其它圖形
private RectTransform graphContainer; //聲明一個(gè) 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)); //生成新物體,該物體包含一個(gè)圖片組件
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è)為公共變量來修改
//下面兩句將生成圖片的錨點(diǎn)設(shè)為了父物體左下角(原點(diǎn))
rectTransform.anchorMin = new Vector2(0, 0);
rectTransform.anchorMax = new Vector2(0, 0);
}
}
運(yùn)行后便會出現(xiàn)一個(gè)點(diǎn)

2.根據(jù)List列表輸入繪制出多個(gè)圓點(diǎn)
繼續(xù)修改MyGraph
public class MyGraph : MonoBehaviour
{
//[SerializeField]
//private Sprite circleSprite;
//private RectTransform graphContainer;
private void Awake()
{
//graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>();
//聲明一個(gè)列表用于測試
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ù)點(diǎn)x坐標(biāo)的間距
float ySpace = graphHeight / maxValue; //數(shù)據(jù)的y坐標(biāo)的比例
for (int i = 0; i < valueList.Count; i++)
{
float xPos = i * xSpace; //x坐標(biāo)為線性固定增長
float yPos = ySpace * valueList[i]; //y坐標(biāo)是以列表中最大值為畫布高度,按值的大小與最大值的比例取高度
CreateCircle(new Vector2(xPos, yPos)); //畫出點(diǎn)
}
}
}
運(yùn)行顯示結(jié)果

為了好看點(diǎn),可以將內(nèi)側(cè)灰色的背景放大點(diǎn)

所有點(diǎn)都在 GraphContainer 之內(nèi),點(diǎn)在x坐標(biāo)平均分布,最高點(diǎn)為列表中的最大值

3.繪制點(diǎn)之間的連線
這里點(diǎn)之間的連線我仍然使用Image,只要Image足夠細(xì)就能夠看作線條
之后我會嘗試能否使用LineRenderer
這里畫線的想法是在兩點(diǎn)中點(diǎn)創(chuàng)建一個(gè)線條狀的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; //用于保存上一個(gè)點(diǎn),畫出上一個(gè)點(diǎn)到現(xiàn)在點(diǎn)的連線,這樣就不用管最后一個(gè)點(diǎ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)建的點(diǎn)
if (lastPoint != null)
{
//畫線,參數(shù)為上一個(gè)點(diǎn)的位置,和當(dāng)前點(diǎn)的位置
DrawLine(lastPoint.GetComponent<RectTransform>().anchoredPosition, circleGameobject.GetComponent<RectTransform>().anchoredPosition);
}
lastPoint = circleGameobject; //畫完連線之后,變?yōu)樯弦粋€(gè)點(diǎn)
}
}
private void DrawLine(Vector2 pointA, Vector2 pointB) //畫線方法
{
GameObject gameObject = new GameObject("line", typeof(Image));//新建一個(gè)物體包含一個(gè)Image組件
gameObject.transform.SetParent(graphContainer, false); //將該圖片設(shè)為graphContainer的子物體
//就是在畫板內(nèi)畫線
RectTransform rectTransform = gameObject.GetComponent<RectTransform>(); //獲取 RectTransform 組件
Vector2 dir = pointB - pointA; //兩點(diǎn)間的向量
//同樣將線段錨點(diǎn)設(shè)為畫板左下角(原點(diǎn))
rectTransform.anchorMin = new Vector2(0, 0);
rectTransform.anchorMax = new Vector2(0, 0);
rectTransform.sizeDelta = new Vector2(dir.magnitude, 3f); //線段的長寬,長為兩點(diǎn)間向量的長度,就是兩點(diǎn)間距離
rectTransform.anchoredPosition = pointA + dir / 2; //線段的中心點(diǎn),為兩點(diǎn)間的中心點(diǎn)
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ù),如果右邊的點(diǎn)更矮則是負(fù)數(shù),可以直接用于旋轉(zhuǎn)
運(yùn)行后顯示效果:

實(shí)際自己需要輸入的數(shù)據(jù)列表建議自己進(jìn)行修改
線狀圖2.0會加上坐標(biāo)軸
到此這篇關(guān)于UnityUI中繪制線狀統(tǒng)計(jì)圖的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 利用Unity制作特寫鏡頭的示例代碼
- Unity通過腳本創(chuàng)建網(wǎng)格Mesh的方法
- 解決Unity無限滾動復(fù)用列表的問題
- Unity為軟件添加使用有效期的具體步驟
- Unity利用XML制作一個(gè)簡易的登錄系統(tǒng)
- Unity游戲開發(fā)之炸彈人游戲的實(shí)現(xiàn)
- Unity游戲開發(fā)之射擊小游戲的實(shí)現(xiàn)
- 基于Unity制作一個(gè)簡易的計(jì)算器
- Unity3D實(shí)戰(zhàn)之答題系統(tǒng)的實(shí)現(xiàn)
- 基于Unity3D實(shí)現(xiàn)3D照片墻效果
- C#使用Unity實(shí)現(xiàn)IOC
相關(guān)文章
WinForm實(shí)現(xiàn)頁面按鈕定時(shí)隱藏功能
這篇文章主要介紹了WinForm實(shí)現(xiàn)頁面按鈕定時(shí)隱藏功能,結(jié)合實(shí)例形式分析了WinForm基于定時(shí)器的頁面控件屬性動態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-05-05
C# 時(shí)間與時(shí)間戳互轉(zhuǎn)的方法(13位)
這篇文章主要介紹了C# 時(shí)間與時(shí)間戳互轉(zhuǎn)的方法(13位),詳細(xì)的介紹了常出現(xiàn)的幾種時(shí)間方式及其時(shí)間與時(shí)間戳互轉(zhuǎn)的方法,非常具有實(shí)用價(jià)值,希望此文章對各位有所幫助2018-10-10
C#并發(fā)實(shí)戰(zhàn)記錄之Parallel.ForEach使用
這篇文章主要給大家介紹了關(guān)于C#并發(fā)實(shí)戰(zhàn)記錄之Parallel.ForEach使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08
C#利用FluentFTP實(shí)現(xiàn)FTP上傳下載功能詳解
FTP作為日常工作學(xué)習(xí)中,非常重要的一個(gè)文件傳輸存儲空間,想必大家都非常的熟悉了,那么如何快速的實(shí)現(xiàn)文件的上傳下載功能呢,本文以一個(gè)簡單的小例子,簡述如何通過FluentFTP實(shí)現(xiàn)文件的上傳和下載功能2023-02-02
c#擴(kuò)展datatable轉(zhuǎn)json示例
這篇文章主要介紹了c#擴(kuò)展datatable轉(zhuǎn)json示例,需要的朋友可以參考下2014-05-05
C#連接mysql數(shù)據(jù)庫完整實(shí)例
這篇文章主要介紹了C#連接mysql數(shù)據(jù)庫的方法,以一個(gè)完整實(shí)例形式分析了C#操作mysql數(shù)據(jù)庫連接的基本技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-05-05

