在 SwiftUI 中,Path 是用于绘制自定义形状的基础组件。通过定义点和线的集合,可以创建复杂的矢量图形,如直线、曲线、矩形、圆形等。Path 是绘制自定义形状的核心工具,通常与 Shape 协同使用。
Path 的基本结构
Path 是一个结构体,可以通过以下几种方式构建路径:
1、手动构建路径
使用 Path 的构造函数添加点和线段,构建路径。
struct ContentView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 50, y: 50)) // 移动到起点
path.addLine(to: CGPoint(x: 200, y: 50)) // 添加一条线
path.addLine(to: CGPoint(x: 200, y: 200)) // 添加另一条线
path.closeSubpath() // 闭合路径
}
.stroke(Color.blue, lineWidth: 3) // 描边路径
}
}
效果:
一个蓝色的三角形路径。
2、内置形状辅助方法
Path 提供了许多简化绘制常见形状的方法,例如矩形、圆弧等。
struct ContentView: View {
var body: some View {
Path { path in
path.addRect(CGRect(x: 50, y: 50, width: 100, height: 100)) // 添加矩形
path.addEllipse(in: CGRect(x: 200, y: 50, width: 100, height: 100)) // 添加椭圆
}
.stroke(Color.green, lineWidth: 3)
}
}
3、曲线绘制
Path 支持绘制曲线,例如二次贝塞尔曲线和三次贝塞尔曲线:
struct ContentView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 50, y: 200))
path.addQuadCurve(to: CGPoint(x: 250, y: 200), control: CGPoint(x: 150, y: 50)) // 二次贝塞尔曲线
path.move(to: CGPoint(x: 50, y: 300))
path.addCurve(to: CGPoint(x: 250, y: 300),
control1: CGPoint(x: 100, y: 100),
control2: CGPoint(x: 200, y: 500)) // 三次贝塞尔曲线
}
.stroke(Color.purple, lineWidth: 2)
}
}
4、闭合路径
使用 .closeSubpath() 方法自动连接路径的起点和终点,形成一个闭合图形:
struct ContentView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 100, y: 100))
path.addLine(to: CGPoint(x: 200, y: 100))
path.addLine(to: CGPoint(x: 150, y: 200))
path.closeSubpath() // 自动闭合
}
.fill(Color.orange) // 填充路径
}
}
结合 Shape 使用
通过实现 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.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.closeSubpath()
return path
}
}
struct ContentView: View {
var body: some View {
Triangle()
.stroke(Color.red, lineWidth: 4)
.frame(width: 200, height: 200)
}
}
Path 的核心方法
1、move(to:):将当前点移动到指定位置,不绘制线条。
通常用于初始化绘制的起点。
path.move(to: CGPoint(x: 50, y: 50)) // 移动到 (50, 50)
2、addLine(to:):从当前点到指定点绘制一条直线。
path.addLine(to: CGPoint(x: 150, y: 50)) // 绘制直线
3、addQuadCurve(to:control:):绘制二次贝塞尔曲线,指定终点和控制点。
path.addQuadCurve(to: CGPoint(x: 150, y: 100), control: CGPoint(x: 100, y: 50))
4、addCurve(to:control1:control2:):绘制三次贝塞尔曲线,指定终点和两个控制点。
path.addCurve(to: CGPoint(x: 150, y: 100),
control1: CGPoint(x: 75, y: 50),
control2: CGPoint(x: 125, y: 150))
5、addRect(_:):添加一个矩形到路径。
path.addRect(CGRect(x: 50, y: 50, width: 100, height: 100))
6、addEllipse(in:):添加一个椭圆或圆形到路径。
path.addEllipse(in: CGRect(x: 50, y: 50, width: 100, height: 50))
7、addArc(center:radius:startAngle:endAngle:clockwise:):绘制弧形或完整的圆。
path.addArc(center: CGPoint(x: 100, y: 100),
radius: 50,
startAngle: .degrees(0),
endAngle: .degrees(270),
clockwise: false)
8、closeSubpath():将当前路径闭合(起点和终点连接)。
path.closeSubpath() // 闭合路径
高级示例:组合路径
使用 Path 组合多个子路径:
struct ContentView: View {
var body: some View {
Path { path in
path.addRect(CGRect(x: 50, y: 50, width: 100, height: 100))
path.addEllipse(in: CGRect(x: 75, y: 200, width: 50, height: 50))
}
.stroke(Color.blue, lineWidth: 2)
}
}
动态动画
与 AnimatableData 结合,创建动态路径:
struct AnimatableArc: Shape {
var startAngle: Angle
var endAngle: Angle
var animatableData: AnimatablePair<Double, Double> {
get { AnimatablePair(startAngle.radians, endAngle.radians) }
set {
startAngle = .radians(newValue.first)
endAngle = .radians(newValue.second)
}
}
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: false)
return path
}
}
struct ContentView: View {
@State private var progress: Double = 0.01
var body: some View {
AnimatableArc(startAngle: .degrees(0), endAngle: .degrees(360 * progress))
.stroke(Color.green, lineWidth: 5)
.frame(width: 200, height: 200)
.onTapGesture {
withAnimation(.linear(duration: 1)) {
progress = progress == 1 ? 0.01 : 1
}
}
}
}
相关文章
1、SwiftUI内置形状:https://fangjunyu.com/2024/12/14/swiftui%e5%86%85%e7%bd%ae%e5%bd%a2%e7%8a%b6/
2、SwiftUI绘制边框stroke和strokeBorder:https://fangjunyu.com/2024/12/15/swiftui%e7%bb%98%e5%88%b6%e8%be%b9%e6%a1%86stroke%e5%92%8cstrokeborder/
3、SwiftUi定义尺寸和位置的CGRect结构: https://fangjunyu.com/2024/12/15/swiftui%e5%ae%9a%e4%b9%89%e5%b0%ba%e5%af%b8%e5%92%8c%e4%bd%8d%e7%bd%ae%e7%9a%84cgrect%e7%bb%93%e6%9e%84/
4、SwiftUi绘制边框stroke和strokeBorder: https://fangjunyu.com/2024/12/15/swiftui%e7%bb%98%e5%88%b6%e8%be%b9%e6%a1%86stroke%e5%92%8cstrokeborder/