前言
休了半年产假,回来发现快要不会写代码了。慢慢琢磨了一小段代码仅供自己参考
思考
首先想需要再当前的view
中间抠掉一个圆实现局部透明的遮罩效果。而 CAShapeLayer
的 fillRule
属性可以帮我们实现这个过程。奇偶填充规则(Even Odd Fill Rule
)指的是:在绘制 UIBezierPath
的过程中,会碰到同一个点被覆盖多次的情况。当一个点被覆盖偶数(0 属于偶数)次的时候,表示其位于图像外,而奇数次则表示位于图形内。位于图形内的点会被填充颜色,位于图形外的则不会。总结就是奇数填充,偶数不填充
那么:
let roundRect = CGRect(x: (ScreenWidth - 235) / 2.0, y: 100, width: 235, height: 235)
// 绘制第一个矩形path为当前view的视图
let path = UIBezierPath(rect: UIScreen.main.bounds)
// 绘制第二个圆形path为摄像头大小
let bezierPath = UIBezierPath(roundedRect: roundRect, cornerRadius: 235 / 2)
path.append(bezierPath)
let shaperLayer = CAShapeLayer()
// 奇数填充,偶数不填充
shaperLayer.fillRule = .evenOdd
shaperLayer.fillColor = UIColor.white.cgColor
shaperLayer.path = path.cgPath
view.layer.addSublayer(shaperLayer)
// 为方便看出效果,可以把当前的view视图设置一个颜色
view.backgroundColor = UIColor.lightGray
运行之后可以看到如下效果:
添加外圈动画
首先把图片添加上去
let outImageView = UIImageView()
outImageView.image = UIImage(named: "face_animation_0")
view.addSubview(outImageView)
let imgCenterY = roundRect.origin.y + roundRect.height / 2.0
outImageView.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.centerY.equalTo(imgCenterY)
make.size.equalTo(CGSize(width: 280, height: 280))
}
let inImageView = UIImageView()
inImageView.image = UIImage(named: "face_animation_1")
view.addSubview(inImageView)
inImageView.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.centerY.equalTo(imgCenterY)
make.size.equalTo(CGSize(width: 270, height: 270))
}
给图片添加动画
let roationAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
roationAnimation.fromValue = 0
roationAnimation.toValue = Double.pi * 2
roationAnimation.repeatCount = MAXFLOAT
roationAnimation.speed = 1
roationAnimation.duration = 3
roationAnimation.isRemovedOnCompletion = false
outImageView.layer.add(roationAnimation, forKey: nil)
let roationAnimation1 = CABasicAnimation(keyPath: "transform.rotation.z")
roationAnimation1.fromValue = 0
roationAnimation1.toValue = -Double.pi * 2
roationAnimation1.repeatCount = MAXFLOAT
roationAnimation1.speed = 1
roationAnimation1.duration = 3
roationAnimation1.isRemovedOnCompletion = false
inImageView.layer.add(roationAnimation1, forKey: nil)
打开前置摄像头
//音频视频相关类,记得在info.plist文件配置NSCameraUsageDescription
private var device: AVCaptureDevice!
private var videoPrelayer: AVCaptureVideoPreviewLayer!
private var input: AVCaptureDeviceInput!
private var output: AVCaptureStillImageOutput!
private var session: AVCaptureSession!
//获取后置摄像头设备对象
for item in AVCaptureDevice.devices(for: .video) {
if item.position == .front {
device = item
}
}
// 创建媒体管理会话
session = AVCaptureSession()
// 创建输入数据对象
input = try? AVCaptureDeviceInput.init(device: device)
// 创建输出数据对象
output = AVCaptureStillImageOutput()
output.outputSettings = [AVVideoCodecKey: AVVideoCodecJPEG]
//添加输入数据对象和输出对象到会话中
if session.canAddInput(input) {
session.addInput(input)
}
if session.canAddOutput(output) {
session.addOutput(output)
}
// 创建视频预览图层
videoPrelayer = AVCaptureVideoPreviewLayer.init(session: session)
videoPrelayer.videoGravity = .resizeAspectFill
videoPrelayer.frame = roundRect
// 插入图层在view视图的最下方
view.layer.insertSublayer(videoPrelayer, at: 0)
session.startRunning()
运行,效果就出来了。