iOS开发:如何实现圆形透明轮廓(背景可穿透)?
iOS 实现圆形透明轮廓(透出背景)的解决方案
问题分析
你当前的代码存在两个核心问题:
- Mask 路径坐标越界:设置的
borderPath起始坐标为-borderWidth,超出了circleImageView的 bounds 范围,导致部分轮廓被截断。 - Mask 逻辑反向:使用
evenOdd填充规则时,大圈嵌套小圈的路径会只显示「大圈减去小圈」的边框区域,这和你想要的「中间显示图片、轮廓区域透出背景」的需求完全相反。
修正方案:使用 Mask 保留图片中间区域,轮廓透明透出背景
下面是修改后的代码,同时支持可选的轮廓颜色设置:
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let backgroundImage = UIImageView(frame: UIScreen.main.bounds) backgroundImage.image = UIImage(named: "background") backgroundImage.contentMode = .scaleAspectFill view.addSubview(backgroundImage) view.sendSubviewToBack(backgroundImage) // 参数配置 let circleSize: CGFloat = 100 let borderWidth: CGFloat = 4 let circleSpacing: CGFloat = 30 var previousContainer: UIView? for _ in 0..<3 { // 创建容器视图,承载图片和可选的轮廓层 let containerView = UIView() view.addSubview(containerView) // 图片视图,尺寸与容器一致 let circleImageView = UIImageView(frame: containerView.bounds) circleImageView.image = UIImage(named: "ggg") circleImageView.contentMode = .scaleAspectFill containerView.addSubview(circleImageView) // 设置图片的 Mask:只保留中间圆形区域,轮廓区域透明 let maskLayer = CAShapeLayer() // 中间圆的路径:从 borderWidth 开始,避免被容器边界截断 let innerCirclePath = UIBezierPath(ovalIn: CGRect(x: borderWidth, y: borderWidth, width: circleSize, height: circleSize)) maskLayer.path = innerCirclePath.cgPath circleImageView.layer.mask = maskLayer // --- 可选:添加带颜色的轮廓 --- let borderLayer = CAShapeLayer() let outerCirclePath = UIBezierPath(ovalIn: containerView.bounds) outerCirclePath.append(innerCirclePath) outerCirclePath.usesEvenOddFillRule = true borderLayer.path = outerCirclePath.cgPath borderLayer.fillRule = .evenOdd borderLayer.fillColor = UIColor.clear.cgColor // 镂空填充 borderLayer.strokeColor = UIColor.white.cgColor // 轮廓颜色,可自定义 borderLayer.lineWidth = 0 containerView.layer.addSublayer(borderLayer) // --- 可选部分结束 --- // 布局约束 containerView.snp.makeConstraints { make in make.width.height.equalTo(circleSize + 2 * borderWidth) make.centerY.equalToSuperview() if let prev = previousContainer { make.left.equalTo(prev.snp.right).offset(-(circleSize - circleSpacing + borderWidth)) } else { make.left.equalToSuperview().offset(20) } } previousContainer = containerView } } }
代码说明
- 容器视图:用
UIView作为容器,方便同时管理图片和轮廓层,布局更清晰。 - 图片 Mask:通过
CAShapeLayer只保留图片的中间圆形区域,轮廓区域自动透明,直接透出下层的背景图。 - 可选轮廓颜色:如果需要给透明轮廓添加颜色,使用另一个
CAShapeLayer绘制「大圈减小圈」的镂空路径,设置填充色为透明,描边色为你需要的轮廓颜色。
内容的提问来源于stack exchange,提问作者Alex Nagi
相关产品推荐
相关产品推荐

