如何在条形码扫描仪上绘制的矩形动画?
我在Swift中创建了一个条形码扫描仪控件。扫描仪工作正常,我可以绘制一个扫描区域盒覆盖。我试图根据扫描的成功使盒子闪光绿色或红色。我添加了一个延迟的动画,但是它无法正常工作。盒子的颜色确实发生了变化,但在持续时间内没有缓慢的动画。它只是立即改变。 I.希望盒子闪烁绿色,然后恢复为原始颜色。
我想知道我一开始如何绘制盒子是否有什么应有的作用。也许我正在修改的cashapelayer
与动画不兼容?
class BarcodeScanner: UIView, AVCaptureMetadataOutputObjectsDelegate {
var scanBoxLayer: CAShapeLayer!
func preparePreviewLayer() {
self.layer.sublayers?.removeAll()
captureSession = AVCaptureSession()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
return
}
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417, .qr, .code39, .code128]
} else {
return
}
scanPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
scanPreviewLayer.frame = self.layer.bounds
scanPreviewLayer.videoGravity = .resizeAspectFill
self.layer.addSublayer(scanPreviewLayer)
// Here is where I draw the scan box
drawScanBox()
}
func drawScanBox() {
let path = UIBezierPath(rect: scanBox())
scanBoxLayer = CAShapeLayer()
scanBoxLayer.path = path.cgPath
scanBoxLayer.strokeColor = UIColor.systemYellow.cgColor
scanBoxLayer.lineWidth = 2
scanBoxLayer.fillColor = UIColor.clear.cgColor
scanBoxLayer.shadowColor = UIColor.systemYellow.cgColor
scanBoxLayer.shadowOpacity = 1.0
scanBoxLayer.shadowRadius = 5.0
self.layer.addSublayer(scanBoxLayer)
}
func scanBox() -> CGRect {
let height: CGFloat = self.scanPreviewLayer.frame.size.height
let width: CGFloat = self.scanPreviewLayer.frame.size.width
return self.bounds.insetBy(dx: width / 5, dy: height / 3)
}
func flash() {
UIView.animate(
withDuration: 3.0,
delay: 0.0,
options: [.repeat, .autoreverse],
animations: {
self.scanBoxLayer.strokeColor = UIColor.systemGreen.cgColor
self.scanBoxLayer.shadowColor = UIColor.systemGreen.cgColor
},
completion: nil
)
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
if let barcode = readableObject.stringValue {
// Here is where I want to make the scan box flash
flash()
self.delegate?.scanComplete(code: barcode)
}
}
}
}
有人可以告诉我我是否缺少某些东西?
谢谢!
I created a barcode scanner control in Swift. The scanner works fine and I am able to draw a scan area box overlay. I am trying to make the box flash green or red depending on the success of the scan. I've added an animation with a delay but it does not work properly. The color of the box does change but there isn't a slow animation for the duration period. it just changes immediately. I. would like the box to flash green and then revert back to the original color.
I am wondering if it has something to due with how I am drawing the box in the first place. Perhaps the CAShapeLayer
that I am modifying isn't compatible with animations?
class BarcodeScanner: UIView, AVCaptureMetadataOutputObjectsDelegate {
var scanBoxLayer: CAShapeLayer!
func preparePreviewLayer() {
self.layer.sublayers?.removeAll()
captureSession = AVCaptureSession()
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
return
}
let videoInput: AVCaptureDeviceInput
do {
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
} catch {
return
}
if (captureSession.canAddInput(videoInput)) {
captureSession.addInput(videoInput)
} else {
return
}
let metadataOutput = AVCaptureMetadataOutput()
if (captureSession.canAddOutput(metadataOutput)) {
captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = [.ean8, .ean13, .pdf417, .qr, .code39, .code128]
} else {
return
}
scanPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
scanPreviewLayer.frame = self.layer.bounds
scanPreviewLayer.videoGravity = .resizeAspectFill
self.layer.addSublayer(scanPreviewLayer)
// Here is where I draw the scan box
drawScanBox()
}
func drawScanBox() {
let path = UIBezierPath(rect: scanBox())
scanBoxLayer = CAShapeLayer()
scanBoxLayer.path = path.cgPath
scanBoxLayer.strokeColor = UIColor.systemYellow.cgColor
scanBoxLayer.lineWidth = 2
scanBoxLayer.fillColor = UIColor.clear.cgColor
scanBoxLayer.shadowColor = UIColor.systemYellow.cgColor
scanBoxLayer.shadowOpacity = 1.0
scanBoxLayer.shadowRadius = 5.0
self.layer.addSublayer(scanBoxLayer)
}
func scanBox() -> CGRect {
let height: CGFloat = self.scanPreviewLayer.frame.size.height
let width: CGFloat = self.scanPreviewLayer.frame.size.width
return self.bounds.insetBy(dx: width / 5, dy: height / 3)
}
func flash() {
UIView.animate(
withDuration: 3.0,
delay: 0.0,
options: [.repeat, .autoreverse],
animations: {
self.scanBoxLayer.strokeColor = UIColor.systemGreen.cgColor
self.scanBoxLayer.shadowColor = UIColor.systemGreen.cgColor
},
completion: nil
)
}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
if let metadataObject = metadataObjects.first {
guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
if let barcode = readableObject.stringValue {
// Here is where I want to make the scan box flash
flash()
self.delegate?.scanComplete(code: barcode)
}
}
}
}
Can anyone please tell me if I am missing something?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论