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

如何像裁剪图片一样裁剪AVCaptureVideoPreviewLayer视频预览层?

实现AVCaptureVideoPreviewLayer的圆形裁剪+描边效果

当然可以搞定!我之前也碰到过类似的需求,AVCaptureVideoPreviewLayer作为CALayer的子类,我们可以用Core Animation的特性来实现和SwiftUI里clipShape(Circle())加描边几乎一样的效果,具体步骤如下:

1. 给预览层添加圆形遮罩实现裁剪

AVCaptureVideoPreviewLayer本身支持通过mask属性设置裁剪形状,我们可以用CAShapeLayer创建一个圆形路径作为遮罩:

// 先创建你的previewLayer(保持你原有的代码)
let captureSession = AVCaptureSession()
// ... 这里省略session的配置代码 ...
let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
previewLayer.frame = CGRect(x: 20, y: 60, width: 335, height: 200)
previewLayer.videoGravity = .resizeAspectFill
view.layer.addSublayer(previewLayer)

// 创建圆形遮罩层
let circleMask = CAShapeLayer()
circleMask.path = UIBezierPath(ovalIn: previewLayer.bounds).cgPath
// 把遮罩赋值给previewLayer,实现圆形裁剪
previewLayer.mask = circleMask

2. 添加绿色描边的圆形图层

因为遮罩会把超出圆形范围的内容全部裁剪掉,所以不能直接给previewLayer加描边(加了也看不到),需要单独创建一个描边图层,放在previewLayer的上方或者同级位置:

// 创建描边用的形状层
let strokeLayer = CAShapeLayer()
// 复用之前的圆形路径,保证和裁剪形状一致
strokeLayer.path = circleMask.path
// 设置描边样式
strokeLayer.strokeColor = UIColor.green.cgColor
strokeLayer.fillColor = UIColor.clear.cgColor // 填充色设为透明,只显示描边
strokeLayer.lineWidth = 1.0

// 把描边图层添加到父视图的layer上,位置和previewLayer保持一致
view.layer.addSublayer(strokeLayer)
strokeLayer.frame = previewLayer.frame

3. 适配视图布局变化

如果你的视图会发生布局变化(比如屏幕旋转、横竖屏切换),需要在布局更新时同步更新遮罩和描边的路径,避免形状错位:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // 找到之前创建的遮罩层和描边层
    guard let maskLayer = previewLayer.mask as? CAShapeLayer,
          let strokeLayer = view.layer.sublayers?.first(where: {
              guard let shapeLayer = $0 as? CAShapeLayer else { return false }
              return shapeLayer.strokeColor == UIColor.green.cgColor
          }) as? CAShapeLayer else {
        return
    }
    // 更新路径和frame
    maskLayer.path = UIBezierPath(ovalIn: previewLayer.bounds).cgPath
    strokeLayer.path = maskLayer.path
    strokeLayer.frame = previewLayer.frame
}

扩展:实现其他形状的裁剪

如果想要换成圆角矩形或者自定义形状,只需要修改UIBezierPath的创建方式即可,比如圆角矩形:

let roundedRectPath = UIBezierPath(roundedRect: previewLayer.bounds, cornerRadius: 20)
circleMask.path = roundedRectPath.cgPath
strokeLayer.path = roundedRectPath.cgPath

这样就能实现和你给出的SwiftUI示例几乎完全一致的视觉效果啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:42:00