Unity-微信截图功能简单复刻-03绘制空心矩形

思路-绘制空心矩形

拓展UGUI的Graphic类,实现拖拽接口。

开始拖拽时记录鼠标位置,

使用拖拽中的鼠标位置和记录的位置,计算矩形顶点,绘制矩形。

两个三角形合并为一个矩形,作为空心矩形的一条边,四个边合并为空心矩形。

示例-绘制空心矩形

csharp 复制代码
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class TestDraw : Graphic, IBeginDragHandler, IDragHandler, IEndDragHandler
{
    UIVertex[] rectangle1 = new UIVertex[4];
    UIVertex[] rectangle2 = new UIVertex[4];
    UIVertex[] rectangle3 = new UIVertex[4];
    UIVertex[] rectangle4 = new UIVertex[4];

    [SerializeField] float width = 5f;

    Vector3 lastPoint;

    protected override void Awake()
    {
        Init(rectangle1);
        Init(rectangle2);
        Init(rectangle3);
        Init(rectangle4);
        void Init(UIVertex[] uIVertices)
        {
            var length = uIVertices.Length;
            for (int i = 0; i < length; i++)
                uIVertices[i] = new UIVertex();
        }
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddUIVertexQuad(rectangle1);
        vh.AddUIVertexQuad(rectangle2);
        vh.AddUIVertexQuad(rectangle3);
        vh.AddUIVertexQuad(rectangle4);
    }

    public void ClearDraw()
    {
        Clear(rectangle1);
        Clear(rectangle2);
        Clear(rectangle3);
        Clear(rectangle4);
        void Clear(UIVertex[] uIVertices)
        {
            var length = uIVertices.Length;
            for (int i = 0; i < length; i++)
                uIVertices[i].position = Vector3.zero;
        }
        SetVerticesDirty();
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        lastPoint = ScreenPointToLocalPoint(rectTransform, eventData.position);
    }

    public void OnDrag(PointerEventData eventData)
    {
        Vector3 point = ScreenPointToLocalPoint(rectTransform, eventData.position);

        if (lastPoint.x < point.x && lastPoint.y < point.y)//起点在左下角
        {
            //水平方向投影向量           
            var horizontalNormal = Vector3.Project(point - lastPoint, Vector3.right);
            SetRectangleVertex(point - horizontalNormal, point, lastPoint + horizontalNormal, lastPoint);
            SetRectangleColor(color);
            SetVerticesDirty();
        }
        else if (lastPoint.x > point.x && lastPoint.y > point.y)//起点在右上角
        {
            var horizontalNormal = Vector3.Project(point - lastPoint, Vector3.right);
            SetRectangleVertex(lastPoint + horizontalNormal, lastPoint, point - horizontalNormal, point);
            SetRectangleColor(color);
            SetVerticesDirty();
        }
        else if (lastPoint.x > point.x && lastPoint.y < point.y)//起点在右下角
        {
            var horizontalNormal = Vector3.Project(point - lastPoint, Vector3.right);
            SetRectangleVertex(point, point - horizontalNormal, lastPoint, lastPoint + horizontalNormal);
            SetRectangleColor(color);
            SetVerticesDirty();
        }
        else if (lastPoint.x < point.x && lastPoint.y > point.y)//起点在左上角
        {
            var horizontalNormal = Vector3.Project(point - lastPoint, Vector3.right);
            SetRectangleVertex(lastPoint, lastPoint + horizontalNormal, point, point - horizontalNormal);
            SetRectangleColor(color);
            SetVerticesDirty();
        }
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        lastPoint = Vector3.zero;
    }

    void SetRectangleVertex(Vector3 topLeftUp, Vector3 topRigthUp, Vector3 bottomRightDown, Vector3 bottomLeftDown)
    {
        //top矩形
        rectangle1[0].position = topLeftUp;
        rectangle1[1].position = topRigthUp;
        rectangle1[2].position = topRigthUp - Vector3.up * width;
        rectangle1[3].position = topLeftUp - Vector3.up * width;

        //bottom矩形
        rectangle2[0].position = bottomRightDown;
        rectangle2[1].position = bottomLeftDown;
        rectangle2[2].position = bottomLeftDown + Vector3.up * width;
        rectangle2[3].position = bottomRightDown + Vector3.up * width;

        //left矩形
        rectangle3[0].position = topLeftUp - Vector3.up * width;
        rectangle3[1].position = topLeftUp - Vector3.up * width + Vector3.right * width;
        rectangle3[2].position = bottomLeftDown + Vector3.up * width + Vector3.right * width;
        rectangle3[3].position = bottomLeftDown + Vector3.up * width;

        //right矩形
        rectangle4[0].position = topRigthUp - Vector3.up * width;
        rectangle4[1].position = bottomRightDown + Vector3.up * width;
        rectangle4[2].position = bottomRightDown + Vector3.up * width - Vector3.right * width;
        rectangle4[3].position = topRigthUp - Vector3.up * width - Vector3.right * width;
    }

    void SetRectangleColor(Color color)
    {
        var length = rectangle1.Length;
        for (int i = 0; i < length; i++)
            rectangle1[i].color = color;
        length = rectangle2.Length;
        for (int i = 0; i < length; i++)
            rectangle2[i].color = color;
        length = rectangle3.Length;
        for (int i = 0; i < length; i++)
            rectangle3[i].color = color;
        length = rectangle4.Length;
        for (int i = 0; i < length; i++)
            rectangle4[i].color = color;
    }

    Vector2 ScreenPointToLocalPoint(RectTransform rect, Vector2 mousePoint)
    {
        Vector2 result = Vector2.zero;
        switch (canvas.renderMode)
        {
            case RenderMode.ScreenSpaceOverlay:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, mousePoint, null, out result);
                break;
            case RenderMode.ScreenSpaceCamera:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, mousePoint, canvas.worldCamera, out result);
                break;
            case RenderMode.WorldSpace:
                RectTransformUtility.ScreenPointToLocalPointInRectangle(rect, mousePoint, canvas.worldCamera, out result);
                break;
        }
        return result;
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
            ClearDraw();
    }
}

