UIBezierPath创建圆弧路径自动闭合导致填充异常问题排查
解决UIBezierPath圆弧自动闭合导致填充异常的问题
我刚遇到过几乎一模一样的问题!核心原因很明确:当你用UIBezierPath(arcCenter:...)单独初始化一个圆弧路径时,这个路径默认是自动闭合的——系统会自动添加一条从圆弧终点回到起点的线段,把圆弧变成一个闭合的扇形路径。当你把这个闭合路径追加到主路径后,主路径的结构就被破坏了,填充时就会出现那些奇怪的空白区域(就像你第二张图里左下角的“虚拟线”其实是闭合路径的边界导致的填充逻辑错误)。
解决方案:创建开放的圆弧路径
我们需要在把圆弧路径追加到主路径前,手动移除系统自动添加的闭合线段。这里有个实用的工具函数,可以帮你生成开放的圆弧路径:
func createOpenArcPath(arcCenter: CGPoint, radius: CGFloat, startAngle: CGFloat, endAngle: CGFloat, clockwise: Bool) -> UIBezierPath { // 先创建系统默认的闭合圆弧路径 let arcPath = UIBezierPath(arcCenter: arcCenter, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: clockwise) // 提取CGPath的所有元素,准备移除闭合段 var pathElements = [CGPathElement]() arcPath.cgPath.apply(info: &pathElements) { info, element in let elements = UnsafeMutablePointer<[CGPathElement]>(info)! elements.append(element.pointee) } // 移除最后一个闭合子路径的元素(如果存在) if pathElements.count > 1, case .closeSubpath = pathElements.last!.type { pathElements.removeLast() } // 重新构建开放的圆弧路径 let openPath = UIBezierPath() for element in pathElements { switch element.type { case .moveToPoint: openPath.move(to: element.points[0]) case .addLineToPoint: openPath.addLine(to: element.points[0]) case .addQuadCurveToPoint: openPath.addQuadCurve(to: element.points[1], controlPoint: element.points[0]) case .addCurveToPoint: openPath.addCurve(to: element.points[2], controlPoint1: element.points[0], controlPoint2: element.points[1]) case .closeSubpath: break // 已经移除,无需处理 @unknown default: break } } return openPath }
替换你的原有代码
把你原来的圆弧初始化代码替换成这个函数调用:
let extent = CGFloat(startAngle) let end = extent + CGFloat(arcAngle) let cx = CGFloat(x + w / 2) let cy = CGFloat(y + h / 2) let maxSize = CGFloat(max(w, h)) // 用我们的函数创建开放圆弧路径 let path = createOpenArcPath(arcCenter: CGPoint.zero, radius: maxSize / 2, startAngle: extent, endAngle: end, clockwise: arcAngle >= 0) var transform = CGAffineTransform(translationX: cx, y: cy) transform = transform.rotated(by: CGFloat(rotation)) path.apply(transform.scaledBy(x: CGFloat(w) / maxSize, y: CGFloat(h) / maxSize)) bezierPath.append(path)
为什么addArc(withCenter:...没问题?
因为addArc(withCenter:)是直接在当前路径的基础上追加圆弧,它只会从当前路径的终点画到圆弧的起点,然后绘制圆弧到终点,不会自动闭合路径。而单独初始化的圆弧路径是一个独立的闭合路径,所以追加后会干扰主路径的填充逻辑。
这样修改后,你的主路径就会由连续的直线+开放圆弧组成,填充时就不会出现那些多余的空白区域了,完全符合你SVG里的路径结构。
内容的提问来源于stack exchange,提问作者f3dm76
相关产品推荐
相关产品推荐

