macOS中CGPath描边后无法正确填充的问题求助
解决CGPath描边叠加原路径后填充异常的问题
你当前的做法是把描边后的路径和原始路径直接叠加,由于CGPath默认使用奇偶填充规则,重叠区域会被判定为非填充区域,导致出现挖空效果。这里提供两种可靠的解决方式:
方法一:用路径布尔运算合并(推荐)
直接生成描边路径,再和原路径做联合运算,生成一个整体路径,避免重叠抵消:
func getPreviewPath(path: CGPath, strokeWidth: CGFloat) -> CGPath { // 直接生成描边后的路径,替代原来的上下文方式 let strokedPath = path.copy(strokingWithWidth: strokeWidth, lineCap: .butt, // 对应你原来的CGLineCap(rawValue: 0) lineJoin: .bevel, miterLimit: 0) // 创建可变路径,合并原路径和描边路径 let combined = CGMutablePath() combined.addPath(path) combined.addPath(strokedPath) // 执行联合运算,明确使用非零环绕填充规则,避免重叠挖空 return combined.copy(using: CGPathTransform(evenOdd: false)) ?? combined }
方法二:通过上下文构建路径并修改填充规则
如果你必须用上下文的方式,可以通过设置上下文的填充规则,再导出路径:
func getPreviewPath(path: CGPath, strokeWidth: CGFloat) -> CGPath { // 用位图上下文替代NSWindow,更轻量 let context = CGContext(data: nil, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 0, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue)! context.setLineCap(.butt) context.setLineWidth(strokeWidth) context.setLineJoin(.bevel) // 先添加描边路径,再添加原路径 context.addPath(path) context.replacePathWithStrokedPath() context.addPath(path) // 设置非零环绕填充规则,然后导出路径 context.setFillRule(.winding) return context.path! }
关键说明
- 方法一无需依赖上下文,直接用CGPath的API生成描边路径,更高效且避免不必要的窗口创建
- 两种方法核心都是确保使用非零环绕填充规则,或者通过布尔运算把两个路径合并成一个无重叠冲突的整体
- 你原来的
CGLineCap(rawValue: 0)就是.butt枚举值,直接用枚举更安全,避免rawValue出错
内容的提问来源于stack exchange,提问作者thameem
相关产品推荐
相关产品推荐