场景结构

TestDraw对象挂载TestDraw脚本,该对象需要CanvsRenderer脚本,大小为屏幕大小

运行结果

上方为矩形网格

运行,拖拽鼠标显示矩形。

按下空格键,清除矩形。

知识点

三角形的绘制需要三个顶点,三角形使用顺时针的顺序进行绘制。

其他几何图形的绘制思路

线:多个矩形组合而成

箭头:一个三角形,一个矩形组合而成。

空心椭圆:获取两个圆上的顶点,按照顺序绘制三角形。

椭圆绘制思路:已知圆心,半径

将圆划分多份,利用三角函数和弧度获取x坐标,y坐标。

将x,y坐标缩放,可得到椭圆上的点。

相关推荐
SmalBox16 小时前
【光照】[漫反射diffuse]以UnityURP为例
unity·渲染
SmalBox2 天前
【光照】[自发光Emission]以UnityURP为例
unity·渲染
睫毛上长雀斑2 天前
jsApi支付+h5支付
微信
SmalBox3 天前
【光照】Unity中的[经验模型]
unity·渲染
萘柰奈3 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
Yasin Chen3 天前
Unity UI坐标说明
ui·unity
应用市场3 天前
无人机姿态控制系统详解与实现
游戏引擎·cocos2d
陈言必行3 天前
Unity 性能优化 之 编辑器创建资源优化( 工作流 | 场景 | 预制体)
unity·编辑器·游戏引擎
1uther3 天前
Unity核心概念⑨:Screen
开发语言·游戏·unity·c#·游戏引擎
死也不注释3 天前
【Unity UGUI 交互组件——Slider(7)】
unity·游戏引擎·交互