雷达图的定义:雷达图是以从同一点开始的轴上表示的三个或更多个定量变量的二维图表的形式显示多变量数据的图形方法
想要实现雷达图的效果的话,需要先了解一下MaskableGraphic
MaskableGraphic的意思是可屏蔽图形
MaskableGraphic继承于UI.Graphic,作用是:是在Graphic的基础上实现剪裁和遮罩功能
先通过创建Image并且把Image上的Image组件移除掉,并且创建雷达图脚本,通过重写
OnPopulateMesh方法来实现雷达图效果
public float[] rs = new float[5];
protected override void OnPopulateMesh(VertexHelper vh)
{
if (rs.Length>=3)
{
Rect rect = this.rectTransform.rect;
vh.Clear();
//获取数组中的最大值
float max = rs.Max();
float p = rect.width < rect.height ? rect.width / 2 / max : rect.height / 2 /max;
float ang = 2 * Mathf.PI / rs.Length;
vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));
for (int i = 0; i < rs.Length; i++)
{
float x = Mathf.Sin(ang * i) * rs[i] * p;
float y = Mathf.Cos(ang * i) * rs[i] * p;
float uvx = (x + rect.width / 2) / rect.width;
float uvy = (y + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x, y), color, new Vector2(uvx, uvy));
if (i == 0)
{
vh.AddTriangle(0, rs.Length, 1);
}
else
{
vh.AddTriangle(0, i, i + 1);
}
}
}
}
这里的数组rs是储存每个顶点的信息,通过这个数组里的每一个数据累计算每个角的弧度
这里的max和p这两个变量是用来计算最大值和矩形较长边的比值的
然后再循环中计算x和y坐标的时候乘以这个比值,这样可以避免绘制的超出ui范围的问题
之后还有控制随机值,因为在游戏中的数据也会改变
protected override void Awake()
{
rs = new float[5] { 200, 200, 200, 200, 200 };
if (but != null)
{
but.onClick.AddListener(() =>
{
for (int i = 0; i < 5; i++)
{
rs[i] = Random.Range(1, 200);
}
SetVerticesDirty();
});
}
}
这样就可以控制数据的随机了,效果如下:
数据如下
最后再加一些描边的效果、
public Color wcolor = Color.red;
public float ww = 30f;
//使用过的顶点数量
int next = rs.Length + 1;
//描边
for (int i = 0; i < rs.Length; i++)
{
float x0 = Mathf.Sin(i * ang) * (rs[i] * p - ww);
float y0 = Mathf.Cos(i * ang) * (rs[i] * p - ww);
float uvx0 = (x0 + rect.width / 2) / rect.width;
float uvy0 = (y0 + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x0, y0, 0), wcolor, new Vector2(uvx0, uvy0));
float x = Mathf.Sin(i * ang) * (rs[i] * p);
float y = Mathf.Cos(i * ang) * (rs[i] * p);
float uvx = (x + rect.width / 2) / rect.width;
float uvy = (y + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x, y, 0), wcolor, new Vector2(uvx, uvy));
if (i == rs.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);
}
}
全部代码如下:
public Sprite activeSprite;
public float[] rs = new float[5];
public float ww = 30f;
public Color wcolor = Color.red;
public Button but;
protected override void Awake()
{
rs = new float[5] { 200, 200, 200, 200, 200 };
if (but != null)
{
but.onClick.AddListener(() =>
{
for (int i = 0; i < 5; i++)
{
rs[i] = Random.Range(1, 200);
}
SetVerticesDirty();
});
}
}
public override Texture mainTexture
{
get
{
if (activeSprite == null)
{
if (material != null && material.mainTexture != null)
{
return material.mainTexture;
}
return s_WhiteTexture;
}
return activeSprite.texture;
}
}
protected override void OnPopulateMesh(VertexHelper vh)
{
if (rs.Length >= 3)
{
Rect rect = this.rectTransform.rect;
vh.Clear();
//获取数组中的最大值
float max = rs.Max();
float p = rect.width < rect.height ? rect.width / 2 / max : rect.height / 2 / max;
float ang = 2 * Mathf.PI / rs.Length;
vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));
for (int i = 0; i < rs.Length; i++)
{
float x = Mathf.Sin(ang * i) * rs[i] * p;
float y = Mathf.Cos(ang * i) * rs[i] * p;
float uvx = (x + rect.width / 2) / rect.width;
float uvy = (y + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x, y), color, new Vector2(uvx, uvy));
if (i == 0)
{
vh.AddTriangle(0, rs.Length, 1);
}
else
{
vh.AddTriangle(0, i, i + 1);
}
}
//使用过的顶点数量
int next = rs.Length + 1;
//描边
for (int i = 0; i < rs.Length; i++)
{
float x0 = Mathf.Sin(i * ang) * (rs[i] * p - ww);
float y0 = Mathf.Cos(i * ang) * (rs[i] * p - ww);
float uvx0 = (x0 + rect.width / 2) / rect.width;
float uvy0 = (y0 + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x0, y0, 0), wcolor, new Vector2(uvx0, uvy0));
float x = Mathf.Sin(i * ang) * (rs[i] * p);
float y = Mathf.Cos(i * ang) * (rs[i] * p);
float uvx = (x + rect.width / 2) / rect.width;
float uvy = (y + rect.height / 2) / rect.height;
vh.AddVert(new Vector3(x, y, 0), wcolor, new Vector2(uvx, uvy));
if (i == rs.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);
}
}
}
}
这样就可以做出基础的雷达图效果了