可以使用网格 API 或矢量 API 将 2D 视觉内容生成到视觉元素上。
可以使用网格 API 来绘制自定义形状。网格 API 是高级用户的工具。如果只想生成简单的几何体,请改用矢量 API。矢量 API 受 HTML 画布的启发,绘制 2D 矢量图形,例如线条、弧形和形状。
要使用网格 API,请使用 MeshGenerationContext.Allocate 方法分配网格,然后填充顶点和索引。MeshGenerationContext.Allocate 方法将分配并绘制指定数量的顶点和索引,这些顶点和索引是表达几何体以绘制视觉元素内容所需的。有关几何体生成惯例的详细信息,请参阅 Vertex.position。
以下代码片段将生成单个四边形。它将分配顶点和索引,并提供顺时针方向的坐标:
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);
}
}
要使用矢量 API,请从 MeshGenerationContext 访问 Painter2D 对象并使用它生成路径。然后,可以使用 Stroke 绘制线条或使用 Fill 绘制形状。
要构建路径,需要发出命令来移动一种“虚拟笔”。例如,要生成网格 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:绘制一条射线,从该点向无限远的任何方向延伸,然后检查形状的一段与射线相交的位置。从计数 0 开始,每次路径段从左到右穿过射线时都加一。每次路径段从右到左穿过射线时减一。计算交叉点后,如果结果为零,则点在路径之外。否则,在路径之内。以下代码片段会创建一个带有菱形孔的矩形:
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);