UGUI 繪製自定義折線圖

使用

這裏寫圖片描述

  1. 掛載LineChart.cs
  2. 點擊autoCreate按鈕,會創建子節點,可以在子節點上掛載自定義控件

實現

LineChart.cs

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

namespace ViVi.UIExtensions
{
    [ExecuteInEditMode]
    [RequireComponent(typeof(PTLineChartRender))]


    public class LineChart : MonoBehaviour
    {
        public GameObject[] childNode;




        void Awake()
        {
        }

        // Update is called once per frame
        void Update()
        {
            GameObject go;
            Vector2 size = GetComponent<RectTransform>().rect.size;
            LineChartRender render = GetComponent<LineChartRender>();
            for (int i = 0; i < childNode.Length; i++)
            {
                go = childNode[i];
                if(go!=null)
                {
                    go.GetComponent<RectTransform>().anchoredPosition = new Vector2((size.x / (render.values.Length-1)) * i - size.x*0.5f ,size.y * render.values[i]- size.y*0.5f);
                }
            }
        }
    }
}

LineChartRender.cs

using UnityEngine;
using UnityEngine.UI; 

namespace ViVi.UIExtensions{
    public class LineChartRender : MaskableGraphic {

        [Range (0f, 1f)] 
        public float[] values = new float[2]{1,1};


        public Color BottomColor = Color.white;

        public Color TopColor = Color.white;


        public bool useEdge = false;


        public bool useLine = false;

        [Range (0f, 2.5f)] 
        public float lineWidth = 1.0f;
        [Range (0f, 2.5f)] 
        public float edgeWidth = 1.0f;

        public Color lineColor = Color.black;

        public Color edgeColor = Color.black;



        protected override void OnPopulateMesh(VertexHelper vh)
        {
            Vector2 size = GetComponent<RectTransform>().rect.size;
            vh.Clear();
            int partCount = values.Length;
            float spx = size.x / (float) (partCount - 1);
            float nx = 0;
            float nx1 = 0;


            float height = size.y;

            float sph = size.y * 0.5f;
            float spw = size.x * 0.5f;
            for (int i = 0; i < partCount - 1; i++)
            {
                nx = spx * i - spw;
                nx1 = nx + spx;

                float x1=  (float)i/(float)partCount;
                float x2=  (float)(i+1)/(float)partCount;

                //UIVertex[] vertexs = new UIVertex[4];
                UIVertex v1 = UIVertex.simpleVert;
                UIVertex v2 = UIVertex.simpleVert;
                UIVertex v3 = UIVertex.simpleVert;
                UIVertex v4 = UIVertex.simpleVert;

                v1.position = new Vector2(nx, height * values[i]  - sph);
                v2.position = new Vector2(nx, -sph);
                v3.position = new Vector2(nx1, -sph);
                v4.position = new Vector2(nx1, height * values[i + 1] - sph);


                v1.color = Color.Lerp(BottomColor, TopColor, values[i]);
                v2.color = Color.Lerp(BottomColor, TopColor, 0);
                v3.color = Color.Lerp(BottomColor, TopColor, 0);
                v4.color = Color.Lerp(BottomColor, TopColor, values[i+ 1]);



                v1.uv0 = new Vector2(x1,values[i]);
                v2.uv0 = new Vector2(x1,0);
                v3.uv0 = new Vector2(x2,0);
                v4.uv0 = new Vector2(x2,values[i+ 1]);

                if (useLine)
                {
                    if(i==0)
                        vh.AddUIVertexQuad (GetLine (v1.position, v2.position,lineColor,lineWidth));
                    vh.AddUIVertexQuad (GetLine (v3.position, v4.position,lineColor,lineWidth));
                }


                vh.AddUIVertexQuad(new UIVertex[4]{v4,v3,v2,v1});




                if (useEdge)
                {
                    vh.AddUIVertexQuad (GetLine (v1.position, v4.position,edgeColor,edgeWidth));
                }


            }

        }



        private UIVertex[] GetLine (Vector2 start, Vector2 end ,Color lcolor ,float lwidth) {
            UIVertex[] vs = new UIVertex[4];
            Vector2[] uv = new Vector2[4];
            uv[0] = new Vector2(0, 0);
            uv[1] = new Vector2(0, 1);
            uv[2] = new Vector2(1, 0);
            uv[3] = new Vector2(1, 1);
            Vector2 v1 = end - start;
            Vector2 v2 = (v1.y == 0f) ? new Vector2 (0f, 1f) : new Vector2 (1f, -v1.x / v1.y);
            v2.Normalize ();
            v2 *= lwidth / 2f;
            Vector2[] pos = new Vector2[4];
            pos[0] = start + v2;
            pos[1] = end + v2;
            pos[2] = end - v2;
            pos[3] = start - v2;
            for (int i = 0; i < 4; i++) {
                UIVertex v = UIVertex.simpleVert;
                v.color = lcolor;
                v.position = pos[i];
                v.uv0 = uv[i];
                vs[i] = v;
            }
            return vs;
        }


    }
}

Editor 編輯器擴展

LineChartEditor.cs


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


namespace ViVi.UIExtensions
{
    [CustomEditor(typeof(LineChart))]
    [CanEditMultipleObjects]
    public class LineChartEditor: Editor
    {

        SerializedProperty childNode;

        private LineChart lineChart;
        void OnEnable()
        {
            lineChart = (LineChart) target;
            childNode = serializedObject.FindProperty("childNode");


        }

        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            DrawDefaultInspector();

            if (GUILayout.Button("Auto Create"))
            {       
                LineChartRender render = null;
                render = lineChart.gameObject.GetComponent<LineChartRender>();
                childNode.ClearArray();
                childNode.arraySize = 0;
                GameObject go;
                Vector2 size = lineChart.GetComponent<RectTransform>().rect.size;
                for (int i = 0; i < render.values.Length; i++)
                {
                    Transform tf = lineChart.transform.FindChild("v" + i);
                    RectTransform rect;
                    if (tf == null)
                    {
                        go = new GameObject();
                        rect = go.AddComponent<RectTransform>();
                        go.name = "v" + i;
                        //go.transform.parent = lineChart.transform;
                        rect.SetParent(lineChart.transform,false);

                    }
                    else
                    {
                        go = tf.gameObject;
                        rect = tf.GetComponent<RectTransform>();
                    }

                    rect.localScale = Vector3.one;
                    rect.localRotation = Quaternion.identity;
                    rect.pivot = new Vector2(0.5f,0.5f);
                    rect.sizeDelta = new Vector2(10,10);

                    rect.anchoredPosition = new Vector2((size.x / (render.values.Length-1)) * i - size.x*0.5f ,size.y * render.values[i]- size.y*0.5f);

                    childNode.arraySize += 1;
                    SerializedProperty npc =childNode.GetArrayElementAtIndex(childNode.arraySize-1);
                    npc.objectReferenceValue = go;
                    serializedObject.ApplyModifiedProperties();
                }
            }


            if (GUILayout.Button("Clean Child"))
            {
                childNode.ClearArray();
                childNode.arraySize = 0;
                List<GameObject> child = new List<GameObject>(); 
                for (int i = 0; i < lineChart.transform.childCount; i++)
                {
                    child.Add(lineChart.transform.GetChild(i).gameObject);
                }
                for (int i = 0; i < child.Count; i++)
                {
                    GameObject.DestroyImmediate(child[i]);
                }
                child.Clear();
                serializedObject.ApplyModifiedProperties();
            }
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章