using DG.Tweening;
using UnityEngine;
using UnityEngine.UI;
public class UIRadar : MaskableGraphic
{
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 UIRadarGraphic _radarGraphic;//雷达图
public Text _descPrefab;//描述Prefab
public Transform _descContent;//描述Content
public float _tweenTime = 1f;//动画事件
private Vector2[] _vertexs;//顶点
private float _radius;//半径
private float _perRadian;//弧度
private float _descSpace;//描述间隔
protected override void Awake()
{
base.Awake();
_radius = Mathf.Min(rectTransform.sizeDelta.x, rectTransform.sizeDelta.y) / 2;
_descSpace = Mathf.Max(_descPrefab.rectTransform.sizeDelta.x, _descPrefab.rectTransform.sizeDelta.y) / 5;
}
///
/// 刷新雷达图
///
///
public void RefeshRadarGraph(GraphData[] datas)
{
_datas = datas;
ClearTransform(_descContent);
ClearTransform(_radarGraphic._pointContent);
DrawDesc();
SetAllDirty();//设置Layout布局、Vertices顶点和Material材质为Dirty;当一个Canvas被标记为包含需要被rebatch的几何图形,那这个Canvas被认为dirty。
_radarGraphic.transform.localScale = Vector3.zero;
_radarGraphic.Init(datas, _radius, _radarLineWidth, _radarLineColor);
_radarGraphic.transform.DOScale(Vector3.one, _tweenTime);
_radarGraphic.DrawValuePoint();
}
///
/// UI生成顶点时调用
///
///
protected override void OnPopulateMesh(VertexHelper vh)
{
if (_datas == null || _datas.Length <= 2)//不可能存在边树小于三的多边形
{
base.OnPopulateMesh(vh);
return;
}
vh.Clear();
//DrawAxis(vh);
DrawRuling(vh);
}
///
/// 画坐标轴
///
///
private void DrawAxis(VertexHelper vh)
{
GetVertexs();
for (int i = 0; i < _vertexs.Length; i++)
{
vh.AddUIVertexQuad(GetQuad(Vector2.zero, _vertexs[i], _lineColor, _lineWidth));
}
}
///
/// 画刻度
///
private void DrawRuling(VertexHelper vh)
{
float perRadius = _radius / (_rulingCount - 1);//原点不需要画
for (int i = 1; i < _rulingCount; i++)
{
for (int j = 0; j < _datas.Length; j++)
{
float startRadian = _perRadian * j + 90 * Mathf.Deg2Rad;
float endRadian = _perRadian * (j + 1) + 90 * Mathf.Deg2Rad;
Vector2 startPos = new Vector2(Mathf.Cos(startRadian), Mathf.Sin(startRadian)) * perRadius * i;
Vector2 endPos = new Vector2(Mathf.Cos(endRadian), Mathf.Sin(endRadian)) * perRadius * i;
UIVertex[] newVertexs = GetQuad(startPos, endPos, _lineColor, _lineWidth);
vh.AddUIVertexQuad(newVertexs);
}
}
}
///
/// 描述
///
private void DrawDesc()
{
GetVertexs();
for (int i = 0; i < _vertexs.Length; i++)
{
Text desc = Instantiate(_descPrefab.gameObject).GetComponent();
desc.transform.SetParent(_descContent);
desc.transform.localScale = Vector3.one;
//Text desc = ObjectPool.Instance.GetObject(DESCPOOL, _descContent).GetComponent();
desc.text = _datas[i]._desc;
Vector2 pos = _vertexs[i];
if (Mathf.Abs(pos.x) >= 0.1f)
pos.x += _descSpace * (pos.x > 0 ? 1 : -1);
if (Mathf.Abs(pos.y) >= 0.1f)
pos.y += _descSpace * (pos.y > 0 ? 1 : -1);
desc.rectTransform.localPosition = pos;
desc.gameObject.SetActive(true);
}
}
///
/// 获取顶点
///
///
private void GetVertexs()
{
_perRadian = Mathf.PI * 2 / _datas.Length;
_vertexs = new Vector2[_datas.Length];
for (int i = 0; i < _datas.Length; i++)
{
float radian = _perRadian * i + 90 * Mathf.Deg2Rad;
Vector2 endPos = new Vector2(Mathf.Cos(radian), Mathf.Sin(radian)) * _radius;
_vertexs[i] = endPos;
}
}
///
/// 获取一条线的四个顶点
///
///
///
///
private UIVertex[] GetQuad(Vector2 startPos, Vector2 endPos, Color color, float width)
{
float dis = Vector2.Distance(startPos, endPos);
float x = width / 2 * (endPos.y - startPos.y) / dis;//sin
float y = width / 2 * (endPos.x - startPos.x) / dis;//cos
if (y <= 0) y = -y;
else x = -x;
UIVertex[] vertex = new UIVertex[4];
vertex[0].position = new Vector3(startPos.x + x, startPos.y + y);
vertex[1].position = new Vector3(endPos.x + x, endPos.y + y);
vertex[2].position = new Vector3(endPos.x - x, endPos.y - y);
vertex[3].position = new Vector3(startPos.x - x, startPos.y - y);
for (int i = 0; i < vertex.Length; i++)
vertex[i].color = color;
return vertex;
}
///
/// 入池
///
///
///
private void ClearTransform(Transform parent)
{
for (int i = 1; i < parent.childCount; i++)
{
GameObject.Destroy(parent.GetChild(i).gameObject);
}
}
}