SwiftUI启用具有两种不同类型的自定义绘图:路径和形状。路径是一系列绘制指令,例如“从此处开始,在此处绘制线,然后在此处添加圆”,所有指令均使用绝对坐标。相反,形状不知道将在何处使用或将使用多大的形状,而是会要求其在给定的矩形内绘制自身。
有用的是,形状是使用路径构建的,因此一旦您了解了路径,形状就很容易了。同样,就像路径,颜色和渐变一样,形状也是视图,这意味着我们可以将它们与文本视图,图像等一起使用。
SwiftUI使用一个必需的方法将Shape作为协议实现:给定以下矩形,您想绘制什么路径?仍然会像直接使用原始路径一样创建并返回路径,但是由于我们已经掌握了大小,因此将使用形状,因为我们确切地知道绘制路径的大小——我们不再需要依赖固定的坐标。
例如,以前我们使用Path创建了一个三角形,但是我们可以将其包装成一个形状以确保它自动占用所有可用空间,如下所示:
struct Triangle: Shape { func path(in rect: CGRect) -> Path { var path = Path() path.move(to: CGPoint(x: rect.midX, y: rect.minY)) path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY)) path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY)) path.addLine(to: CGPoint(x: rect.midX, y: rect.minY)) return path } }CGRect使这项工作变得容易得多,它提供了有用的属性,例如minX(矩形中最小的X值),maxX(矩形中最大的X值)和midX(minX和maxX之间的中点)。
然后,我们可以创建一个精确尺寸的红色三角形,如下所示:
Triangle() .fill(Color.red) .frame(width: 300, height: 300)形状还支持相同的StrokeStyle参数,以创建更多高级笔触:
Triangle() .stroke(Color.red, style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round)) .frame(width: 300, height: 300)理解Path和Shape之间差异的关键是可重用性:路径被设计为做一件特定的事情,而形状具有绘制空间的灵活性,并且还可以接受参数以使我们进一步自定义它们。为了说明这一点,我们可以创建一个接受三个参数的圆弧(Arc)形状:起始角度,结束角度以及是否顺时针绘制圆弧。这看起来似乎很简单,尤其是因为Path具有addArc()方法,但是如您所见,它具有几个有趣的现象。
让我们从最简单的弧形开始:
struct Arc: Shape { var startAngle: Angle var endAngle: Angle var clockwise: Bool func path(in rect: CGRect) -> Path { var path = Path() path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: startAngle, endAngle: endAngle, clockwise: clockwise) return path } }我们现在可以像这样创建一个圆弧:
Arc(startAngle: .degrees(0), endAngle: .degrees(110), clockwise: true) .stroke(Color.blue, lineWidth: 10) .frame(width: 300, height: 300)SwiftUI 默认的 0° - 110° 圆弧如果您查看我们弧线的预览,很可能它看起来不像您期望的那样。我们要求顺时针旋转的弧度是从0度到110度,但是我们似乎获得了逆时针旋转从90度到200度的圆弧。
这里发生了两件事:
在SwiftUI看来,0度不是笔直向上,而是直接向右。形状是从左下角而不是左上角开始测量坐标的,这意味着SwiftUI从一个角度到另一个角度都以相反的方式进行测量。在我看来,这是非常陌生的。我们可以使用新的path(in :)方法解决这两个问题,该方法从起点和终点角度减去90度,并且还改变方向,以便SwiftUI遵循自然预期的方式:
func path(in rect: CGRect) -> Path { let rotationAdjustment = Angle.degrees(90) let modifiedStart = startAngle - rotationAdjustment let modifiedEnd = endAngle - rotationAdjustment var path = Path() path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: modifiedStart, endAngle: modifiedEnd, clockwise: !clockwise) return path }我们常用用的 0° - 110° 圆弧运行该代码并查看您的想法——对我来说,它产生了一种更自然的工作方式,并巧妙地隔离了SwiftUI的古怪绘画行为。
译自 Paths vs shapes in SwiftUI
---来自腾讯云社区的---韦弦zhy
微信扫一扫打赏
支付宝扫一扫打赏