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
相关产品推荐
相关产品推荐

