zoukankan      html  css  js  c++  java
  • Unity---UGUI案例学习---雷达图




    1、雷达图

    最后效果


    这里的方法是通过改变黄色区域UI元素的外围顶点位置,来实现出我们需要的渲染效果。

    UGUI

    代码

    Point是蓝色区域最外的顶点,只需执行一次获得其具体位置就行。
    Handler是红色的顶点,每次更新时都要同步更新

    黄色区域雷达图类

    public class Boke_RadarChart : Image
    {
        //顶点个数、顶点位置、顶点大小、顶点显示图片、顶点颜色
        [SerializeField]
        private int _pointCount;
        [SerializeField]
        private List<RectTransform> _points;
        [SerializeField]
        private Vector2 _pointSize = new Vector2(10, 10);
        [SerializeField]
        private Sprite _pointSprite;
        [SerializeField]
        private Color _pointColor = Color.white;
    
        //每个方向上各个点的的比例、存储handler
        [SerializeField]
        private float[] _handlerRadio;
        [SerializeField]
        private List<S5RadarChartHandler> _handlers;
    
        private void Update()
        {
            //刷新
            SetVerticesDirty();
        }
    
        protected override void OnPopulateMesh(VertexHelper vh)
        {
            //修改原来的空image,让他填满我们的雷达图。
            //清空原来顶点,自己添加
            vh.Clear();
            AddVerts(vh);
            //AddVertsTemplete(vh);
            AddTriangle(vh);
        }
    
        /// <summary>
        /// 添加顶点
        /// </summary>
        private void AddVerts(VertexHelper vh)
        {
            //添加轴心点
            vh.AddVert(Vector3.zero, color, Vector2.zero);
            foreach (S5RadarChartHandler handler in _handlers)
            {
                vh.AddVert(handler.transform.localPosition, color, Vector2.zero);
            }
        }
    
        /*
        /// <summary>
        /// 如果需要用贴图。就要每个顶点单独设置uv坐标
        /// </summary>
        private void AddVertsTemplete(VertexHelper vh)
        {
            vh.AddVert(_handlers[0].transform.localPosition, color, new Vector2(0.5f, 1));
            vh.AddVert(_handlers[1].transform.localPosition, color, new Vector2(0f, 1));
            vh.AddVert(_handlers[2].transform.localPosition, color, new Vector2(0f, 0));
            vh.AddVert(_handlers[3].transform.localPosition, color, new Vector2(1f, 0));
            vh.AddVert(_handlers[4].transform.localPosition, color, new Vector2(1f, 1));
        }
        */
    
        /// <summary>
        /// 添加三角形
        /// </summary>
        private void AddTriangle(VertexHelper vh)
        {
            //围绕中心点生成5个面
            for (int i = 1; i < _pointCount; i++)
            {
                //用三个顶点组成一个三角面
                //顺时针
                vh.AddTriangle(0, i + 1, i);
            }
            vh.AddTriangle(0, _pointCount, 1);
        }
    
        public void InitPoint()
        {
            ClearPoints();
            _points = new List<RectTransform>();
            SpawnPoint();
            SetPointPos();
        }
    
        private void ClearPoints()
        {
            if (_points == null)
                return;
    
            foreach (RectTransform point in _points)
            {
                if (point != null)
                    //编辑模式下要用这个
                    DestroyImmediate(point);
            }
        }
    
        private void SpawnPoint()
        {
            //5个最边角的顶点
            for (int i = 0; i < _pointCount; i++)
            {
                GameObject point = new GameObject("Point" + i);
                point.transform.SetParent(transform);
                _points.Add(point.AddComponent<RectTransform>());
            }
        }
    
        private void SetPointPos()
        {
            //每个角的弧度
            float radian = 2 * Mathf.PI / _pointCount;
            //半径
            float radius = 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()
        {
            ClearHandlers();
            _handlers = new List<S5RadarChartHandler>();
            SpawnHandlers();
            SetHandlerPos();
        }
    
        private void ClearHandlers()
        {
            if (_handlers == null)
                return;
    
            foreach (S5RadarChartHandler handler in _handlers)
            {
                if (handler != null)
                    DestroyImmediate(handler.gameObject);
            }
        }
    
        private void SpawnHandlers()
        {
            S5RadarChartHandler handler = null;
            for (int i = 0; i < _pointCount; i++)
            {
                GameObject point = new GameObject("Handler" + i);
                point.AddComponent<RectTransform>();
                point.AddComponent<Image>();
    
                handler = point.AddComponent<S5RadarChartHandler>();
                handler.SetParent(transform);
                handler.ChangeSprite(_pointSprite);
                handler.ChangeColor(_pointColor);
                handler.SetSize(_pointSize);
                handler.SetScale(Vector3.one);
                _handlers.Add(handler);
            }
        }
    
        private void SetHandlerPos()
        {
            //默认的handler位置,就是5项属性全满。
            if (_handlerRadio == null || _handlerRadio.Length != _pointCount)
            {
                for (int i = 0; i < _pointCount; i++)
                {
                    _handlers[i].SetPos(_points[i].anchoredPosition);
                }
            }
            else
            {
                for (int i = 0; i < _pointCount; i++)
                {
                    _handlers[i].SetPos(_points[i].anchoredPosition * _handlerRadio[i]);
                }
            }
        }
    }
    

    红色顶点类

    public class Boke_RadarChartHandler : MonoBehaviour
    {
        private Image _image;
        private Image Image
        {
            get
            {
                if (_image == null)
                    _image = GetComponent<Image>();
    
                return _image;
            }
        }
    
        private RectTransform _rect;
        private RectTransform Rect
        {
            get
            {
                if (_rect == null)
                    _rect = GetComponent<RectTransform>();
    
                return _rect;
            }
        }
    
        #region 封装一层
        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 SetPos(Vector2 pos)
        {
            Rect.anchoredPosition = pos;
        }
        public void SetSize(Vector2 size)
        {
            Rect.sizeDelta = size;
        }
        public void SetScale(Vector3 scale)
        {
            Rect.localScale = scale;
        }
        private float GetScale()
        {
            return Rect.lossyScale.x;
        }
        #endregion
    }
    

    编辑器类,用于把Boke_RadarChart类中的可变属性显示到面板中,方便我们更改调试。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEditor;
    
    [CustomEditor(typeof(Boke_RadarChart), true)]
    [CanEditMultipleObjects]
    public class Boke_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);
    
            Boke_RadarChart radar = target as Boke_RadarChart;
            if (radar != null)
            {
                if (GUILayout.Button("生成雷达图顶点"))
                {
                    radar.InitPoint();
                }
    
                if (GUILayout.Button("生成内部可操作顶点"))
                {
                    radar.InitHandlers();
                }
            }
            serializedObject.ApplyModifiedProperties();
            if (GUI.changed)
            {
                EditorUtility.SetDirty(target);
            }
    
        }
    }
    
    

    学习自Andy老师UGUI教程

  • 相关阅读:
    zipalign内存对齐优化
    反编译 waring...
    android.os.NetworkOnMainThreadException
    android:LayoutInflater
    Notification NotificationManager RemoteViews PendingIntent
    WebView WebViewClient WebChromeClient
    寒假1
    冻死可怕了
    一个人失眠
    军训快乐
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/12713312.html
Copyright © 2011-2022 走看看