• [UGUI]圆形Image


    参考链接:

    http://www.cnblogs.com/leoin2012/p/6425089.html

    前面说过Mask组件会影响性能:https://www.cnblogs.com/lyh916/p/10587632.html

    因此,尽量少使用Mask,对于类似技能图标那样的圆形图片,可以考虑用本文的方式去实现。

    1.CircleImage.cs

      1 using UnityEngine;
      2 using UnityEngine.UI;
      3 using UnityEngine.Sprites;
      4 using System.Collections.Generic;
      5 
      6 public class CircleImage : Image {
      7 
      8     public float fillPercent = 1f;       //填充比例
      9     public int fillNum = 100;            //填充个数
     10     private List<Vector2> outerVertexs;  //圆上顶点列表
     11 
     12     protected override void Awake()
     13     {
     14         base.Awake();
     15         outerVertexs = new List<Vector2>();
     16     }
     17 
     18     protected override void OnPopulateMesh(VertexHelper toFill)
     19     {
     20         if (overrideSprite == null)
     21         {
     22             base.OnPopulateMesh(toFill);
     23             return;
     24         }
     25 
     26         switch (type)
     27         {
     28             case Type.Simple:
     29                 GenerateSimpleSprite(toFill, preserveAspect);
     30                 break;
     31         }
     32     }
     33 
     34     void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect)
     35     {
     36         vh.Clear();
     37         outerVertexs.Clear();
     38 
     39         //计算准备
     40         Vector4 uv = (overrideSprite != null) ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero;
     41 
     42         float degreeDelta = 2 * Mathf.PI / fillNum;
     43         int curNum = (int)(fillNum * fillPercent);
     44         float width = rectTransform.rect.width;
     45         float height = rectTransform.rect.height;
     46         float radius = width * 0.5f;
     47 
     48         float uvCenterX = (uv.x + uv.z) * 0.5f;
     49         float uvCenterY = (uv.y + uv.w) * 0.5f;
     50         float uvScaleX = (uv.z - uv.x) / width;
     51         float uvScaleY = (uv.w - uv.y) / height;
     52 
     53         //添加第一个点
     54         UIVertex uiVertex = new UIVertex();
     55         uiVertex.color = color;
     56         uiVertex.position = Vector2.zero;
     57         uiVertex.uv0 = new Vector2(uvCenterX, uvCenterY);
     58         vh.AddVert(uiVertex);
     59 
     60         //添加圆上的点
     61         int vertNum = (fillPercent == 1) ? curNum : curNum + 1;
     62         for (int i = 1; i <= vertNum; i++)
     63         {
     64             float curDegree = (i - 1) * degreeDelta;
     65             float cosA = Mathf.Cos(curDegree);
     66             float sinA = Mathf.Sin(curDegree);
     67             Vector2 curVertice = new Vector2(cosA * radius, sinA * radius);
     68 
     69             uiVertex = new UIVertex();
     70             uiVertex.color = color;
     71             uiVertex.position = curVertice;
     72             uiVertex.uv0 = new Vector2(uvCenterX + curVertice.x * uvScaleX, uvCenterY + curVertice.y * uvScaleY);
     73             vh.AddVert(uiVertex);
     74 
     75             outerVertexs.Add(curVertice);
     76         }
     77 
     78         //连接点
     79         for (int i = 1; i < vertNum; i++)
     80         {
     81             vh.AddTriangle(0, i + 1, i);
     82         }
     83         if (fillPercent == 1)
     84         {
     85             vh.AddTriangle(0, 1, curNum);
     86         }
     87 
     88         //连接点击区域
     89         if (fillPercent < 1)
     90         {
     91             outerVertexs.Add(Vector2.zero);
     92         }
     93     }
     94 
     95     public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera)
     96     {
     97         Sprite sprite = overrideSprite;
     98         if (sprite == null)
     99             return true;
    100 
    101         Vector2 local;
    102         RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local);
    103 
    104         return MathTool.IsPointInPolygon(local, outerVertexs);
    105     }
    106 }

    效果如下:

    分析:

    a.顶点数据

    这里以pivot为(0.5,0.5)为例。在这种情况下,图片的位置中心和uv中心重合,即都在图片的中点处。因此这时位置和uv是成比例的,即uv.z - uv.x对应width,uv.w - uv.y对应height,这样就可以根据当前点的位置计算出对应的uv坐标。

    关于圆上的顶点个数,当填充比例小于1时,顶点个数=三角形个数+1;当填充比例等于1时,顶点个数=三角形个数(因为点重合)

    b.顶点连接

    要按顺时针连接(顺时针表示正对屏幕,逆时针表示背对屏幕)。这里使用(0, i + 1, i)的顺序。

    c.点击区域

    使用这个算法:https://www.cnblogs.com/lyh916/p/10633132.html

    要注意的是,当填充比例小于1时,要把原点也加上去,可以考虑一下下面的情况:

    2.CircleImageEditor.cs

     1 using UnityEditor;
     2 using UnityEditor.UI;
     3 
     4 [CustomEditor(typeof(CircleImage))]
     5 public class CircleImageEditor : ImageEditor {
     6 
     7     SerializedProperty fillPercent;
     8     SerializedProperty fillNum;
     9 
    10     protected override void OnEnable()
    11     {
    12         base.OnEnable();
    13         fillPercent = serializedObject.FindProperty("fillPercent");
    14         fillNum = serializedObject.FindProperty("fillNum");
    15     }
    16 
    17     public override void OnInspectorGUI()
    18     {
    19         base.OnInspectorGUI();
    20 
    21         serializedObject.Update();
    22 
    23         fillPercent.floatValue = EditorGUILayout.Slider("填充比例", fillPercent.floatValue, 0, 1);
    24         fillNum.intValue = EditorGUILayout.IntSlider("填充个数", fillNum.intValue, 1, 100);
    25 
    26         serializedObject.ApplyModifiedProperties();
    27     }
    28 }
  • 相关阅读:
    Expression Bland 入门视频(五) 了解对象面板和属性面板
    Windows Phone 一步一步从入门到精通
    “北京今年入冬的第一场雪”,纪念博客园写日志一年了
    2010年即将到来,用我的名字注册了的新域名 TerryFeng.com
    我要在黑龙江的老家,组织一个微软.Net俱乐部
    Windows 7 小工具 问题步骤记录器
    给弟弟起步学习软件开发(.Net 方向)的指导,博友们帮助看看,提些意见给他。
    今天是中国传统节日“重阳节”。也是爷爷的生日,今年80岁高龄。
    Windows 7 远程服务器管理工具 简体中文 下载
    新的技术和概念应该尽可能先去接受,而不是排斥。
  • 原文地址:https://www.cnblogs.com/lyh916/p/10611787.html
Copyright © 2020-2023  润新知