在UI中画一条曲线
我封装了一个组件,可以实现基本的画线需求.
效果
按住鼠标左键随手一画.
用起来也很简单,将组件挂到空物体上就行了,红色的背景是Panel.
你可以将该组件理解为一个Image,只不过形状更灵活一些罢了,所以它要放在下面的层级(不然可能会被挡住).
代码
可以调整一些基本的属性,如线的颜色和粗细.
using System;
using UnityEngine.UI;
using UnityEngine;
using System.Collections.Generic;
using Unity.VisualScripting;
[RequireComponent(typeof(CanvasRenderer))] //需要该组件才能生效
public class UILineRenderer : Graphic
{
private readonly List<Vector2> points = new List<Vector2>(); // 用于存储线条的点
[SerializeField] private float lineWidth = 5f; // 线条宽度
[SerializeField] private Color lineColor = Color.white; // 默认线条颜色
//----用来测试,你应当使用自己的办法调用DrawLine方法,后续删除这部分-----
private List<Vector2> points1 = new List<Vector2>(); // 用于存储线条的点
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
points1.Clear();
}
else if (Input.GetMouseButton(0))
{
points1.Add(Input.mousePosition);
DrawLine(points1);
}
else if (Input.GetMouseButtonUp(0))
{
foreach (var VARIABLE in points1)
{
Debug.Log(VARIABLE);
}
}
}
//--------------------------------------------------------
// 每次需要重新绘制UI时调用
protected override void OnPopulateMesh(VertexHelper vh)
{
vh.Clear(); // 清空当前顶点数据
// 如果没有足够的点,则不绘制任何东西
if (points == null || points.Count < 2)
return;
// 遍历每个点,创建线段
for (int i = 0; i < points.Count - 1; i++)
{
Vector2 start = points[i];
Vector2 end = points[i + 1];
// 计算垂直方向的法线,使线条有宽度
Vector2 direction = (end - start).normalized;
Vector2 perpendicular = new Vector2(-direction.y, direction.x) * lineWidth / 2f;
// 四个顶点(左下、左上、右上、右下)
UIVertex vertex = UIVertex.simpleVert;
vertex.color = lineColor; // 定义颜色
// 左下
vertex.position = new Vector3(start.x - perpendicular.x, start.y - perpendicular.y);
vh.AddVert(vertex);
// 左上
vertex.position = new Vector3(start.x + perpendicular.x, start.y + perpendicular.y);
vh.AddVert(vertex);
// 右上
vertex.position = new Vector3(end.x + perpendicular.x, end.y + perpendicular.y);
vh.AddVert(vertex);
// 右下
vertex.position = new Vector3(end.x - perpendicular.x, end.y - perpendicular.y);
vh.AddVert(vertex);
// 添加两个三角形来组成矩形线条
int index = vh.currentVertCount;
vh.AddTriangle(index - 4, index - 3, index - 2);
vh.AddTriangle(index - 4, index - 2, index - 1);
}
}
public void DrawLine(List<Vector2> pointArray)
{
if (pointArray == null || pointArray.Count < 2) return;
List<Vector2> newPoints = new List<Vector2>();
foreach (Vector2 v2 in pointArray)
{
Vector2 localPoint;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
rectTransform, // 当前 UILineRenderer 的 RectTransform
v2,
null,
out localPoint // 输出的局部坐标
);
newPoints.Add(localPoint);
}
this.points.Clear();
this.points.AddRange(newPoints);
SetVerticesDirty();
}
/// <summary>
/// 设置线的颜色
/// </summary>
/// <param name="newColor"></param>
public void SetLineColor(Color newColor)
{
lineColor = newColor;
SetVerticesDirty();
}
/// <summary>
/// 设置线的宽带
/// </summary>
/// <param name="width"></param>
public void SetWidth(float width)
{
lineWidth = width;
SetVerticesDirty();
}
/// <summary>
/// 重置组件
/// </summary>
public void ResetSelf()
{
points.Clear();
lineColor = Color.white;
lineWidth = 5f;
SetVerticesDirty();
}
}