Unity雷达图

本文介绍了如何在Unity中利用MaskableGraphic和OnPopulateMesh方法创建自定义的雷达图,通过数组存储数据并动态调整,包括顶点计算、描边效果的实现,适用于游戏或数据分析可视化。
摘要由CSDN通过智能技术生成

雷达图的定义:雷达图是以从同一点开始的轴上表示的三个或更多个定量变量的二维图表的形式显示多变量数据的图形方法

想要实现雷达图的效果的话,需要先了解一下MaskableGraphic

MaskableGraphic的意思是可屏蔽图形

MaskableGraphic继承于UI.Graphic,作用是:是在Graphic的基础上实现剪裁和遮罩功能

先通过创建Image并且把Image上的Image组件移除掉,并且创建雷达图脚本,通过重写

 OnPopulateMesh方法来实现雷达图效果

    public float[] rs = new float[5];
 protected override void OnPopulateMesh(VertexHelper vh)
 {
        if (rs.Length>=3)
        {
            Rect rect = this.rectTransform.rect;
            vh.Clear();
            //获取数组中的最大值
            float max = rs.Max();
            float p = rect.width < rect.height ? rect.width / 2 / max : rect.height / 2 /max;
            float ang = 2 * Mathf.PI / rs.Length;
            vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));
            for (int i = 0; i < rs.Length; i++)
            {
                float x = Mathf.Sin(ang * i) * rs[i] * p;
                float y = Mathf.Cos(ang * i) * rs[i] * p;
                float uvx = (x + rect.width / 2) / rect.width;
                float uvy = (y + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x, y), color, new Vector2(uvx, uvy));
                if (i == 0)
                {
                    vh.AddTriangle(0, rs.Length, 1);

                }
                else
                {
                    vh.AddTriangle(0, i, i + 1);
                }
            }
       }
}

这里的数组rs是储存每个顶点的信息,通过这个数组里的每一个数据累计算每个角的弧度

这里的maxp这两个变量是用来计算最大值和矩形较长边的比值

然后再循环中计算x和y坐标的时候乘以这个比值,这样可以避免绘制的超出ui范围的问题

之后还有控制随机值,因为在游戏中的数据也会改变

 protected override void Awake()
    {
        rs = new float[5] { 200, 200, 200, 200, 200 };
        if (but != null)
        {
            but.onClick.AddListener(() =>
            {
                for (int i = 0; i < 5; i++)
                {
                    rs[i] = Random.Range(1, 200);
                }
                SetVerticesDirty();
            });
        }
    }

这样就可以控制数据的随机了,效果如下:

数据如下

最后再加一些描边的效果、

  public Color wcolor = Color.red;
  public float ww = 30f;
//使用过的顶点数量
            int next = rs.Length + 1;
            //描边
            for (int i = 0; i < rs.Length; i++)
            {
                float x0 = Mathf.Sin(i * ang) * (rs[i] * p - ww);
                float y0 = Mathf.Cos(i * ang) * (rs[i] * p - ww);
                float uvx0 = (x0 + rect.width / 2) / rect.width;
                float uvy0 = (y0 + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x0, y0, 0), wcolor, new Vector2(uvx0, uvy0));


                float x = Mathf.Sin(i * ang) * (rs[i] * p);
                float y = Mathf.Cos(i * ang) * (rs[i] * p);
                float uvx = (x + rect.width / 2) / rect.width;
                float uvy = (y + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x, y, 0), wcolor, new Vector2(uvx, uvy));
                if (i == rs.Length - 1)
                {
                    vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, 1 + next);
                    vh.AddTriangle(i * 2 + next, 1 + next, next);
                }
                else
                {
                    vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, (i + 1) * 2 + 1 + next);
                    vh.AddTriangle(i * 2 + next, (i + 1) * 2 + 1 + next, (i + 1) * 2 + next);
                }
            }

全部代码如下:

 public Sprite activeSprite;

    public float[] rs = new float[5];

    public float ww = 30f;

    public Color wcolor = Color.red;

    public Button but;



    protected override void Awake()
    {
        rs = new float[5] { 200, 200, 200, 200, 200 };
        if (but != null)
        {
            but.onClick.AddListener(() =>
            {
                for (int i = 0; i < 5; i++)
                {
                    rs[i] = Random.Range(1, 200);
                }
                SetVerticesDirty();
            });
        }
    }
    public override Texture mainTexture
    {
        get
        {
            if (activeSprite == null)
            {
                if (material != null && material.mainTexture != null)
                {
                    return material.mainTexture;
                }
                return s_WhiteTexture;
            }

            return activeSprite.texture;
        }
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        if (rs.Length >= 3)
        {
            Rect rect = this.rectTransform.rect;
            vh.Clear();
            //获取数组中的最大值
            float max = rs.Max();
            float p = rect.width < rect.height ? rect.width / 2 / max : rect.height / 2 / max;
            float ang = 2 * Mathf.PI / rs.Length;
            vh.AddVert(Vector3.zero, color, new Vector2(0.5f, 0.5f));
            for (int i = 0; i < rs.Length; i++)
            {
                float x = Mathf.Sin(ang * i) * rs[i] * p;
                float y = Mathf.Cos(ang * i) * rs[i] * p;
                float uvx = (x + rect.width / 2) / rect.width;
                float uvy = (y + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x, y), color, new Vector2(uvx, uvy));
                if (i == 0)
                {
                    vh.AddTriangle(0, rs.Length, 1);

                }
                else
                {
                    vh.AddTriangle(0, i, i + 1);
                }
            }
            //使用过的顶点数量
            int next = rs.Length + 1;
            //描边
            for (int i = 0; i < rs.Length; i++)
            {
                float x0 = Mathf.Sin(i * ang) * (rs[i] * p - ww);
                float y0 = Mathf.Cos(i * ang) * (rs[i] * p - ww);
                float uvx0 = (x0 + rect.width / 2) / rect.width;
                float uvy0 = (y0 + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x0, y0, 0), wcolor, new Vector2(uvx0, uvy0));


                float x = Mathf.Sin(i * ang) * (rs[i] * p);
                float y = Mathf.Cos(i * ang) * (rs[i] * p);
                float uvx = (x + rect.width / 2) / rect.width;
                float uvy = (y + rect.height / 2) / rect.height;
                vh.AddVert(new Vector3(x, y, 0), wcolor, new Vector2(uvx, uvy));
                if (i == rs.Length - 1)
                {
                    vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, 1 + next);
                    vh.AddTriangle(i * 2 + next, 1 + next, next);
                }
                else
                {
                    vh.AddTriangle(i * 2 + next, i * 2 + 1 + next, (i + 1) * 2 + 1 + next);
                    vh.AddTriangle(i * 2 + next, (i + 1) * 2 + 1 + next, (i + 1) * 2 + next);
                }
            }

        }
    }

这样就可以做出基础的雷达图效果了

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值