SwiftUI:路径 Path vs 形状 Shape

SwiftUI:路径 Path vs 形状 Shape_第1张图片
Shape - Circle

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值)和midXminXmaxX之间的中点)。

然后,我们可以创建一个精确尺寸的红色三角形,如下所示:

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)
理解PathShape之间差异的关键是可重用性:路径被设计为做一件特定的事情,而形状具有绘制空间的灵活性,并且还可以接受参数以使我们进一步自定义它们。

为了说明这一点,我们可以创建一个接受三个参数的圆弧(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:路径 Path vs 形状 Shape_第2张图片
SwiftUI 默认的 0° - 110° 圆弧

如果您查看我们弧线的预览,很可能它看起来不像您期望的那样。我们要求顺时针旋转的弧度是从0度到110度,但是我们似乎获得了逆时针旋转从90度到200度的圆弧。

这里发生了两件事:

  1. 在SwiftUI看来,0度不是笔直向上,而是直接向右。
  2. 形状是从左下角而不是左上角开始测量坐标的,这意味着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
}
SwiftUI:路径 Path vs 形状 Shape_第3张图片
我们常用用的 0° - 110° 圆弧

运行该代码并查看您的想法——对我来说,它产生了一种更自然的工作方式,并巧妙地隔离了SwiftUI的古怪绘画行为。

译自 Paths vs shapes in SwiftUI

SwiftUI:创建自定义路径 Path Hacking with iOS: SwiftUI Edition SwiftUI:自定义 Shape 实现向内绘制边框

赏我一个赞吧~~~

你可能感兴趣的:(SwiftUI:路径 Path vs 形状 Shape)