首页 > 代码库 > unity之圆角头像实现
unity之圆角头像实现
重写了一个image组件,将精灵拖进去可调整圆角的大小和平滑度,我写的这个只支持正方形图片,矩形会比较麻烦,暂时还没想到方法
实现思路:
1.如下图,image画图原理就是在一个方框中画三角形,然后形成图片,红线代表方框的坐标系,蓝色代表图片的坐标系,也就是你在这个方框的某个位置上画图片的哪个部位,例如蓝色的(0,0)点,假如image宽度,高度都为2,也就是在黑框的(-1,-1)画一个(0,0)点。
2.如果想要圆角就很简单了,就是在角上多画几个间距相等的点,点越多平滑度越高,例如我图中左上角多加了一个点,四边形也就成了五边形,得到5个点的集合,也就是图中的紫色数字。
3.画图是由很多个三角形构成,(注意添加三角形时,点的方向必须是顺时针的,例如(0,1,2),(2,3,4),(4,5,0)都可以),然后就可以用一个for循环,从0点开始添加三角形(i,i+1,i+2)。添加完成后图也就画好了~~~^_^~~~
4.点的位置,用sin和cos(90/(点的个数))*r(如果想画圆形r就是1/2)得到点在蓝色坐标的位置,红色坐标可以根据蓝色坐标得到,他两关系是固定的嘛。根据宽度得就行(ps:蓝色坐标中,图片的长宽都为1,而红色的是根据image实际的width和height)
1 using System.Collections.Generic; 2 using UnityEngine; 3 using UnityEngine.UI; 4 using UnityEngine.Sprites; 5 6 [AddComponentMenu("UI/Circle Image")] 7 public class CircleImage2 : BaseImage { 8 9 // Use this for initialization 10 void Awake () { 11 innerVertices = new List<Vector3>(); 12 outterVertices = new List<Vector3>(); 13 } 14 15 // Update is called once per frame 16 void Update () { 17 18 } 19 20 21 [Range(0, 1)] 22 public float scale = 1f; 23 24 [Range(2, 30)] 25 public int segements = 2; 26 27 private List<Vector3> innerVertices; 28 private List<Vector3> outterVertices; 29 30 protected override void OnPopulateMesh(VertexHelper vh) 31 { 32 vh.Clear(); 33 Rect pixelAdjustedRect = this.GetPixelAdjustedRect(); 34 35 float w = pixelAdjustedRect.width; 36 for (int i =0; i < segements+1; i++) 37 { 38 UIVertex uivertex = new UIVertex(); 39 uivertex.color = color; 40 if (i ==0) 41 { 42 uivertex.uv0 = new Vector2((scale / 2) * (1 - Mathf.Sin(i * 90 / segements)),(scale / 2) * (1 - Mathf.Cos(i * 90 / segements))); 43 } 44 else 45 { 46 uivertex.uv0 = new Vector2((scale / 2) * (1 - Mathf.Sin(Mathf.PI / (180f /(i * 90 / segements)))), (scale / 2) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))))); 47 } 48 uivertex.position = new Vector3(w*uivertex.uv0.x-w/2,w*uivertex.uv0.y-w/2); 49 50 vh.AddVert(uivertex); 51 } 52 53 for (int i = 0; i < segements + 1; i++) 54 { 55 UIVertex uivertex = new UIVertex(); 56 uivertex.color = color; 57 if (i == 0) 58 { 59 uivertex.uv0 = new Vector2((scale / 2) - (scale / 2) * Mathf.Cos(i * 90 / segements), (1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements)); 60 } 61 else 62 { 63 uivertex.uv0 = new Vector2((scale / 2) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))), (1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))); 64 } 65 uivertex.position = new Vector3(w * uivertex.uv0.x - w / 2, w * uivertex.uv0.y - w / 2); 66 vh.AddVert(uivertex); 67 } 68 69 for (int i = 0; i < segements + 1; i++) 70 { 71 UIVertex uivertex = new UIVertex(); 72 uivertex.color = color; 73 if (i == 0) 74 { 75 uivertex.uv0 = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements), (1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements)); 76 } 77 else 78 { 79 uivertex.uv0 = new Vector2( (1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements))), (1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))); 80 81 } 82 uivertex.position = new Vector3(w * uivertex.uv0.x - w / 2, w * uivertex.uv0.y - w / 2); 83 vh.AddVert(uivertex); 84 } 85 for (int i = 0; i < segements + 1; i++) 86 { 87 UIVertex uivertex = new UIVertex(); 88 uivertex.color = color; 89 if (i == 0) 90 { 91 uivertex.uv0 = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements), (scale / 2) - (scale / 2) * Mathf.Sin(i * 90 / segements)); 92 } 93 else 94 { 95 uivertex.uv0 = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))), (scale / 2) - (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))); 96 } 97 uivertex.position = new Vector3(w * uivertex.uv0.x - w / 2, w * uivertex.uv0.y - w / 2); 98 vh.AddVert(uivertex); 99 } 100 101 //((点*4+8个点-3)条弦+1)个三角形 102 for (int i = 0; i < ((segements - 1) * 4 + 8 - 3 + 1); i++) 103 { 104 vh.AddTriangle(0, i + 1, i + 2); 105 } 106 107 108 } 109 110 public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) 111 { 112 Sprite sprite = overrideSprite; 113 if (sprite == null) 114 return true; 115 116 Vector2 local; 117 RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local); 118 return Contains(local, outterVertices, innerVertices); 119 } 120 121 private bool Contains(Vector2 p, List<Vector3> outterVertices, List<Vector3> innerVertices) 122 { 123 var crossNumber = 0; 124 RayCrossing(p, innerVertices, ref crossNumber);//检测内环 125 RayCrossing(p, outterVertices, ref crossNumber);//检测外环 126 return (crossNumber & 1) == 1; 127 } 128 129 /// <summary> 130 /// 使用RayCrossing算法判断点击点是否在封闭多边形里 131 /// </summary> 132 /// <param name="p"></param> 133 /// <param name="vertices"></param> 134 /// <param name="crossNumber"></param> 135 private void RayCrossing(Vector2 p, List<Vector3> vertices, ref int crossNumber) 136 { 137 for (int i = 0, count = vertices.Count; i < count; i++) 138 { 139 var v1 = vertices[i]; 140 var v2 = vertices[(i + 1) % count]; 141 142 //点击点水平线必须与两顶点线段相交 143 if (((v1.y <= p.y) && (v2.y > p.y)) 144 || ((v1.y > p.y) && (v2.y <= p.y))) 145 { 146 //只考虑点击点右侧方向,点击点水平线与线段相交,且交点x > 点击点x,则crossNumber+1 147 if (p.x < v1.x + (p.y - v1.y) / (v2.y - v1.y) * (v2.x - v1.x)) 148 { 149 crossNumber += 1; 150 } 151 } 152 } 153 } 154 155 156 }
unity之圆角头像实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。