文章目录
👉一、前言
项目中有遇到实现UI圆角化的功能,在网上看了一下,普遍是用Shader来实现的。但感觉用网上的Shader实现的圆角化跟传统软件(PS、 Word、Maya、AE)上的圆角化效果不太一样。最终还是决定用Unity提供的方法去实现圆角化功能。其实只要了解了圆角化的构图原理,很轻松就可以利用MaskableGraphic去绘制UI圆角了。
👉二、圆角化原理
1、以Word圆角矩形为例,找出圆角化规律
首先我们应该有一个圆角系数Radius(也可以叫圆角半径吧)的概念,为了方便计算,让它归一化:从0到1。请看以下两张图:
不难看出这样一个规律:Radius从0到1的过程,就是矩形四个边角小圆形从半径为0到最大值的演变过程,这个最大值等于矩形最短那一边的一半。
2、根据圆角化规律,得出UI圆角绘制流程
1.根据圆角系数Radius计算出四个边角圆形的真实半径realRadius
2.确定四个边角圆形的圆心位置(以左上角圆心为例,在UI矩形自身坐标系下,该圆心x坐标为:负的(UI的宽Width的一半减去realRadius);y坐标为:负的(UI的高Height的一半减去realRadius))。
3.确定水平方向矩形顶点坐标,绘制这个矩形用来补充圆形水平方向之间的空隙:
同理确定垂直方向矩形顶点坐标,补充圆形垂直方向之间的空隙:
4.绘制的时候先根据圆心坐标和半径通过数学公式计算出圆上的点的坐标,首先绘制四个边角圆,最后绘制两个矩形,设置颜色,就可以实现我们想要的圆角化效果了。
5.当UI的宽高一样时,即在正方形内画圆角,当圆角系数为1时,四个圆形重合为一个圆。
👉三、完整圆角化绘制代码
脚本挂载到UI空物体上,设置Radius或者UI的宽高即可。
usingSystem.Collections.Generic;usingUnityEngine;usingUnityEngine.UI;publicclassRoundCorner:MaskableGraphic{/// <summary>/// 圆角系数,归一化从0到1/// </summary>[Range(0,1.0f)]publicfloat radius =1f;//提供访问器,供外部设置圆角系数publicfloat Radius
{get{return radius;}set{
radius =value;SetVerticesDirty();}}//三角形顶点下标[SerializeField]privateint triangleIdx =0;/// <summary>/// 每个圆的三角形个数/// </summary>[Range(3,200)]publicint triangleCount =100;protectedoverridevoidOnPopulateMesh(VertexHelper vh){
vh.Clear();//计算真实半径范围float realRadius;if(rectTransform.rect.height < rectTransform.rect.width)
realRadius =0.5f* rectTransform.rect.height * radius;else
realRadius =0.5f* rectTransform.rect.width * radius;//确定四个边角圆形圆心的坐标//左下角圆心Vector2 leftBottomCenter =newVector2(-0.5f* rectTransform.rect.width + realRadius,-0.5f* rectTransform.rect.height + realRadius);//左上角圆心Vector2 leftTopCenter =newVector2(-0.5f* rectTransform.rect.width + realRadius,0.5f* rectTransform.rect.height - realRadius);//右上角圆心Vector2 rightTopCenter =newVector2(0.5f* rectTransform.rect.width - realRadius,0.5f* rectTransform.rect.height - realRadius);//右下角圆心Vector2 rightBottomCenter =newVector2(0.5f* rectTransform.rect.width - realRadius,-0.5f* rectTransform.rect.height + realRadius);//确定左右矩形顶点坐标var left_corner0 =newVector2(-0.5f* rectTransform.rect.width,-0.5f* rectTransform.rect.height + realRadius);var left_corner1 =newVector2(-0.5f* rectTransform.rect.width,0.5f* rectTransform.rect.height - realRadius);var right_corner2 =newVector2(0.5f* rectTransform.rect.width,0.5f* rectTransform.rect.height - realRadius);var right_corner3 =newVector2(0.5f* rectTransform.rect.width,-0.5f* rectTransform.rect.height + realRadius);//确定上下矩形顶点坐标var down_corner0 =newVector2(-0.5f* rectTransform.rect.width + realRadius,-0.5f* rectTransform.rect.height);var up_corner1 =newVector2(-0.5f* rectTransform.rect.width + realRadius,0.5f* rectTransform.rect.height);var up_corner2 =newVector2(0.5f* rectTransform.rect.width - realRadius,0.5f* rectTransform.rect.height);var down_corner3 =newVector2(0.5f* rectTransform.rect.width - realRadius,-0.5f* rectTransform.rect.height);//首先绘制四个边角圆形List<Vector2> circleCenters =newList<Vector2>();
circleCenters.Add(leftBottomCenter);
circleCenters.Add(leftTopCenter);
circleCenters.Add(rightTopCenter);
circleCenters.Add(rightBottomCenter);//三角形的弧度float angle =360f/ triangleCount * Mathf.Deg2Rad;
triangleIdx =0;for(int i =0; i < circleCenters.Count; i++){DrawCircle(vh, circleCenters[i], realRadius, triangleCount, angle, color);}//最后绘制两个矩形
vh.AddUIVertexQuad(GetRectangleQuad(color, left_corner0, left_corner1, right_corner2, right_corner3));
vh.AddUIVertexQuad(GetRectangleQuad(color, down_corner0, up_corner1, up_corner2, down_corner3));}/// <summary>/// 画圆/// </summary>/// <param name="vh"></param>/// <param name="center">圆心坐标</param>/// <param name="r">半径</param>/// <param name="angle">弧度</param>/// <param name="c">颜色</param>publicvoidDrawCircle(VertexHelper vh,Vector2 center,float r,int triangle,float angle,Color c){//添加圆心点为第一个点
vh.AddVert(GetUIVertex(center, c));//获取圆上的点for(int i =0; i < triangle; i++){float _angle = angle * i;//此时以圆心为0,0点,且从圆形顶部开始计算Vector2 borderXY =newVector2(r * Mathf.Sin(_angle), r * Mathf.Cos(_angle));//映射到矩形上的点应为Vector2 borderPos = center + borderXY;
vh.AddVert(GetUIVertex(borderPos, c));}//绘制圆中三角形for(int i =0; i < triangle; i++){if(i == triangle -1)
vh.AddTriangle(triangleIdx, i +1+ triangleIdx,1+ triangleIdx);else
vh.AddTriangle(triangleIdx, i +1+ triangleIdx, i +2+ triangleIdx);}
triangleIdx += triangleCount +1;}/// <summary>/// 获取矩形面片/// </summary>publicstaticUIVertex[]GetRectangleQuad(Color _color,paramsVector2[] vector2s){UIVertex[] vertexs =newUIVertex[vector2s.Length];for(int i =0; i < vertexs.Length; i++){
vertexs[i]=GetUIVertex(vector2s[i], _color);}return vertexs;}/// <summary>/// 获取UI顶点/// </summary>/// <param name="point"></param>/// <param name="color"></param>/// <returns></returns>publicstaticUIVertexGetUIVertex(Vector2 point,Color _color){UIVertex vertex =newUIVertex{
position = point,
color = _color,
uv0 = Vector2.zero
};return vertex;}}
👉四、圆角化效果演示
1.效果图
2.动态修改Radius和UI宽高
版权归原作者 周周的Unity小屋 所有, 如有侵权,请联系我们删除。