UnityUI中绘制线状统计图

先来个效果图


觉得不好看可以自己调整

1.绘制数据点

线状图一般由数据点和连线组成
在绘制连线之前,我们先标出数据点
这里我选择用Image图片来绘制数据点

新建Canvas,添加空物体Graph
在Graph上添加空物体 GraphContainer 和 Image BackGround
在 GraphContainer 上添加 Image BackGround

修改两个BackGround的大小和颜色制作背景

注意:这里GraphContainer 锚点为左下角
左下角默认为原点(0,0),之后所有的图形绘制都会在GraphContainer之内

在Graph上新建脚本MyGraph

public class MyGraph : MonoBehaviour
{
    [SerializeField]
    private Sprite circleSprite;	//需要画的图像,这里赋值为了一个Unity自带的圆形,也可改为其它图形

    private RectTransform graphContainer;	//声明一个 RectTransform,用于修改图片的大小

    private void Awake()
    {
        //获取graphContainer的RectTransform并赋值,为内侧的小矩形,会作为我们的画板
        graphContainer = transform.Find("GraphContainer").GetComponent<RectTransform>();
        CreateCircle(new Vector2(200, 200));	//在(200,200)的地方创建圆,用于测试
    }

    private void CreateCircle(Vector2 anchoredPosition)
    {
        GameObject gameObject = new GameObject("circle", typeof(Image));	//生成新物体,该物体包含一个图片组件
        gameObject.transform.SetParent(graphContainer, false);			//将图片设为graphContainer的子物体
        gameObject.GetComponent<Image>().sprite = circleSprite;			//将图片赋值为Inspector中设置的图片

        //获取新建图片物体的RectTransform并赋值
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();
        rectTransform.anchoredPosition = anchoredPosition;			//设置图片位置
        rectTransform.sizeDelta = new Vector2(20, 20);				//设置图片大小,可设为公共变量来修改

        //下面两句将生成图片的锚点设为了父物体左下角(原点)
        rectTransform.anchorMin = new Vector2(0, 0);
        rectTransform.anchorMax = new Vector2(0, 0);
    }
}

运行后便会出现一个点

2.根据List列表输入绘制出多个圆点

继续修改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);  //数据点x坐标的间距
        float ySpace = graphHeight / maxValue;		    //数据的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));	    //画出点
        }
    }
}

运行显示结果

为了好看点,可以将内侧灰色的背景放大点

所有点都在 GraphContainer 之内,点在x坐标平均分布,最高点为列表中的最大值

3.绘制点之间的连线

这里点之间的连线我仍然使用Image,只要Image足够细就能够看作线条
之后我会尝试能否使用LineRenderer
这里画线的想法是在两点中点创建一个线条状的Image,然后旋转一定角度

继续修改MyGraph

public class MyGraph : MonoBehaviour
{
    ......
    private void ShowGraph(List<int> valueList)
    {
        ......

        float xSpace = graphWidth / (valueList.Count - 1);
        float ySpace = graphHeight / maxValue;

        GameObject lastPoint = null;	//用于保存上一个点,画出上一个点到现在点的连线,这样就不用管最后一个点
        for (int i = 0; i < valueList.Count; i++)
        {
            //float xPos = i * xSpace;
            //float yPos = ySpace * valueList[i];

            GameObject circleGameobject = CreateCircle(new Vector2(xPos, yPos));//获取创建的点
            if (lastPoint != null)
            {
                //画线,参数为上一个点的位置,和当前点的位置
                DrawLine(lastPoint.GetComponent<RectTransform>().anchoredPosition, circleGameobject.GetComponent<RectTransform>().anchoredPosition);
            }
            lastPoint = circleGameobject;	//画完连线之后,变为上一个点
        }
    }

