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坐标缩放,可得到椭圆上的点。

相关推荐
死也不注释7 小时前
【第零章编辑器开发与拓展】
unity·编辑器
死也不注释8 小时前
【第一章编辑器开发基础第二节编辑器布局_3GUI元素和布局大小(3/4)】
unity·编辑器
Kiri霧15 小时前
细谈kotlin中缀表达式
开发语言·微信·kotlin
KhalilRuan1 天前
Unity Demo-3DFarm详解-其二
unity·游戏引擎
死也不注释2 天前
【unity编辑器开发与拓展EditorGUILayoyt和GUILayoyt】
unity·编辑器·游戏引擎
红橙Darren2 天前
手写操作系统 - 环境搭建
android·微信·操作系统
Zillionnn2 天前
Unreal Engine 自动设置图像
游戏引擎·虚幻
3 天前
Unity开发中常用的洗牌算法
java·算法·unity·游戏引擎·游戏开发
陈思杰系统思考Jason3 天前
系统思考:多元胜过能力
百度·微信·微信公众平台·新浪微博·微信开放平台
马特说3 天前
Unity VR手术模拟系统架构分析与数据流设计
unity·系统架构·vr