一:雷达图的概括
是一个五边形,其中可以扩展贴图,限制Image大小和描边
首先,要了解一些UGUI底层的原理代码,因为其中包括了生成五边形的一些特定条件,它的代码路径在“Unity\Hub\Editor\2020.3.33f1c2\Editor\Data\Resources\PackageManager\BuiltInPackages\com.unity.ugui\Runtime\UI\Core”的Image文件中OnPopulateMesh的方法
使用OnPopulateMesh方法必须要继承MaskableGraphic这个类
这个方法是判断要创建的图形有多少个顶点,如果不满足对应顶点数量的话,则直接退出,代码如下:
public float[] arr;
protected override void OnPopulateMesh(VertexHelper vh)//顶点助手
{
if (arr.Length<3)
{
base.OnPopulateMesh(vh);
return;
}
}
arr数组是用来存储顶点数量的一个容器
二:创建图形的具体逻辑如下:
vh.Clear();//因为底层涉及到了集合,所以每次执行这个方法之前先把集合内数据清空
float ang = 2 * Mathf.PI / arr.Length;//弧度
vh.AddVert(Vector3.zero,color,Vector2.zero);//圆心
for (int i = 0; i < arr.Length; i++)
{
float x = Mathf.Sin(i * ang) * arr[i] ;
float y = Mathf.Cos(i * ang) * arr[i] ;
vh.AddVert(new Vector3(x, y, 0), color, Vector2.zero);
//添加绘制顺序
if (i==0)
{
vh.AddTriangle(0, arr.Length, 1);
}
else
{
vh.AddTriangle(0, i, i+1);//正常的绘制顺序
}
}
三:在创建好图形之后,可以考虑是否加入贴图;
如果考虑加入贴图,那么要考虑两点,一个是对象的2D坐标和uv坐标;
加入好贴图之后,要更改创建图形中的两条数据,一条为圆心数据,一条为贴图的uv坐标;
public Sprite activeSprite;
public override Texture mainTexture//赋值图片
{
get
{
if (activeSprite == null)
{
if (material != null && material.mainTexture != null)
{
return material.mainTexture;
}
return s_WhiteTexture;
}
return activeSprite.texture;
}
}
以上是创建好图形之后的返回Sprite精灵的方法,如果图片上存在精灵(Sprite)或者存在Material(材质球)等效果,那么进行展示,如果都不存在,直接返回初始图片
四:设置图片的限制大小,让效果更美观
vh.Clear();//因为底层涉及到了集合,所以每次执行这个方法之前先把集合内数据清空
float w = rectTransform.sizeDelta.x;
float h = rectTransform.sizeDelta.y;//贴图,获取2D坐标
float max = arr.Max();//限制雷达图长宽
float p=w<h?(w/2)/max:(h/2)/max;//比例
float ang = 2 * Mathf.PI / arr.Length;//弧度
vh.AddVert(Vector3.zero,color, new Vector2(0.5f, 0.5f));//圆心
for (int i = 0; i < arr.Length; i++)
{
float x = Mathf.Sin(i * ang) * arr[i] * p;
float y = Mathf.Cos(i * ang) * arr[i] * p;
float uvx = (x + w / 2) / w;
float uvy = (y + h / 2) / h;//uv的横纵坐标
vh.AddVert(new Vector3(x,y,0), color, new Vector2(uvx, uvy));//贴图需要改变Vector2参数
//添加绘制顺序
if (i==0)
{
vh.AddTriangle(0, arr.Length, 1);
}
else
{
vh.AddTriangle(0, i, i+1);//正常的绘制顺序
}
}
五:添加描边的效果
//描边颜色
public Color uColor = Color.red;
//描边宽度
public float m = 1;
//画描边
int next = arr.Length + 1;
for (int i = 0; i < arr.Length; i++)
{
//内顶点
//计算顶点坐标
float x0 = Mathf.Sin(i * ang) * (arr[i] * p - m);
float y0 = Mathf.Cos(i * ang) * (arr[i] * p - m);
//计算uv坐标
float uvx0 = (x0 + w / 2) / w;
float uvy0 = (y0 + h / 2) / h;
//添加顶点
vh.AddVert(new Vector3(x0, y0, 0), uColor, new Vector2(uvx0, uvy0));
//外顶点
//计算顶点坐标
float x = Mathf.Sin(i * ang) * arr[i] * p;
float y = Mathf.Cos(i * ang) * arr[i] * p;
//计算uv坐标
float uvx = (x + w / 2) / w;
float uvy = (y + h / 2) / h;
//添加顶点
vh.AddVert(new Vector3(x, y, 0), uColor, new Vector2(uvx, uvy));
//添加绘制顺序
if (i == arr.Length - 1)
{
vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, 1 + next);
vh.AddTriangle(i * 2 + next, 1 + next, next);
}
else
{
vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, (i + 1) * 2 + 1 + next);
vh.AddTriangle(i * 2 + next, (i + 1) * 2 + 1 + next, (i + 1) * 2 + next);
}
}
描边效果:计算出每个顶点和对应点(可以自定义设置)之间的宽度,增加一个颜色的效果即可