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

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
        }
    }
}

代码说明

  1. 容器视图:用 UIView 作为容器,方便同时管理图片和轮廓层,布局更清晰。
  2. 图片 Mask:通过 CAShapeLayer 只保留图片的中间圆形区域,轮廓区域自动透明,直接透出下层的背景图。
  3. 可选轮廓颜色:如果需要给透明轮廓添加颜色,使用另一个 CAShapeLayer 绘制「大圈减小圈」的镂空路径,设置填充色为透明,描边色为你需要的轮廓颜色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:21:16