2025-05-18 01:04:31 +08:00

194 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
namespace G.UI
{
public class RadarChart : Image
{
// Start is called before the first frame update
[SerializeField]
public int _pointCount;
[SerializeField]
public List<RectTransform> _points = new List<RectTransform>();
[SerializeField]
private Vector2 _pointSize = new Vector2(10, 10);
[SerializeField]
private Sprite _pointSprite;
[SerializeField]
private Color _pointColor = Color.white;
[SerializeField]
public List<RadarChartHandler> _handlers = new List<RadarChartHandler>();
[SerializeField]
private float[] _handlerRadio;
public float[] radio
{
get { return _handlerRadio; }
}
private void Update()
{
SetVerticesDirty(); //实时对顶点数据刷新
}
protected override void OnPopulateMesh(VertexHelper vertexHelper)
{
vertexHelper.Clear();
if (_handlers != null && _handlers.Count > 0)
if (!_handlers[0])
_handlers.Clear();
if (_handlers != null && _handlers.Count == 0)
return;
AddVerts(vertexHelper); //添加全部顶点信息
//AddVertsPlate(vertexHelper);
AddTriangles(vertexHelper); //添加全部面信息
}
/// <summary>
/// 添加顶点
/// </summary>
/// <param name="vh"></param>
private void AddVerts(VertexHelper vh)
{
vh.AddVert(transform.localPosition, color, Vector2.one);
foreach (var handler in _handlers)
{
vh.AddVert(handler.transform.localPosition, color, Vector2.zero);
}
}
/// <summary>
/// 添加顶点模板 制作带sprite的雷达图效果
/// </summary>
/// <param name="vh"></param>
private void AddVertsPlate(VertexHelper vh)
{
if (_handlers != null && _handlers.Count > 0)
{
if (!_handlers[0])
{
_handlers.Clear();
return;
}
vh.AddVert(_handlers[0].transform.localPosition, color, new Vector2(0.5f, 1.0f));
vh.AddVert(_handlers[1].transform.localPosition, color, new Vector2(0f, 1.0f));
vh.AddVert(_handlers[2].transform.localPosition, color, new Vector2(0f, 0f));
vh.AddVert(_handlers[3].transform.localPosition, color, new Vector2(1.0f, 0f));
vh.AddVert(_handlers[4].transform.localPosition, color, new Vector2(1.0f, 1.0f));
}
}
private void AddTriangles(VertexHelper vh) //UI.Default.shader 默认剔除是关闭的,模型黑面,很奇怪(法向量搞反)
{
for (int i = 1; i <= _pointCount - 1; i++)
{
vh.AddTriangle(0, i + 1, i);
}
vh.AddTriangle(0, 1, 5);
}
public void InitPoints()
{
ClearPoints();
_points = new List<RectTransform>();
_handlers = new List<RadarChartHandler>();
SpawnPoints();
SetPointPos();
}
private void SpawnPoints() //生成 point
{
for (var i = 0; i < _pointCount; i++)
{
var point = new GameObject("Point" + i);
point.transform.SetParent(transform);
_points.Add(point.AddComponent<RectTransform>());
}
}
private void ClearPoints()
{
if (_points == null) return;
foreach (var point in _points.Where(point => point != null))
{
DestroyImmediate(point); //在编译时也能进行
}
}
private void ClearHandles()
{
if (_handlers == null) return;
for (int i = _handlers.Count - 1; i >= 0; i--)
{
if (_handlers[i])
{
DestroyImmediate(_handlers[i].gameObject);
}
}
_handlers.Clear();
}
private void SetPointPos() //设置点坐标
{
float radian = 2 * Mathf.PI / _pointCount; //计算出当前多边形的每一段对应填充圆的弧长
float radius = 130; //暂定当前正多边形的所填充圆的半径为100.
float curRadian = 2 * Mathf.PI / 4.0f; //计算出初始弧度位置 为正五边形的正上方 (起点选择与坐标轴延伸线相接的地方)
for (int i = 0; i < _pointCount; i++)
{
float x = Mathf.Cos(curRadian) * radius;
float y = Mathf.Sin(curRadian) * radius;
curRadian += radian;
_points[i].anchoredPosition = new Vector2(x, y);
}
}
public void InitHandlers()
{
ClearHandles();
SpawnHandlers();
SetHandlerPos();
}
private void SpawnHandlers()
{
for (int i = 0; i < _pointCount; i++)
{
if (i < _handlers.Count)
{
continue;
}
var go = new GameObject("Handler" + i);
go.AddComponent<RectTransform>();
go.AddComponent<Image>();
var handler = go.AddComponent<RadarChartHandler>();
handler.transform.SetParent(transform, false);
handler.ChangeColor(_pointColor);
handler.ChangeSprite(_pointSprite);
handler.SetSize(_pointSize);
_handlers.Add(handler);
}
}
private void SetHandlerPos()
{
if (_handlerRadio == null || _handlerRadio.Length != _pointCount)
{
for (var i = 0; i < _pointCount; i++)
{
if (_handlers[i])
_handlers[i].SetPos(_points[i].anchoredPosition);
}
}
else
{
for (var i = 0; i < _pointCount; i++)
{
if (_handlers[i])
_handlers[i].SetPos(_points[i].anchoredPosition * _handlerRadio[i]);
}
}
}
}
}