SwiftUI为我们提供了很多种图形的绘制,各个形状没有什么特别的地方,只需要根据文档中的构造函数进行初始化就好了, 形状会尽量充满父视图给予的空间,所以可以通过调整父视图或者 .frame 之类的,方式调整他们的形状和尺寸。
SwiftUI为我们提供了五个常用的内置形状:矩形,圆角矩形,圆形,椭圆形和胶囊形。根据提供的尺寸,最后三个尤其在行为上有细微的差别,但是我们可以通过一个示例来演示所有选项:
Capsule()//胶囊型:是一种特殊的圆角矩形,其圆角的半径等于变长的一半
Circle()//圆形
Ellipse()//椭圆
Rectangle()//长方形
RoundedRectangle(cornerRadius: 25.0)//圆角矩形
RoundedRectangle(cornerSize: CGSize(width: 25, height: 50))//椭圆角矩形
或者对其进行修改:
ZStack {
Rectangle()
.fill(Color.black)
.frame(width: 200, height: 200)
RoundedRectangle(cornerRadius: 25, style: .continuous)
.fill(Color.red)
.frame(width: 200, height: 200)
Capsule()
.fill(Color.green)
.frame(width: 100, height: 50)
Ellipse()
.fill(Color.blue)
.frame(width: 100, height: 50)
Circle()
.fill(Color.white)
.frame(width: 100, height: 50)
}
绘制所有五个形状:两个以200x200绘制,三个以100x50绘制。但是,由于形状的绘制行为不同,因此您会在输出中看到所有五个形状:
为了统一说明,先定义一个可以对图形进行美化的视图结构:
struct ShapeWithLabel: View where Content: View {
let shape: Content //传入图形
let label: String //图形的名字显示
var body: some View {
VStack {
Text(label)
shape
.foregroundColor(.blue)//图形统一设置为蓝色
}
.frame(height: 100)
.padding()
}
}
下面就可以使用表格排列图片显示了:
LazyVGrid(columns: [GridItem(.adaptive(minimum: 100, maximum: 200))]) {
ShapeWithLabel(shape: Capsule(), label: "胶囊型")
ShapeWithLabel(shape: Circle(), label: "圆形")
ShapeWithLabel(shape: Ellipse(), label: "椭圆")
ShapeWithLabel(shape: Rectangle(), label: "长方形")
ShapeWithLabel(shape: RoundedRectangle(cornerRadius: 25.0), label: "圆角矩形")
ShapeWithLabel(shape: RoundedRectangle(cornerSize: CGSize(width: 25, height: 50)), label: "椭圆角矩形")
}
SwiftUI启用具有两种不同类型的自定义绘图:路径和形状。路径是一系列绘制指令,例如“从此处开始,在此处绘制线,然后在此处添加圆”,所有这些指令均使用绝对坐标。相反,形状不知道将在何处使用或将使用多大的形状,而是会要求其在给定的矩形内绘制自身。
有用的是,形状是使用路径构建的,因此一旦了解路径,形状就很容易。而且,就像路径,颜色和渐变一样,形状也是视图,这意味着我们可以将它们与文本视图,图像等一起使用。
SwiftUIShape使用一个必需的方法作为协议来实现:给定以下矩形,您想绘制什么路径?这仍然会像直接使用原始路径一样创建并返回路径,但是由于我们已经掌握了尺寸,因此将使用形状,因为我们确切知道绘制路径的大小–我们不再需要依赖固定的坐标。
例如,以前我们使用来创建了一个三角形Path,但是我们可以将其包装成一个形状以确保它自动占用所有可用空间,如下所示:
//遵循Shape协议就可以画一个三角形
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)
或者:
ShapeWithLabel(shape: Triangle(), label: "三角形")
理解之间的区别的关键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)
如果您查看我们弧线的预览,很可能它看起来并不像您期望的那样。我们要求顺时针旋转的弧度是从0度到110度,但逆时针旋转的弧度似乎是从90度到200度。
这里发生了两件事:
我们可以使用一种新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
}
充分利用路径可以画出很多漂亮的图标,SVG也是通过这样的方式实现图标渲染的。
除非注明,网络人的文章均为原创,转载请以链接形式标明本文地址:https://www.55mx.com/post/131
《【SwiftUI基础篇】17 各种形状 Circle 圆形、Rectangle矩形、Capsule胶囊形等》的网友评论(0)