UGUI雷达图的实现

RadarChart.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RadarChart : Image
{
    [SerializeField]
    private int pointCount;
    [SerializeField]
    private List<RectTransform> pointList;
    [SerializeField]
    private Sprite pointSprite;
    [SerializeField]
    private Color pointColor=Color.white;
    [SerializeField]
    private Vector2 pointSize;
    [SerializeField]
    private List<RaderChartHandler> handlerList;
    [SerializeField]
    private float[] handlerRadio;//代表每个handler所占那条轴线的比例


    private void Update()
    {
        //设置成dirty状态,此状态下顶点信息会实时刷新,实时重新连接绘制
        SetVerticesDirty();
    }

    //图形界面编写
    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        //AddVerts(vh);
        AddVertsTemplete(vh);
        AddTriangle(vh);
    }
    //把handler作为顶点信息添加进去
    private void AddVerts(VertexHelper vh)
    {
        foreach (RaderChartHandler hander in handlerList)
        {
            vh.AddVert(hander.transform.localPosition,color,Vector2.zero);
        }
    }


    //当要添加进去的精灵不是五边形,是矩形时候,计算uv坐标,把矩形上边拉伸,成五边形
    private void AddVertsTemplete(VertexHelper vh)
    {
        vh.AddVert(handlerList[0].transform.localPosition, color, new Vector2(0.5f,1));
        vh.AddVert(handlerList[1].transform.localPosition, color, new Vector2(0, 1));
        vh.AddVert(handlerList[2].transform.localPosition, color, new Vector2(0, 0));
        vh.AddVert(handlerList[3].transform.localPosition, color, new Vector2(1, 0));
        vh.AddVert(handlerList[4].transform.localPosition, color, new Vector2(1, 1));
    }

    //根据顶点信息生成三角形
    private void AddTriangle(VertexHelper vh)
    {
        for (int i = 1; i < pointCount-1; i++)
        {
            vh.AddTriangle(0, i + 1, i);
        }
    }


    //初始化
    public void InitPoint()
    {
        ClearPoints();
        pointList = new List<RectTransform>();
        SpawnPoint();
        SetPointPos();
    }
    //清除point
    private void ClearPoints()
    {
        if (pointList==null)
        {
            return;
        }
        foreach (RectTransform point in pointList)
        {
            if (point!=null)
            {
                //立即销毁对象,该函数应只在编写 Editor 代码时使用,因为在编辑模式下,永远不会调用延迟销毁(destory)。
                //RectTransform 是一个组件,它可以直接被销毁,而 Unity 会自动处理与之关联的游戏对象。
                //因此,直接调用 DestroyImmediate(point) 就足够了,因为它会处理 RectTransform 所在的游戏对象。
                DestroyImmediate(point);
            }
        }

    }

    //设置几个point点的初始位置
    private void SetPointPos()
    {
        //根据弧度求出point的坐标
        float radian = 2 * Mathf.PI / pointCount;
        float radius = 100;
        float curRadian = Mathf.PI * 0.5f;
        for (int i = 0; i < pointCount; i++)
        {
            float x = Mathf.Cos(curRadian) * radius;
            float y = Mathf.Sin(curRadian) * radius;
            curRadian += radian;
            //设置锚定位置,此 RectTransform 的轴心相对于锚点参考点的位置。
            pointList[i].anchoredPosition = new Vector2(x, y);
        }
    }

    //设置出生点数
    private void SpawnPoint()
    {
        for (int i = 0; i < pointCount; i++)
        {
            GameObject point = new GameObject("Point" + i);
            point.transform.parent = transform;
            pointList.Add(point.AddComponent<RectTransform>());
        }
    }

    //初始化中间可操作点
    public void InitHandlers()
    {
        ClearHandlers();
        handlerList = new List<RaderChartHandler>();
        SpawnHandlers();
        SetHandlerPos();

    }

    private void ClearHandlers()
    {
        if (handlerList == null)
        {
            return;
        }
        foreach (RaderChartHandler handler in handlerList)
        {
            if (handler != null)
            {
                //立即销毁对象,该函数应只在编写 Editor 代码时使用,因为在编辑模式下,永远不会调用延迟销毁(destory)。
                //DestroyImmediate(handler.gameObject) 需要指定 gameObject 是因为 RaderChartHandler 是一个脚本组件,
                //而 DestroyImmediate 只能销毁游戏对象或其组件。
                DestroyImmediate(handler.gameObject);
            }
        }

    }

    private void SpawnHandlers()
    {
        //创建一个缓存变量
        RaderChartHandler handler = null;
        for (int i = 0; i < pointCount; i++)
        {
            GameObject point = new GameObject("Handler" + i);
            point.AddComponent<RectTransform>();
            point.AddComponent<Image>();
            //使用缓存变量存储handlerpoint的一个radercharthandler组件
            handler=point.AddComponent<RaderChartHandler>();
            handler.SetParent(transform);
            handler.ChangeSprite(pointSprite);
            handler.ChangeColor(pointColor);
            handler.SetSize(pointSize);
            handlerList.Add(handler);
        }
    }

    private void SetHandlerPos()
    {
        if (handlerRadio == null||handlerRadio.Length<pointCount)
        {
            for (int i = 0;i < pointCount;i++)
            {
                handlerList[i].SetPos(pointList[i].anchoredPosition);
            }
        }
        else
        {
            for (int i = 0;i<pointCount;i++)
            {
                handlerList[i].SetPos(pointList[i].anchoredPosition * handlerRadio[i]);
            }
        }
    }
}

