一、基础概念
UIBezierPath 是 UIKit 中用于定义矢量路径的类,可用于绘制自定义形状、实现复杂图形和动画效果。
二、基础绘制方法
1. 创建路径实例
let path = UIBezierPath()
2. 基本图形绘制
// 矩形
let rectPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 100, height: 100))
// 圆角矩形
let roundedRect = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100), cornerRadius: 10)
// 圆形/椭圆
let ovalPath = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 100, height: 100)) // 圆弧 let arcPath = UIBezierPath(arcCenter: CGPoint(x: 50, y: 50), radius: 40, startAngle: 0, endAngle: CGFloat.pi/2, clockwise: true)
三、常用路径操作方法
1. 直线绘制
path.move(to: CGPoint(x: 0, y: 0)) // 移动起点
path.addLine(to: CGPoint(x: 100, y: 100)) // 添加直线
2. 曲线绘制
// 二次贝塞尔曲线
path.addQuadCurve(to: CGPoint(x: 200, y: 0), controlPoint: CGPoint(x: 100, y: 100))
// 三次贝塞尔曲线
path.addCurve(to: CGPoint(x: 300, y: 100), controlPoint1: CGPoint(x: 200, y: 0), controlPoint2: CGPoint(x: 250, y: 200))
3. 闭合路径
path.close() // 连接最后一个点与起点
四、进阶技巧
1. 组合路径
let path1 = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 50, height: 50))
let path2 = UIBezierPath(ovalIn: CGRect(x: 25, y: 25, width: 50, height: 50))
path1.append(path2)
2. 路径变换
// 缩放
path.apply(CGAffineTransform(scaleX: 2.0, y: 1.5))
// 旋转
path.apply(CGAffineTransform(rotationAngle: CGFloat.pi/4))
// 平移
path.apply(CGAffineTransform(translationX: 50, y: 100))
3. 路径布尔运算
path1.usesEvenOddFillRule = true // 设置填充规则
五、实用案例
1. 绘制五角星
func createStarPath(center: CGPoint, radius: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let pointsOnStar = 5
for i in 0..<pointsOnStar * 2 {
let angle = CGFloat(i) * .pi / CGFloat(pointsOnStar)
let r = i % 2 == 0 ? radius : radius/2
let point = CGPoint(x: center.x + r * sin(angle),
y: center.y + r * cos(angle))
if i == 0 {
path.move(to: point)
} else {
path.addLine(to: point)
}
}
path.close()
return path
}
2. 绘制对话气泡
func createBubblePath(rect: CGRect, pointerSize: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let radius: CGFloat = 10
// 顶部
path.move(to: CGPoint(x: rect.minX + radius, y: rect.minY))
path.addLine(to: CGPoint(x: rect.maxX - radius, y: rect.minY))
path.addArc(withCenter: CGPoint(x: rect.maxX - radius, y: rect.minY + radius),
radius: radius,
startAngle: 3 * .pi/2,
endAngle: 0,
clockwise: true)
// 右侧
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - radius - pointerSize))
// 气泡指针
path.addLine(to: CGPoint(x: rect.maxX - pointerSize, y: rect.maxY - pointerSize))
path.addLine(to: CGPoint(x: rect.maxX - pointerSize, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX - 2 * pointerSize, y: rect.maxY - pointerSize))
// 底部
path.addLine(to: CGPoint(x: rect.minX + radius, y: rect.maxY - pointerSize))
path.addArc(withCenter: CGPoint(x: rect.minX + radius, y: rect.maxY - pointerSize - radius),
radius: radius,
startAngle: .pi/2,
endAngle: .pi,
clockwise: true)
// 左侧
path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + radius))
path.addArc(withCenter: CGPoint(x: rect.minX + radius, y: rect.minY + radius),
radius: radius,
startAngle: .pi,
endAngle: 3 * .pi/2,
clockwise: true)
return path
}
六、路径使用技巧
- 渲染路径:
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = UIColor.red.cgColor
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.lineWidth = 2
view.layer.addSublayer(shapeLayer)
- 路径动画:
let animation = CABasicAnimation(keyPath: "path")
animation.duration = 1.0
animation.toValue = newPath.cgPath
shapeLayer.add(animation, forKey: "pathAnimation")
- 路径检测:
path.contains(point) // 判断点是否在路径内