在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会加上坐标轴
2.0在这里:https://www.cnblogs.com/AlphaIcarus/p/16126504.html
2.0之后是绘制柱状统计图:https://www.cnblogs.com/AlphaIcarus/p/16128922.html
在UnityUI中绘制线状统计图的更多相关文章
- 在UnityUI中绘制线状统计图2.0
##在之前的基础上添加横纵坐标 上一期在这里:https://www.cnblogs.com/AlphaIcarus/p/16123434.html 先分别创建横纵坐标点的模板,将这两个Text放在G ...
- 使用ArcGIS API for Silverlight + Visifire绘制地图统计图
原文:使用ArcGIS API for Silverlight + Visifire绘制地图统计图 最近把很久之前做的统计图又拿出来重新做了一遍,感觉很多时候不复习,不记录就真的忘了,时间是最好的稀释 ...
- MATLAB中绘制质点轨迹动图并保存成GIF
工作需要在MATLAB中绘制质点轨迹并保存成GIF以便展示. 绘制质点轨迹动图可用comet和comet3命令,使用例子如下: t = 0:.01:2*pi;x = cos(2*t).*(cos(t) ...
- CSharpGL(6)在OpenGL中绘制UI元素
CSharpGL(6)在OpenGL中绘制UI元素 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo,更适合入 ...
- HTML5在canvas中绘制复杂形状附效果截图
HTML5在canvas中绘制复杂形状附效果截图 一.绘制复杂形状或路径 在简单的矩形不能满足需求的情况下,绘图环境提供了如下方法来绘制复杂的形状或路径. beginPath() : 开始绘制一个新路 ...
- 在Image控件中绘制文字
//Canvas 在Image控件中绘制文字 procedure TForm1.Button1Click(Sender: TObject);begin image1.Canvas.Font.Size ...
- Android中绘制圆角矩形图片及任意形状图片
圆角矩形图片在苹果的产品中很流行,相比于普通的矩形,很多人都喜欢圆角矩形的图片,因为它避开了直角的生硬,带来更好的用户体验,下面是几个设计的例子: 下面在Android中实现将普通的矩形图片绘制成圆角 ...
- MATLAB坐标系中绘制图片
MATLAB坐标系中绘制图片 方法一 使用图片坐标循环的方式,代码如下. clear,clc,close all tic; map=imbinarize(imread('map.bmp'));%map ...
- Java 在PPT中绘制图形
Microsoft PowerPoint可支持在幻灯片中插入各种类型的图形并且可设置图形填充.线条颜色.图形大小.位置等.下面将通过Java编程来演示在PPT中绘制图形的方法. 工具:Free Spi ...
随机推荐
- 构造器注入的方式给Cart属性赋值 关系1:1;1:n
1.通过Spring创建对象,现有Users和Cart实体类,关系为1:1 属性注入的方式给Users属性赋值 2.Cart和Product实体类,关系1:n 构造器注入的方式给Cart属性赋值 Ca ...
- Java基础——Math类
Math包含执行基本数字运算的方法 没有构造方法的情况下如何使用类中的成员? 看类的成员是否都是静态的,是的话可以直接通过类名调用 Mathl类的常用方法: 方法名 说明 public static ...
- Linux上搭建meterSphere
镜像下载.域名解析.时间同步请点击 阿里云开源镜像站 一.安装Docker (1)安装CentOS Docker curl -fsSL https://get.docker.com | bash -s ...
- RDMA——libibverbs 代码分析(1)
下载libibverbs最新代码,https://downloads.openfabrics.org/verbs/README.html 为1.2.0版本.后面开始逐步分析libibverbs源码. ...
- POI Excel索引是从0还是1开始??
this.workbook.getSheetAt(1).getFirstRowNum() // == 0 this.workbook.getSheetAt(1).getLastRowNum() // ...
- Integer与int的区别?
int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Integer是java为int提供的封装类.int的默认值为0,而Integer的默认值为null,即Integer可 ...
- 为什么要使用 kafka,为什么要使用消息队列?
缓冲和削峰:上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理. 解耦 ...
- request表示HttpServletRequest对象?
request表示HttpServletRequest对象.它包含了有关浏览器请求的信息,并且提供了几个用于获取cookie, header, 和session数据的有用的方法. response表示 ...
- React+Webpack+ES6 兼容低版本浏览器(IE9)解决方案
虽然过了兼容IE6的噩梦时代,IE依旧阴魂不散,因为你可能还要兼容IE9.在ES6已经普及的今天,用ES6写react已经成了标配.但是babel编译的js语法,由于某些不规范的写法,可能在IE9下不 ...
- 微信小程序wx.login()获取openid,附:前端+后端代码
微信小程序开放了微信登录的api,无论是个人还是企业申请的小程序均可使用. 首先创建一个项目,把这些代码都清空,我们自己写! 然后,开始写了!首先index.wxml,写一个button用于发起登录 ...