您可以使用 Mesh API 或 Vector API 在视觉元素上生成 2D 视觉内容。
您可以使用 Mesh API 绘制自定义形状。 Mesh API 是一个面向高级用户的工具。如果您只想生成简单的几何图形,请改用 Vector API。受到 HTML Canvas 的启发,Vector API 绘制 2D 矢量图形,例如线条、弧线和形状。
要使用 Mesh API,请使用 MeshGenerationContext.Allocate
方法分配网格,然后填充顶点和索引。 MeshGenerationContext.Allocate
方法分配并绘制指定数量的顶点和索引,这些顶点和索引是用来表示视觉元素内容的几何图形的。有关几何图形生成约定的详细信息,请参阅 Vertex.position。
以下代码片段生成一个单个 quad。它分配顶点和索引,并按顺时针方向提供坐标
class QuadMeshElement : VisualElement
{
public Color color = Color.red;
public QuadMeshElement()
{
generateVisualContent += OnGenerateVisualContent;
}
void OnGenerateVisualContent(MeshGenerationContext mgc)
{
var mesh = mgc.Allocate(4, 6);
var p0 = Vector2.zero;
var p1 = new Vector2(layout.width, 0);
var p2 = new Vector2(layout.width, layout.height);
var p3 = new Vector2(0, layout.height);
mesh.SetNextVertex(new Vertex() { position = new Vector3(p0.x, p0.y, Vertex.nearZ), tint = color });
mesh.SetNextVertex(new Vertex() { position = new Vector3(p1.x, p1.y, Vertex.nearZ), tint = color });
mesh.SetNextVertex(new Vertex() { position = new Vector3(p2.x, p2.y, Vertex.nearZ), tint = color });
mesh.SetNextVertex(new Vertex() { position = new Vector3(p3.x, p3.y, Vertex.nearZ), tint = color });
mesh.SetNextIndex(0);
mesh.SetNextIndex(1);
mesh.SetNextIndex(2);
mesh.SetNextIndex(0);
mesh.SetNextIndex(2);
mesh.SetNextIndex(3);
}
}
要使用 Vector API,请从 MeshGenerationContext
中访问 Painter2D
对象,并用它生成路径。然后,您可以使用 Stroke
绘制线条,或使用 Fill
绘制形状。
要构建路径,您发出移动一种“虚拟笔”的命令。例如,要生成 Mesh API 示例中的相同四边形,请将“笔”移动到第一个位置,并将线条链接在一起。完成路径后,使用 Fill
来构建形状。
class QuadVectorElement : VisualElement
{
public Color color = Color.red;
public QuadVectorElement()
{
generateVisualContent += OnGenerateVisualContent;
}
void OnGenerateVisualContent(MeshGenerationContext mgc)
{
var p0 = Vector2.zero;
var p1 = new Vector2(layout.width, 0);
var p2 = new Vector2(layout.width, layout.height);
var p3 = new Vector2(0, layout.height);
var painter2D = mgc.painter2D;
painter2D.fillColor = color;
painter2D.BeginPath();
painter2D.MoveTo(p0);
painter2D.LineTo(p1);
painter2D.LineTo(p2);
painter2D.LineTo(p3);
painter2D.ClosePath();
painter2D.Fill();
}
}
LineTo
方法从当前笔位置到提供的笔位置生成一条直线。在绘制线条之前,请定义属性,例如笔划颜色、线条宽度、连接和端点。
在绘制线条时,LineJoin
和 LineCap
的属性控制线条连接和端点的样式。
下图说明了不同样式的线条端点和连接
以下代码片段绘制一条锯齿线
painter2D.lineWidth = 10.0f;
painter2D.strokeColor = Color.white;
painter2D.lineJoin = LineJoin.Round;
painter2D.lineCap = LineCap.Round;
painter2D.BeginPath();
painter2D.MoveTo(new Vector2(100, 100));
painter2D.LineTo(new Vector2(120, 120));
painter2D.LineTo(new Vector2(140, 100));
painter2D.LineTo(new Vector2(160, 120));
painter2D.LineTo(new Vector2(180, 100));
painter2D.LineTo(new Vector2(200, 120));
painter2D.LineTo(new Vector2(220, 100));
painter2D.Stroke();
您可以使用以下方法绘制弧线
以下代码片段使用 Arc
绘制一个带有边框的扇形
painter2D.lineWidth = 2.0f;
painter2D.strokeColor = Color.red;
painter2D.fillColor = Color.blue;
painter2D.BeginPath();
// Move to the arc center
painter2D.MoveTo(new Vector2(100, 100));
// Draw the arc, and close the path
painter2D.Arc(new Vector2(100, 100), 50.0f, 10.0f, 95.0f);
painter2D.ClosePath();
// Fill and stroke the path
painter2D.Fill();
painter2D.Stroke();
以下代码片段使用 ArcTo
在线条拐角处绘制一个所需半径的弧线
painter2D.BeginPath();
painter2D.MoveTo(new Vector2(100, 100));
painter2D.ArcTo(new Vector2(150, 150), new Vector2(200, 100), 20.0f);
painter2D.LineTo(new Vector2(200, 100));
painter2D.Stroke();
您可以使用以下方法绘制曲线
BezierCurveTo
方法使用两个控制点和三次贝塞尔曲线的最终位置生成一条三次贝塞尔曲线。QuadraticCurveTo
方法使用一个控制点和二次贝塞尔曲线的最终位置生成一条二次贝塞尔曲线。以下代码片段使用 BezierCurveTo
绘制一条贝塞尔曲线
painter2D.BeginPath();
painter2D.MoveTo(new Vector2(100, 100));
painter2D.BezierCurveTo(new Vector2(150, 150), new Vector2(200, 50), new Vector2(250, 100));
painter2D.Stroke();
以下代码片段使用 QuadraticCurveTo
绘制一条二次曲线
painter2D.BeginPath();
painter2D.MoveTo(new Vector2(100, 100));
painter2D.QuadraticCurveTo(new Vector2(150, 150), new Vector2(250, 100));
painter2D.Stroke();
在进行 Fill
时,您可以构建具有孔的路径。当您调用 MoveTo
时,它将启动一条新的子路径。要创建孔,请使用 填充规则 将各种子路径相互重叠。
填充规则 确定如何填充形状内部
OddEven
:从该点向无限远处画一条射线,并计算该射线穿过给定形状的路径段数。如果这个数字是奇数,则该点在内部;如果是偶数,则该点在外部。NonZero
:从该点向无限远处画一条射线,然后检查形状的段与射线相交的位置。从零开始计数,每当路径段从左到右穿过射线时加一。每当路径段从右到左穿过射线时减一。计算完交叉点后,如果结果为零,则该点在路径外部。否则,它在内部。以下代码片段创建一个矩形,其中有一个菱形孔
painter2D.BeginPath();
painter2D.MoveTo(new Vector2(10, 10));
painter2D.LineTo(new Vector2(300, 10));
painter2D.LineTo(new Vector2(300, 150));
painter2D.LineTo(new Vector2(10, 150));
painter2D.ClosePath();
painter2D.MoveTo(new Vector2(150, 50));
painter2D.LineTo(new Vector2(175, 75));
painter2D.LineTo(new Vector2(150, 100));
painter2D.LineTo(new Vector2(125, 75));
painter2D.ClosePath();
painter2D.Fill(FillRule.OddEven);