RadarChartHandler.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class RaderChartHandler : MonoBehaviour, IDragHandler
{
    //获得image组件属性,利用属性来设置方法
    private Image _image;
    private Image image
    {
        get
        {
            if (_image == null)
            {
                _image = GetComponent<Image>();
            }
            return _image;
        }
    }

    //获得recttransform组件属性,利用属性来设置方法
    private RectTransform _rect;
    private RectTransform rect
    {
        get
        {
            if (_rect == null)
            {
                _rect = GetComponent<RectTransform>();
            }

            return _rect;
        }
    }

    public void SetParent(Transform parent)
    {
        transform.SetParent(parent);
    }

    public void ChangeSprite(Sprite sprite)
    {
        image.sprite = sprite;
    }

    public void ChangeColor(Color color)
    {
        image.color = color;
    }

    public void SetSize(Vector2 size)
    {
        rect.sizeDelta = size;
    }

    public void SetPos(Vector2 pos)
    {
        rect.anchoredPosition = pos;
    }

    public void OnDrag(PointerEventData eventData)
    {
        rect.anchoredPosition += eventData.delta/GetScale();
    }

    private float GetScale()
    {
        return rect.lossyScale.x;
    }
}

RadarChartEditor.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(RadarChart), true)]
[CanEditMultipleObjects]
public class RadarChartEditor : UnityEditor.UI.ImageEditor
{
    SerializedProperty pointCount;
    SerializedProperty pointSprite;
    SerializedProperty pointColor;
    SerializedProperty pointSize;
    SerializedProperty handlerRadio;

    protected override void OnEnable()
    {
        base.OnEnable();
        pointCount = serializedObject.FindProperty("pointCount");
        pointSprite = serializedObject.FindProperty("pointSprite");
        pointColor = serializedObject.FindProperty("pointColor");
        pointSize = serializedObject.FindProperty("pointSize");
        handlerRadio = serializedObject.FindProperty("handlerRadio");
    }

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        serializedObject.Update();
        
        EditorGUILayout.PropertyField(pointCount);
        EditorGUILayout.PropertyField(pointSprite);
        EditorGUILayout.PropertyField(pointColor);
        EditorGUILayout.PropertyField(pointSize);
        EditorGUILayout.PropertyField(handlerRadio,true);

        RadarChart radar = target as RadarChart;
        if (radar != null)
        {
            if (GUILayout.Button("生成雷达图顶点"))
            {
                radar.InitPoint();
            }

            if (GUILayout.Button("生成内部可操作顶点"))
            {
                radar.InitHandlers();
            }
        }
        serializedObject.ApplyModifiedProperties();
        if (GUI.changed)
        {
            EditorUtility.SetDirty(target);
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值