问题
I have an overlay over the camera view made up of red circles, stored in the Assets.xcasset ImgOverlay placeholders, and the cameraview (preview) appears behind - or underneath - the overlay. That's fine. As it should be. When I run the app on the iPhone, the overlay appears as it should. See Img.1 But I also have a blue circle being drawn, that is Underneath the Camera View, and only appears if the camera view is missing. That is, Turned off, or run on a simulator. See Img.2 below.
Image 1. red circles over camera view, in iPhone
Image 2. red circles including drawn blue circle in Simulator
The code I have so far is here. I'm doing something wrong, but can't see it. I need the blue circle(s) visible in the iPhone, not just in the Simulator. I'm trying to draw all the circles, so I can abandon the red circles which are in a image.png type file. I prefer to draw the circles for better accuracy across any device, and display them instead of the red circles, and then save the composite image, of the circles and the camera view. I haven't yet managed to combine the images when saved either, but getting the blue circle visible on the iPhone is the first step ... So it's almost fully working. I can't see what I'm doing wrong?
ViewController.swift
import UIKit
import AVFoundation
import Foundation
class ViewController: UIViewController {
@IBOutlet weak var navigationBar: UINavigationBar!
@IBOutlet weak var imgOverlay: UIImageView!
@IBOutlet weak var btnCapture: UIButton!
@IBOutlet weak var shapeLayer: UIView!
let captureSession = AVCaptureSession()
let stillImageOutput = AVCaptureStillImageOutput()
var previewLayer : AVCaptureVideoPreviewLayer?
//var shapeLayer : CALayer?
// If we find a device we'll store it here for later use
var captureDevice : AVCaptureDevice?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//=======================
let midX = self.view.bounds.midX
let midY = self.view.bounds.midY
let circlePath = UIBezierPath(arcCenter: CGPoint(x: midX,y: midY), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = circlePath.cgPath
//change the fill color
shapeLayer.fillColor = UIColor.clear.cgColor
//you can change the stroke color
shapeLayer.strokeColor = UIColor.blue.cgColor
//you can change the line width
shapeLayer.lineWidth = 2.5
view.layer.addSublayer(shapeLayer)
print("Shape layer drawn")
//=====================
captureSession.sessionPreset = AVCaptureSessionPresetHigh
if let devices = AVCaptureDevice.devices() as? [AVCaptureDevice] {
// Loop through all the capture devices on this phone
for device in devices {
// Make sure this particular device supports video
if (device.hasMediaType(AVMediaTypeVideo)) {
// Finally check the position and confirm we've got the back camera
if(device.position == AVCaptureDevicePosition.back) {
captureDevice = device
if captureDevice != nil {
print("Capture device found")
beginSession()
}
}
}
}
}
}
@IBAction func actionCameraCapture(_ sender: AnyObject) {
print("Camera button pressed")
saveToCamera()
}
func beginSession() {
do {
try captureSession.addInput(AVCaptureDeviceInput(device: captureDevice))
stillImageOutput.outputSettings = [AVVideoCodecKey:AVVideoCodecJPEG]
if captureSession.canAddOutput(stillImageOutput) {
captureSession.addOutput(stillImageOutput)
}
}
catch {
print("error: \(error.localizedDescription)")
}
guard let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) else {
print("no preview layer")
return
}
// this is what displays the camera view. But - it's on TOP of the drawn view, and under the overview. ??
self.view.layer.addSublayer(previewLayer)
previewLayer.frame = self.view.layer.frame
captureSession.startRunning()
print("Capture session running")
self.view.addSubview(navigationBar)
self.view.addSubview(imgOverlay)
self.view.addSubview(btnCapture)
}
func saveToCamera() {
if let videoConnection = stillImageOutput.connection(withMediaType: AVMediaTypeVideo) {
stillImageOutput.captureStillImageAsynchronously(from: videoConnection, completionHandler: { (CMSampleBuffer, Error) in
if let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(CMSampleBuffer) {
if let cameraImage = UIImage(data: imageData) {
UIImageWriteToSavedPhotosAlbum(cameraImage, nil, nil, nil)
}
}
})
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
回答1:
You're very close...
You have:
@IBOutlet weak var shapeLayer: UIView!
but then you also create a CAShapeLayer named shapeLayer:
let shapeLayer = CAShapeLayer()
which you add as a Sublayer of your "main" view. You then add everything else on top of your main view, covering the shapeLayer.
In viewDidLoad(), change your blue-circle-drawing section to this:
let midX = self.view.bounds.midX
let midY = self.view.bounds.midY
let circlePath = UIBezierPath(arcCenter: CGPoint(x: midX,y: midY), radius: CGFloat(20), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let shapeLayerPath = CAShapeLayer()
shapeLayerPath.path = circlePath.cgPath
//change the fill color
shapeLayerPath.fillColor = UIColor.clear.cgColor
//you can change the stroke color
shapeLayerPath.strokeColor = UIColor.blue.cgColor
//you can change the line width
shapeLayerPath.lineWidth = 2.5
// add the blue-circle layer to the shapeLayer ImageView
shapeLayer.layer.addSublayer(shapeLayerPath)
print("Shape layer drawn")
//=====================
Then, at the end of beginSession()...
self.view.addSubview(navigationBar)
self.view.addSubview(imgOverlay)
self.view.addSubview(btnCapture)
// shapeLayer ImageView is already a subview created in IB
// but this will bring it to the front
self.view.addSubview(shapeLayer)
// note: since these elements are added as @IBOutlet in IB,
// these could be:
// self.view.bringSubview(toFront: navigationBar)
// self.view.bringSubview(toFront: imgOverlay)
// self.view.bringSubview(toFront: btnCapture)
// self.view.bringSubview(toFront: shapeLayer)
See what you get :)
Edit: Follow-up question moved to Combining Images in CameraView with Overlay. (Swift 3)?
来源:https://stackoverflow.com/questions/42579545/adding-objects-over-camera-view-in-app-swift-3-not-under-camera-view