雷达图是游戏中常见的图表表现之一,比如用来呈现英雄的属性等等,本文将在 Unity 中实现一个带均匀描边、可响应点击的雷达图。
Graphic类
Unity 的原生 UI 系统 UGUI 提供了名为 Graphic 的基类用于实现各自 UI组件的。该类中有名为 OnPopulateMesh 的方法,只要向参数 VertexHelper 传递正确的顶点数组与下标数组,即可构造出我们期望的网格。
网格的构建
雷达图可视为一个正多边形,每个顶点沿径向缩放得到。因此,我们只需要遍历每个角度,并根据当前角度的权重计算出相应的顶点。最后,我们可以构造下标数组来获得所需的网格。构造顶点代码如下
这样对于边数为 N 的雷达图,我们会得到包括中心点在内的 N 1 个顶点,然后是构造下标数组,代码如下。
这只是一个简单的方法,结合两个相邻的顶点与中心点形成一个三角形。注意,第一个顶点在这里被重用。
响应点击
Unity 的 UI 组件,响应点击需要实现接口 ICanvasRaycastFilter 的 IsRaycastLocationValid 方法。如果命中多边形,也就是点击坐标落在多边形内,则返回 true ,否则返回 false。首先需要将方法参数里的屏幕坐标转换到ui的局部坐标。
然后我们检测坐标是否落在多边形中。对于我们单击的坐标,我们检测到一条指向多边形外部顶点的光线从它发出。对于多边形的每一条边,我们检测它是否相交。最后,我们计算相交边的数量。如果是奇数,则表示该点落在多边形中,否则落在多边形外。有关详细信息,请参阅以下问题。
如何判断一个点是在一个有自交线的封闭图的内部还是外部?
代码如下
做完这些就实现了一个可响应点击的雷达图了。
一开始觉得这就不算个问题,搞两个权重一样但是半径不一样的雷达图不就能实现了嘛。试了试发现,问题没有这么简单。
因为权重不均匀,所以会导致描边也不均匀,为了实现均匀的描边,还需要额外的工作。
解决办法是额外进行边的绘制。对于多边形的每一个顶点 C ,我们按逆时针方向找出它的上一个 A 与下一个顶点 B ,并且得到它相邻的两条边的向外的垂线,把 A 与 B 沿着垂线向外延伸得到 E 与 F,把 E 与 F 沿着边的方向延伸,相交于点 P,对每个顶点重复上述步骤,就能得到外框的所有点了。
顶点构造代码
下标数组构造
获得交点
获得垂线
最后看效果
网上 Unity 实现 雷达图的代码能找到不少,但是我发现基本都止步于网格的构造,并没有将点击响应的计算以及均匀描边的实现,有的更过分,甚至连 uv 都不肯算,没办法只能自己撸一个,把一些中学几何的东西又捡起来过了一遍,总的来说,这个过程还是有所收获的。
转载声明:本文来源于网络,不作任何商业用途。
IOS下载
安卓下载
小程序