Unity_雷达图(属性图)+ UI动画
效果
介绍
实现雷达图的大体思路:因为要根据不同数量的数据绘制图图形,所以和之前数据图表不同的是,需要自己对UGUI进行重绘。在这之前我没有了解过UGUI底层,所以参考了其他博主的博客(主要是这篇@MrASL(CSDN),这个功能是我在2019年8月份写的,现在是2020年4月份,参考的其他博客没有印象了,抱歉😬)。
绘制UGUI图形的主要思路,和Image组件一样,继承自MaskableGraphic类,当调用SetAllDirty()函数时,使Canvas重新绘制图形,内部调用了MaskableGraphic.OnPopulateMesh(VertexHelper vh)函数,VertexHelper是UI绘制的一个帮助类,绘制之前需要先调用vh.Clear()函数将原有的UI网格清空,然后调用AddUIVertexQuad(UIVertex[] verts)函数、AddVert(Vector3 position, Color32 color, Vector2 uv0)等函数添加绘制图形的顶点、颜色等数据,VertexHelper类里面的函数可以到Unity的官方文档查看使用,这里不做具体介绍了。
继续说雷达图的思路:首先根据一组数据的数量将一张平面圆形的360°平分(我在代码中注释为:坐标轴),得到坐标轴顶点(零点的另一端)的位置数据的描述文本,其次,要在坐标轴上显示数据从0-100(最小-最大)之间的等比刻度,雷达图是根据数据在相应轴的比例计算uv坐标,绘制三角形填充内部,绘线连接形成外框。最后是使用DOTween做的缩放动画。
关键字
1. 对象池
2. DoTween 动画
3. Unity_UI重绘
分析及代码
和之前一样,定义绘图数据的结构GraphData,包含数据的描述信息_desc,数据的值_value。在需要绘图时传递一个GraphData[]数组给此模块就可以实现图表的绘制。
[System.Serializable]
public struct GraphData
{
public string _desc;
[Range(0, 100)]
public float _value;
public float Rate
{
get
{
return _value / 100;
}
}
public GraphData(string desc, float value)
{
_desc = desc;
_value = value;
}
}
下图是Unity的布局:RadarGraphPanel挂载UIRadarGraphManager组件用来绘制底图,Radar挂载UIRadarImage用来绘制数据图,DescContent是空对象用来管理所有描述文本,Desc是描述文本预制体。
根据↑上面的介绍:需要的参数有刻度数(假设0-100,刻度=5,每个刻度为0、25、50、75、100)…其他的参数都有注释,自己看吧。😁
public GraphData[] _datas;
public int _rulingCount = 4;//刻度数
public float _lineWidth = 1f;//背景线宽度
public float _radarLineWidth = 1f;//雷达边框宽度
public Color _lineColor = Color.gray;//背景线颜色
public Color _radarLineColor = Color.blue;//雷达边框颜色
public UIRadarImage _radarImage;//雷达图
public Text _descPrefab;//描述Prefab
public Transform _descContent;//描述Content
public float _tweenTime = 1f;//动画事件
private Vector2[] _vertexs;//顶点
private float _radius;//半径
private float _perRadian;//弧度
private float _descSpace;//描述间隔
private const string DESCPOOL = "RDescPool";
根据数量平分360°绘制每个数据的坐标轴,根据刻度数绘制刻度并连线,获得顶点位置生成文本描述。
绘制底图用到的是UI画线,一条线相当于一个很长的矩形,对于UI网格来说,相当于绘制两个三角形,共用四个顶点。
/// <summary>
/// 画坐标轴
/// </summary>
/// <param name="vh"></param>
private void DrawAxis(VertexHelper vh)
{
GetVertexs();
for (int i = 0; i < _vertexs.Length; i++)
{
vh.AddUIVertexQuad(GetQuad(Vector2.zero, _vertexs[i], _lineColor, _lineWidth));
}
}
/// <summary>
/// 画刻度
/// </summary>
private void DrawRuling(VertexHelper vh)
{
float perRadius = _radius / (_rulingCo