Unity自定义UI组件(三)饼图篇

我的梦境 提交于 2019-12-03 14:14:29

Unity自定义UI组件(三)饼图篇

   博主在工作中曾经多次遇到过要计算并显示一些数据占比的功能,但是数值的显示不够直观,然后在Unity商店中看到有人编写过类似的UI插件,但是价格小贵,就萌发了自己编写类似插件的冲动,第一次编写是利用Image组件设置为Filled类型时可实现扇形的功能进行组合,弊端特别明显就是需要制作预制物,使得代码量比较庞大,而且为了实现一些炫酷的功能,还得引入缓冲池去避免不停生成扇形带来的性能妥协,之后在了解了MaskableGraphic类型之后,利用底层绘制,可以避免由组件拼合的多种性能的妥协,而且极易移植,因为只需要的一个脚本即可,下面会详细讲解如何绘制,并将附上源码。

主要内容:

1.饼图的基础实现
2.饼图百分比文字的显示
3.饼图文字的自适应
4.饼图样式自定义

实现效果:

饼图

详细设计:

1.饼图的绘制过程:

1.1 获取以某个点为中心,固定半径的圆上的点,再结合原点绘制三角面,可生成扇形;

图一

  //计算圆上点的位置 Smooth代表圆的光滑程度,也就是饼图被分为多少等份
  int Smooth = 100;
  float perRadian = Matfh.PI * 2 / Smooth;//得到每份所占弧度
  然后根据某一块饼图所占的比例计算出它在圆周上相交的点,我们规定从饼图右侧中间位置开始,逆时针方向计算。见图1:

  //比如绘制19%比例的扇形图
  float radius = x;//半径
  float startRadian = 0;
  Vector2 startPoint = new Vector2( radius,0 );
  for( int i = 0 ; i * perRadian < 0.19f * Mathf.PI * 2 ; i ++ )
  {
      float endRadian = startRadian + perRadian;
      Vector2 endPoint = new Vector2(Matfh.Cos(startRadian),Mathf.Sin(endRadian));
      startRadian = endRadian;
      startPoint = endPoint;
      //如上我们就可以利用startPoint点和endPoint和原点绘制出一个三角形,多个三角形的"积分"就是扇形了
  }
1.2 按输入数据的数量,分为若干扇形,一次绘制;
  //多个扇形的绘制就是我们只需要将以上的代码写到一个循环中就可以自动完成
  for( int i = 0 ; i < Count ; i ++ )
  {
      //执行1.1中类似的代码
  }
1.3 在绘制时,为UIVertex(UI顶点)传入不同的颜色值,即可分类
  //在以上的步骤中我们已经能够绘制出一个饼图,但是我们应该如何为不同的扇形附上不同的颜色值,我们需要在绘制三角面的时候会顶点设置颜色
  UIVertex vertex = new UIVertex
  {
      position = point ,
      color = color0 ,
  };
  //每次构造一个UI顶点的时候,给 color属性赋值即可,因此我们就需要注意在构造饼图类型的时候讲颜色属性添加为一个Public字段,方便在这里使用。
1.4 实现饼图空心的原理是,绘制时不与原点组合三角面,原理见图2

图2

    绘制不在是与中心点直接构成三角形面进行绘制了,而是与小尺寸的圆的两个新交点构成了一个矩形,因此得按照两个三角形绘制,可以直接利用VertexHelper提供绘制矩形的接口直接绘制。
1.5 实现饼图炸裂的原理,在每次绘制完一个扇形之后,隔一定弧度进行下一个扇形的绘制,这个弧度的大小可以自定义。就是在上面的绘制代码的结尾处,将startRadian(绘制起始点)加一份炸裂效果产生的间隔的弧度:
  float boomRadian = x ; 
  for( int i = 0 ; i * perRadian < 0.19f * Mathf.PI * 2 ; i ++ )
  {
      //P-CODE
      startRadian += boomRadian;
  }

2. 文字的添加:

2.1 文字应该显示在折线的左端或者右端,计算出折线的左端或者右端的点的位置,就可以确定文字的位置,并且确定文字应该左对齐,还是右对齐

图3

  //如果需要绘制百分比的文字,则需要我们在绘制扇形的时候记录下扇形中点所对应的弧度,开始绘制的第一个其实弧度加上扇形弧度的1/2
  float middleRadian = startRadian + radian / 2.0f;
  Vector2 point = new Vector2(Mathf.Cos(middleRadian),Mathf.Sin(middleRadian)) * radius;
  //这时我们还需要记录下它应该靠左显示还是靠右显示,所有相对于中心点(0,0)为正在右,反则在左。
2.2 折线的绘制应该在扇形弧度的中间值处取一点(就是在2.1中获取的中点),然后在同一方向的某个距离上取的第二个点,然后在第二个点的同一水平线上取第三个点来绘制折线
  Vector2 secondPoint = new Vector2(Mathf.Cos(middleRadian),Mathf.Sin(middleRadian)) * (radius + brokenLineLenght);
  //第三个点可以根据是在左侧或者是右侧直接水平挪动一定的值即可,比如在右侧
  Vector2 thridPoint = secondPoint + new Vector2(extralenght,0);
  //同理三个点,两两绘制直线即可
2.3 文字自适应的方法在函数图篇中已经讲解过,方法在代码中也有,不在赘述。

拓展方向:

   在这个工具做完之后我才思考过一个问题,这样做出的来的饼图暂时还不能和鼠标直接发生交互,但是如果我们想要更加炫酷的效果,比如鼠标移动到某一个扇形上,扇形变大显示等就没法实现吗?博主在后续的文章会提出可行的解决方案,希望大家也能够参与进来一起思考,看看大家有什么更好的想法。
好了以后的博文就不会像之前的博文一样把所有的源代码全部粘贴进去了,以后会只针对关键部分用伪代码进行简单的讲解,如果能够看懂,希望可以自己先手动编写,当然也可以下载我的全部源码。

下载链接

1.CSDN下载:

http://download.csdn.net/detail/qq_29579137/9835230

2.GitHub下载:

https://github.com/ll4080333

3.CSDN博客:

http://blog.csdn.net/qq_29579137

如果你觉我的文章有可用之处,欢迎点赞,如果有不足,欢迎评论留言并指出。关注我的博客第一时间获取后续更新内容。

==转载表明出处==

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!