扇形图原理和折线图差不多,都是在UI的OnPopulateMesh函数下绘制的。由于做的是半径不均匀的扇形图,所以去贴图抗锯齿没有实现。大家有啥想法(怎么取uv以及边界模糊的贴图怎么画)欢迎留言。
下面是OnPopulateMesh下的代码块。
protected override void OnPopulateMesh(VertexHelper toFill)
{
toFill.Clear();
//ITEMS表示这个圆形被多少个三角形均分 数量越多 圆越精细
offset = 360 / ITEMS;
List<UIVertex> vertices = new List<UIVertex>();
radiusOffset = 0.5f / count;//count 数据个数
for (int i = 0; i < count; i++)
{
//if(i==0) continue;
float value = Values[i];
int c = (int)(value * ITEMS);
float offsetAngle = 360 * value / c;
float angle = 0;
for (int j = 0; j < i; j++)
{
angle += Values[j];
}
angle *= 360;
Vector2 originDir = Quaternion.Euler(0, 0, angle) * Vector2.up;
for (int j = 0; j < c - 1; j++)
{
Vector2 startDir = Quaternion.Euler(0, 0, offsetAngle * j) * originDir;
Vector2 endDir = (j == c - 2) ? Quaternion.Euler(0, 0, (360 * value)) * originDir: Quaternion.Euler(0, 0, offsetAngle * (j + 1)) * originDir;
vertices.Add(new UIVertex() { position = Vector2.zero, color = Colors[i],uv0 = new Vector2(0f,0)});
vertices.Add(new UIVertex() { position = endDir * GetRadius(i), color = Colors[i],uv0 = new Vector2(0,0.9f)});
vertices.Add(new UIVertex() { position = startDir * GetRadius(i), color = Colors[i] ,uv0=new Vector2(1,0.9f)});
}
}
toFill.AddUIVertexTriangleStream(vertices);
}
//这里设置每个扇形的半径
float GetRadius(int index)
{
//return length; //选用此处代码则扇形图是半径均匀的
return length* (0.5f + index * radiusOffset);//不同区域数据半径不同
}
还加入了扇形区域选择提示数据值的功能。判断鼠标是否点击到了扇形图内还是折线图里相同的计算方法:
public BoolAndFloat IsRaycastLocationValid(UnityEngine.Vector2 sp, UnityEngine.Camera eventCamera)
{
Vector2 local;
//求出屏幕坐标在canvas下的2D坐标
RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, sp, eventCamera, out local);
Vector3 crossDir = Vector3.Cross(Vector3.up, new Vector3(local.x, local.y, 0));
float angle = Vector2.Angle(Vector2.up, local);
float dis = local.magnitude;
if (Vector3.Dot(crossDir, Vector3.forward) <= 0)
angle = 360 - angle;
float value = angle / 360;
int index = GetIndex(value);
float radius = GetRadius(index);
if (dis <= radius)
return new BoolAndFloat(true,Values[index], radius, GetToTal(index));
else return new BoolAndFloat(false,0, radius,0);
}
float GetToTal(int index)
{
float angle = 0;
for (int i = 0; i < index+1; i++)
{
angle += Values[i];
}
return angle * 360;
}
int GetIndex(float value)
{
float temp = 0;
for (int i = 0; i < Values.Count; i++)
{
temp += Values[i];
if (value <= temp)
return i;
}
return 0;
}
public struct BoolAndFloat
{
public bool Value1;
public float Value2;
public float Dis;
public float Angle;
public BoolAndFloat(bool value1, float value2, float dis,float angle)
{
Value1 = value1;
Value2 = value2;
Dis = dis;
Angle = angle;
}
}
运行结果如下:
项目地址如下:扇形图项目下载地址。