Article / 2026/05/29
SwiftUI Path 类完整 API 指南
SwiftUI 的 Path 结构体用于创建自定义的矢量图形路径。它提供了一系列方法来构建复杂的形状和线条,可以用于绘制自定义图形、创建动画效果或实现复杂的 UI 元素。
🚀 SwiftUI Path 类完整 API 指南
概述
SwiftUI 的 Path 结构体用于创建自定义的矢量图形路径。它提供了一系列方法来构建复杂的形状和线条,可以用于绘制自定义图形、创建动画效果或实现复杂的 UI 元素。
初始化方法
Path()
创建一个空的路径。
let emptyPath = Path()
Path(_ rect: CGRect)
创建一个矩形路径。
参数:
rect: 矩形的边界框
let rectPath = Path(CGRect(x: 0, y: 0, width: 100, height: 100))
Path(_ ellipse: CGRect)
创建一个椭圆路径。
参数:
ellipse: 椭圆的边界框
let ellipsePath = Path(ellipseIn: CGRect(x: 0, y: 0, width: 100, height: 50))
Path(_ roundedRect: CGRect, cornerRadius: CGFloat)
创建一个圆角矩形路径。
参数:
roundedRect: 矩形的边界框cornerRadius: 圆角半径
let roundedPath = Path(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100),
cornerRadius: 10)
Path(_ roundedRect: CGRect, cornerSize: CGSize)
创建一个具有不同 x、y 圆角半径的矩形路径。
参数:
roundedRect: 矩形的边界框cornerSize: 圆角的尺寸(宽度和高度)
let customRoundedPath = Path(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100),
cornerSize: CGSize(width: 15, height: 8))
基本绘制方法
move(to point: CGPoint)
将当前点移动到指定位置,不绘制线条。
参数:
point: 目标位置
var path = Path()
path.move(to: CGPoint(x: 50, y: 50))
addLine(to point: CGPoint)
从当前点绘制直线到指定点。
参数:
point: 直线的终点
var path = Path()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 100, y: 100))
addLines(_ points: [CGPoint])
添加一系列连续的直线段。
参数:
points: 直线段的端点数组
var path = Path()
path.move(to: CGPoint(x: 0, y: 0))
path.addLines([
CGPoint(x: 50, y: 100),
CGPoint(x: 100, y: 50),
CGPoint(x: 150, y: 150)
])
曲线绘制方法
addQuadCurve(to end: CGPoint, control: CGPoint)
添加二次贝塞尔曲线。
参数:
end: 曲线的终点control: 控制点
var path = Path()
path.move(to: CGPoint(x: 0, y: 100))
path.addQuadCurve(to: CGPoint(x: 200, y: 100),
control: CGPoint(x: 100, y: 0))
addCurve(to end: CGPoint, control1: CGPoint, control2: CGPoint)
添加三次贝塞尔曲线。
参数:
end: 曲线的终点control1: 第一个控制点control2: 第二个控制点
var path = Path()
path.move(to: CGPoint(x: 0, y: 100))
path.addCurve(to: CGPoint(x: 200, y: 100),
control1: CGPoint(x: 50, y: 0),
control2: CGPoint(x: 150, y: 200))
几何图形方法
addRect(_ rect: CGRect)
添加矩形到路径。
参数:
rect: 矩形的边界框
var path = Path()
path.addRect(CGRect(x: 10, y: 10, width: 80, height: 60))
addRoundedRect(in rect: CGRect, cornerSize: CGSize)
添加圆角矩形到路径。
参数:
rect: 矩形的边界框cornerSize: 圆角的尺寸
var path = Path()
path.addRoundedRect(in: CGRect(x: 0, y: 0, width: 100, height: 100),
cornerSize: CGSize(width: 10, height: 10))
addEllipse(in rect: CGRect)
添加椭圆到路径。
参数:
rect: 椭圆的边界框
var path = Path()
path.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 50))
弧线绘制方法
addArc(center: CGPoint, radius: CGFloat, startAngle: Angle, endAngle: Angle, clockwise: Bool)
添加圆弧到路径。
参数:
center: 圆弧的中心点radius: 圆弧的半径startAngle: 起始角度endAngle: 结束角度clockwise: 是否顺时针方向
var path = Path()
path.addArc(center: CGPoint(x: 100, y: 100),
radius: 50,
startAngle: .degrees(0),
endAngle: .degrees(90),
clockwise: false)
addArc(tangent1End: CGPoint, tangent2End: CGPoint, radius: CGFloat)
添加与两条切线相切的圆弧。
参数:
tangent1End: 第一条切线的终点tangent2End: 第二条切线的终点radius: 圆弧的半径
var path = Path()
path.move(to: CGPoint(x: 0, y: 100))
path.addArc(tangent1End: CGPoint(x: 100, y: 100),
tangent2End: CGPoint(x: 100, y: 0),
radius: 20)
路径操作方法
addPath(_ path: Path)
将另一个路径添加到当前路径。
参数:
path: 要添加的路径
var mainPath = Path()
mainPath.addRect(CGRect(x: 0, y: 0, width: 50, height: 50))
var secondPath = Path()
secondPath.addEllipse(in: CGRect(x: 60, y: 0, width: 50, height: 50))
mainPath.addPath(secondPath)
closeSubpath()
关闭当前子路径,从当前点绘制直线到子路径的起始点。
var path = Path()
path.move(to: CGPoint(x: 50, y: 0))
path.addLine(to: CGPoint(x: 100, y: 50))
path.addLine(to: CGPoint(x: 0, y: 50))
path.closeSubpath() // 形成三角形
路径变换方法
applying(_ transform: CGAffineTransform)
对路径应用仿射变换,返回新的路径。
参数:
transform: 要应用的仿射变换
var path = Path()
path.addRect(CGRect(x: 0, y: 0, width: 50, height: 50))
let scaledPath = path.applying(CGAffineTransform(scaleX: 2, y: 2))
offsetBy(dx: CGFloat, dy: CGFloat)
创建一个偏移的路径副本。
参数:
dx: X 轴偏移量dy: Y 轴偏移量
var path = Path()
path.addEllipse(in: CGRect(x: 0, y: 0, width: 50, height: 50))
let offsetPath = path.offsetBy(dx: 100, dy: 50)
路径信息属性
isEmpty: Bool
检查路径是否为空。
let path = Path()
print(path.isEmpty) // true
boundingRect: CGRect
获取路径的边界矩形。
var path = Path()
path.addEllipse(in: CGRect(x: 10, y: 10, width: 80, height: 60))
let bounds = path.boundingRect
currentPoint: CGPoint?
获取路径的当前点位置。
var path = Path()
path.move(to: CGPoint(x: 50, y: 50))
print(path.currentPoint) // Optional(CGPoint(50, 50))
路径检测方法
contains(_ point: CGPoint, eoFill: Bool = false)
检查指定点是否在路径内部。
参数:
point: 要检查的点eoFill: 是否使用奇偶填充规则
var path = Path()
path.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
let isInside = path.contains(CGPoint(x: 50, y: 50))
strokedPath(_ style: StrokeStyle)
创建路径的描边路径。
参数:
style: 描边样式
var path = Path()
path.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
let strokeStyle = StrokeStyle(lineWidth: 5, lineCap: .round, lineJoin: .round)
let strokedPath = path.strokedPath(strokeStyle)
实际应用示例
创建自定义形状
struct CustomShape: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// 创建一个心形
let width = rect.width
let height = rect.height
path.move(to: CGPoint(x: width * 0.5, y: height * 0.25))
path.addCurve(to: CGPoint(x: width * 0.1, y: height * 0.25),
control1: CGPoint(x: width * 0.5, y: height * 0.15),
control2: CGPoint(x: width * 0.1, y: height * 0.15))
path.addArc(center: CGPoint(x: width * 0.1, y: height * 0.35),
radius: height * 0.1,
startAngle: .degrees(180),
endAngle: .degrees(0),
clockwise: false)
path.addCurve(to: CGPoint(x: width * 0.5, y: height * 0.9),
control1: CGPoint(x: width * 0.1, y: height * 0.55),
control2: CGPoint(x: width * 0.5, y: height * 0.75))
path.addCurve(to: CGPoint(x: width * 0.9, y: height * 0.45),
control1: CGPoint(x: width * 0.5, y: height * 0.75),
control2: CGPoint(x: width * 0.9, y: height * 0.55))
path.addArc(center: CGPoint(x: width * 0.9, y: height * 0.35),
radius: height * 0.1,
startAngle: .degrees(0),
endAngle: .degrees(180),
clockwise: false)
path.closeSubpath()
return path
}
}
动画路径示例
struct AnimatedPath: View {
@State private var animationProgress: CGFloat = 0
var body: some View {
Canvas { context, size in
var path = Path()
path.move(to: CGPoint(x: 0, y: size.height / 2))
for i in 0...Int(size.width) {
let x = CGFloat(i)
let y = size.height/2 + sin(x * 0.02 + animationProgress) * 50
path.addLine(to: CGPoint(x: x, y: y))
}
context.stroke(path, with: .color(.blue), lineWidth: 3)
}
.onAppear {
withAnimation(.linear(duration: 2).repeatForever(autoreverses: false)) {
animationProgress = .pi * 2
}
}
}
}
复杂路径组合
struct ComplexPath: View {
var body: some View {
Canvas { context, size in
// 主路径
var mainPath = Path()
mainPath.addRect(CGRect(x: 50, y: 50, width: 100, height: 100))
// 圆形路径
var circlePath = Path()
circlePath.addEllipse(in: CGRect(x: 75, y: 75, width: 50, height: 50))
// 组合路径
mainPath.addPath(circlePath)
// 应用变换
let rotatedPath = mainPath.applying(
CGAffineTransform(rotationAngle: .pi / 4)
)
context.fill(rotatedPath, with: .color(.red.opacity(0.7)))
context.stroke(rotatedPath, with: .color(.black), lineWidth: 2)
}
.frame(width: 300, height: 300)
}
}
注意事项
- 性能考虑: 复杂的路径计算可能影响性能,特别是在动画中
- 坐标系统: SwiftUI 使用左上角为原点的坐标系统
- 路径复用: 可以将复杂路径缓存以提高性能
- 内存管理: 大量的路径对象可能消耗较多内存
- 精度问题: 浮点数计算可能存在精度误差
总结
SwiftUI 的 Path API 提供了强大而灵活的矢量图形绘制能力。通过组合使用这些方法,可以创建复杂的自定义形状、动画效果和交互式图形界面。掌握这些 API 将大大增强你在 SwiftUI 中创建自定义视觉效果的能力。
Giscus 未启用:请在
src/site.config.ts中配置 repoId 与 categoryId。