SwiftUI:创建自定义路径 Path
绘图:简介
在这个技术项目中,我们将仔细研究SwiftUI中的绘图,包括创建自定义路径和形状,为您的更改添加动画效果,解决性能问题等,这是一个非常重要的主题,值得密切关注。
在幕后,SwiftUI使用了与其他Apple框架相同的绘图系统:Core Animation
和Metal
。大多数时候,Core Animation
负责我们的绘图,无论是自定义的路径和形状还是UI元素(例如TextField
),但是当事情变得复杂时,我们可以移至Metal
– Apple的底层框架,该框架针对复杂的绘图进行了优化。SwiftUI的简洁功能之一是这两者几乎可以互换:我们可以做一个小小的改动就可以从Core Animation
迁移到Metal
。
无论如何,我们有很多工作要做,因此请创建一个名为“绘图”的新Single View App项目,让我们深入了解...
路径 Path
SwiftUI为我们提供了一种专用的Path
类型,用于绘制自定义形状。这是一个非常低的级别,我的意思是您通常会希望将其包装在其他内容中以使其更有用,但是由于它是其他工作的基础,我们将从它开始。
就像颜色,渐变和形状一样,路径本身就是视图。这意味着我们可以像使用文本视图和图像一样使用它们,尽管您会看到它们有些笨拙。
让我们从一个简单的形状开始:绘制一个三角形。有几种创建路径的方法,包括一种接受闭包绘图指令的方法。此闭包必须接受单个参数,这是绘制的路径。我意识到一开始这可能有点费劲,因为我们正在创建路径,并且在该路径的初始值设定项内通过绘制的路径来传递,但是可以这样想:SwiftUI正在创建一个空的路径,然后让我们有机会根据需要添加更多内容。
路径有很多创建带有正方形,圆形,弧形和直线形的形状的方法。对于我们的三角形,我们需要移动到起始位置,然后添加如下三行:
var body: some View {
Path { path in
path.move(to: CGPoint(x: 200, y: 100))
path.addLine(to: CGPoint(x: 100, y: 300))
path.addLine(to: CGPoint(x: 300, y: 300))
path.addLine(to: CGPoint(x: 200, y: 100))
}
}
我们以前没有使用过CGPoint
,但是我确实在项目6中快速浏览了CGSize
。“ CG”是Core Graphics的缩写,它提供了一些基本类型,可以让我们引用X / Y坐标(CGPoint
),宽度和高度(CGSize
),矩形框(CGRect
)以及浮点数(CGFloat
)。
当我们的三角形代码运行时,您会看到一个大的黑色三角形。相对于屏幕的位置取决于您使用的模拟器,这是这些原始路径问题的一部分:我们需要使用精确的坐标,因此,如果您想单独使用路径,则需要接受在所有设备上调整大小,或使用GeometryReader
之类的内容相对于容器缩放它们。
我们将在短期内寻找更好的选择,但首先让我们着眼于为路径涂上颜色。一种选择是使用fill()
修饰符,如下所示:
Path { path in
path.move(to: CGPoint(x: 200, y: 100))
path.addLine(to: CGPoint(x: 100, y: 300))
path.addLine(to: CGPoint(x: 300, y: 300))
path.addLine(to: CGPoint(x: 200, y: 100))
}
.fill(Color.blue)
我们还可以使用stroke()
修饰符在路径周围进行绘制,而不用填充它:
不过,这看起来不太正确——三角形的底角很好看而且很锐利,但顶角已损坏。之所以会这样,是因为SwiftUI确保线与前后的线连接整齐,而不仅仅是一系列单独的线,但是我们的最后一行之后没有任何内容,因此无法建立连接。
解决此问题的一种方法是再次绘制第一条线,这意味着最后一条线具有一条与之匹配的连接线:
Path { path in
path.move(to: CGPoint(x: 200, y: 100))
path.addLine(to: CGPoint(x: 100, y: 300))
path.addLine(to: CGPoint(x: 300, y: 300))
path.addLine(to: CGPoint(x: 200, y: 100))
path.addLine(to: CGPoint(x: 100, y: 300))
}
.stroke(Color.blue, lineWidth: 10)
如您所见,这很棒。而且它甚至还可以很好地与透明度配合使用:如果使用透明的笔触颜色(例如Color.blue.opacity(0.25))
,那么您会看到整个笔划均匀地褪色,而在第一行中没有看到任何双笔划。
一种替代方法是使用SwiftUI的专用ShapeStyle
结构体,该结构体使我们可以控制每条线在其后应如何连接到该线(线连接 line join),以及如何在结束后没有连接的情况下绘制每条线(线帽 line cap)。这是特别有用的,因为用于连接和盖帽的选项之一是.round
,它会创建柔和的圆形形状:
.stroke(Color.blue, style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
有了该位置,您就可以从我们的路径中删除多余的行,因为不再需要它。
使用圆角可以解决粗糙边缘的问题,但不能解决固定坐标的问题。为此,我们需要继续前进,并研究更复杂的事物:形状。
Moonshot 项目挑战 | Hacking with iOS: SwiftUI Edition | SwiftUI:路径 Path vs 形状 Shape |
---|
赏我一个赞吧~~~