    private void DrawLine(Vector2 pointA, Vector2 pointB)	//画线方法
    {
        GameObject gameObject = new GameObject("line", typeof(Image));//新建一个物体包含一个Image组件
        gameObject.transform.SetParent(graphContainer, false);		 //将该图片设为graphContainer的子物体
																//就是在画板内画线
        RectTransform rectTransform = gameObject.GetComponent<RectTransform>();	//获取 RectTransform 组件
        Vector2 dir = pointB - pointA;	//两点间的向量

        //同样将线段锚点设为画板左下角(原点)
        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);				   //线段的旋转角度
        rectTransform.localEulerAngles = new Vector3(0, 0, angle);	//旋转线段
    }
    private float RotateAngle(float x, float y)	//旋转方法
    {
        float angle = Mathf.Atan2(y, x) * 180 / 3.14f;//Atan2返回的是弧度,需要乘以180/PI得到角度,这里PI直接用了3.14
        return angle;
    }
}

RotateAngle()方法中Mathf.Atan2会返回角θ的弧度

图片所示情况会返回正数,如果右边的点更矮则是负数,可以直接用于旋转

运行后显示效果:

实际自己需要输入的数据列表建议自己进行修改
线状图2.0会加上坐标轴

到此这篇关于UnityUI中绘制线状统计图的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 基于Unity制作一个简易的计算器

    目录 一.前言 二.效果图及源工程 三.实现 1.界面搭建 2.代码实现 四.后记 一.前言 Hello,又见面了,今天分享如何使用Unity制作计算器,难度中等,可以用来学习,或者当成其他项目的小组件导入. 当然,也可以导出来,发布到网页端,来做一个嵌入式工具也可以. 二.效果图及源工程 效果图: 源工程 三.实现 1.界面搭建 所有的按钮摆放到Background下面. 2.代码实现 首先找到所有的按钮,添加到事件: //结果显示 TextComputeProcess = GameObjec

  • Unity游戏开发之炸弹人游戏的实现

    目录 前言 制作思路 开始制作 第一步:游戏场景制作 第二步:墙体代码 第三步:炸弹人制作 第四步:炸弹处理 第五步:敌人制作 第六步:游戏控制器 第七步:UI控制器 前言 大家小时候肯定玩过这款游戏,炸弹人也算是经典中的经典啦~ 希望看到这篇小游戏,可以让你重拾童年跟小伙伴一起对着大屁股电视机玩游戏的美好时光! 时间在慢慢的流逝,那些陪你一起度过童年的小伙伴有多久没联系了呢~ 看完这篇炸弹人,有时间的话就找自己童年的小伙伴们聊会天吧,一起找回童年的回忆和梦想! 回归主题,炸弹人小游戏制作开始!

  • C#使用Unity实现IOC

    一.什么是IOC 学习IOC之前先来了解一个依赖导致原则(DIP),依赖导致原则是IOC的核心原理. 依赖导致:即上层模块不应该依赖于低层模块,二者应该通过抽象来依赖.依赖于抽象,而不是依赖于细节. 首先来看下面的例子: 1.定义一个接口,封装数据库的基本CRUD操作,接口定义如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threadin

  • Unity为软件添加使用有效期的具体步骤

    功能需求:为软件设定一个使用有效期,当超过指定时间后,程序无法运行. 实现思路:定义一个常量,用于记录一个时间,我们称之为标记时间,使用当前时间减去标记时间,如果时间间隔大于设定的有效期,退出程序. 具体步骤: 1.定义标记时间常量: //标记时间 private const string flag = "2022-03-17 17:11:25"; 使用DateTime.Parse可将其转换为DateTime类型: DateTime flagTime = DateTime.Parse(

  • 基于Unity3D实现3D照片墙效果

    一.前言 Unity3D不仅仅可以开发游戏,还有非常多的开发方向,秉承着兴趣为先,将可以使用Unity制作的各种应用案例,分享如何进行开发,如何实现,希望大家可以在感兴趣的地方,学习到自己想要学习的东西. 今天就来实现一个3D照片墙的效果. 我对于这个项目的构思就是照片是3D的,可以滑动,然后使用DoTween插件去做动画平滑移动. OK,那就正式开始. 先看一下效果图: 二.正式开发 新建项目,我使用的版本是Unity3D 2019.4.7f1,模板选用3D: (1)导入DoTween插件.

  • Unity3D实战之答题系统的实现

    目录 一.前言 三.实现 1.界面搭建 2.读取文档 3.加载题目 4.按钮功能 5.题目对错判断 四.后言 一.前言 这是本专栏系列的第一篇,答题系统的开发. 这个答题系统,可以从文本文档中提取题目和分数,然后绑定到UI上,在答题的过程中,自动判断分数,自动判断正确率. 目的是实现一个可快速导入到项目中使用的小模块. 二.效果图及工程下载 题目文档  密码:47z2 源工程 三.实现 1.界面搭建 首先,新建工程,然后摆UI,如下图所示: 2.读取文档 题目存放在txt文档中,首先,我们看一下

  • 解决Unity无限滚动复用列表的问题

    目录 无限滚动复用列表 前言 设计思路 关键基类 1.ScrollData 2.ScrollView 3.ScrollItem 测试类 1.添加20组数据 2.回到顶部 3.回到底部 坑点 1.ScrollView回滚设置延迟: 2.锚点设置: 3.数据需要网络请求,自适应会失效: 无限滚动复用列表 Demo展示 前言 游戏中有非常多的下拉滚动菜单,比如成就列表,任务列表,以及背包仓库之类:如果列表内容非常丰富,会占用大量内存,这篇无限滚动复用ScrollView就是解决这种问题:还可以用来做朋

  • Unity游戏开发之射击小游戏的实现

    目录 前言 游戏画面展示 游戏代码解析 游戏打包 总结 前言 人们一直都说学习和玩游戏不能兼顾,那我们就来边学习怎样制作游戏,边玩游戏 不就兼得了嘛~ 我可真是一个小天才呢~ 所以本篇文章为大家带来一个 横版2D射击小游戏,游戏制作超级简单,玩法一学就会, 一起来看看吧! 游戏画面展示 这款小游戏只用了两个UI界面,一个是菜单界面,另一个是战斗界面 菜单界面有三种模式,分别是一般.困难和地狱 战斗界面就是很简单的从两边刷野怪,然后主角开枪打死他们 UI搭建很简单,只有一张背景图使用Image,加

  • Unity利用XML制作一个简易的登录系统

    通过XML文件保存账号密码,存储到本地,不连接数据库的简易登录系统. 1.创建一个XML文件,设置一个初始的账号密码. public void Creat() { localPath = UnityEngine.Application.streamingAssetsPath + "/" + "MyXML.xml"; if (!File.Exists(localPath)) { XmlDocument xml = new XmlDocument(); XmlDecla

  • Unity通过脚本创建网格Mesh的方法

    目录 1.创建一个带Mesh的物体 2.通过脚本创建Mesh 1.创建一个带Mesh的物体 Unity中的网格作为组件不能脱离物体单独存在新建脚本CreateMesh public class CreateMesh: MonoBehaviour { void Start() { //该方法会新建一个名为Mesh的GameObject,该物体上包含一个 MeshFilter 和一个 MeshRenderer GameObject gameObject = new GameObject("Mesh&

  • 利用Unity制作特写镜头的示例代码

    目录 类似这种效果 1.首先制作上下两层黑边 2.摄像头聚焦的效果 类似这种效果 黑边的大小可以自行调整 这里为了方便直接用两个Button绑定了方法,有需要自行调用方法 1.首先制作上下两层黑边 创建Canvas然后在canvas上新建空物体,命名为CinemaCloseUpShot 在上面新建脚本CinemaCloseUP public class CinemaCloseUP : MonoBehaviour { public float targetSizeInput; //上下黑条的宽度

随机推荐