You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift开发问题:如何移除相交线条仅保留外部轮廓?

解决Swift中三个相交圆形仅保留外部轮廓的问题

嘿,我来帮你搞定这个问题!你现在的代码是把三个完整的圆路径直接拼接在一起,所以会显示所有线条——包括那些相交的内部部分。要只保留外部轮廓,这里有两种实用的方案,你可以根据自己的需求和系统兼容情况选择:

方案一:利用填充规则提取外部轮廓

这个思路是先让三个圆的区域合并,再提取合并区域的描边轮廓,适合需要兼容iOS 13以下版本的场景:

let width = 300
func circle(withRadius radius: CGFloat) -> UIView {
    // 分别创建三个圆的路径
    let topCircle = UIBezierPath(arcCenter: CGPoint(x: width * 0.5, y: width * 1/3), 
                                 radius: 80, 
                                 startAngle: .zero, 
                                 endAngle: .pi * 2, 
                                 clockwise: true)
    let leftBottomCircle = UIBezierPath(arcCenter: CGPoint(x: width * 1/3, y: width * 2/3), 
                                        radius: 80, 
                                        startAngle: .zero, 
                                        endAngle: .pi * 2, 
                                        clockwise: true)
    let rightBottomCircle = UIBezierPath(arcCenter: CGPoint(x: width * 2/3, y: width * 2/3), 
                                         radius: 80, 
                                         startAngle: .zero, 
                                         endAngle: .pi * 2, 
                                         clockwise: true)
    
    // 把三个圆合并到一个复合路径里
    let combinedPath = UIBezierPath()
    combinedPath.append(topCircle)
    combinedPath.append(leftBottomCircle)
    combinedPath.append(rightBottomCircle)
    
    // 先创建一个图层用来生成合并后的填充区域
    let fillLayer = CAShapeLayer()
    fillLayer.path = combinedPath.cgPath
    fillLayer.fillColor = UIColor.black.cgColor
    fillLayer.strokeColor = UIColor.clear.cgColor
    fillLayer.fillRule = .evenOdd // 这个规则会让重叠的区域不被填充
    
    // 创建轮廓图层,提取填充区域的边界作为描边路径
    let outlineLayer = CAShapeLayer()
    outlineLayer.path = fillLayer.presentation()?.path ?? fillLayer.path
    outlineLayer.fillColor = UIColor.clear.cgColor
    outlineLayer.strokeColor = UIColor.black.cgColor
    outlineLayer.lineWidth = 3.0
    
    backView.layer.addSublayer(outlineLayer)
    return backView
}

方案二:直接用路径运算生成外部轮廓

如果你的APP只需要兼容iOS 13+,这个方案更简洁高效,直接通过路径的联合运算生成外部轮廓:

let width = 300
func circle(withRadius radius: CGFloat) -> UIView {
    // 生成三个圆的CGPath
    let topCirclePath = UIBezierPath(arcCenter: CGPoint(x: width * 0.5, y: width * 1/3), 
                                     radius: 80, 
                                     startAngle: .zero, 
                                     endAngle: .pi * 2, 
                                     clockwise: true).cgPath
    let leftBottomCirclePath = UIBezierPath(arcCenter: CGPoint(x: width * 1/3, y: width * 2/3), 
                                            radius: 80, 
                                            startAngle: .zero, 
                                            endAngle: .pi * 2, 
                                            clockwise: true).cgPath
    let rightBottomCirclePath = UIBezierPath(arcCenter: CGPoint(x: width * 2/3, y: width * 2/3), 
                                             radius: 80, 
                                             startAngle: .zero, 
                                             endAngle: .pi * 2, 
                                             clockwise: true).cgPath
    
    // 创建可变路径,通过union运算合并三个圆,直接得到外部轮廓
    let mergedPath = CGMutablePath()
    mergedPath.addPath(topCirclePath)
    mergedPath.addPath(leftBottomCirclePath, transform: .identity, operation: .union)
    mergedPath.addPath(rightBottomCirclePath, transform: .identity, operation: .union)
    
    let shapeLayer = CAShapeLayer()
    shapeLayer.path = mergedPath
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.strokeColor = UIColor.black.cgColor
    shapeLayer.lineWidth = 3.0
    
    backView.layer.addSublayer(shapeLayer)
    return backView
}

小提示

  • 方案一的evenOdd填充规则:简单来说就是路径重叠奇数次的区域会被填充,偶数次的不填充,这样三个圆相交的部分就不会被填充,我们提取这个填充区域的边界就是想要的外部轮廓。
  • 方案二的.union运算:相当于把多个路径合并成一个“整体”,直接生成包含所有区域的外围路径,一步到位,代码更简洁。

内容的提问来源于stack exchange,提问作者Toto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:47:31