【SwiftUI】カメラ機能を使いたい 開発日誌

SwiftUIでカメラ機能を実装する方法についてです。

基本機能の実装

import SwiftUI
import AVFoundation

struct CameraContentView: View {
    var body: some View {
        CameraView()
            .edgesIgnoringSafeArea(.all)
    }
}

struct CameraView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView { BaseCameraView() }
    func updateUIView(_ uiView: UIViewType, context: Context) {}
}

class BaseCameraView: UIView {
    override func layoutSubviews() {
        super.layoutSubviews()
        _ = initCaptureSession
        (layer.sublayers?.first as? AVCaptureVideoPreviewLayer)?.frame = bounds
    }

    lazy var initCaptureSession: Void = {
        guard let device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera],
                                                            mediaType: .video,
                                                            position: .unspecified)
                .devices.first(where: { $0.position == .front }),
              let input = try? AVCaptureDeviceInput(device: device) else { return }

        let session = AVCaptureSession()
        session.addInput(input)
        session.startRunning()

        layer.insertSublayer(AVCaptureVideoPreviewLayer(session: session), at: 0)
    }()
}

このコードを実行すると、フロントカメラが起動し、画面全体に映像が表示されます。

画面の向きに合わせてカメラの向きを変える

このままだと、端末の向きを変えた時に縦:横=16:9の比率を保ったまま回転してしまうので、画面の向きに応じたカメラの映像が出てこなくなってしました。

そこで下記コードを追記しました。

enum Orientation: Int {
    case right = -1, down = 0, left = 1, up = 2
}

private func getDeviceOrientation() -> Orientation {
    guard let interfaceOrientation = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.windowScene?.interfaceOrientation else {
        return .right
    }
    switch interfaceOrientation {
    case .landscapeLeft:
        return .left
    case .landscapeRight:
        return .right
    case .portrait:
        return .down
    case .portraitUpsideDown:
        return .up
    default:
        return .right
    }
}

private func fixCameraOrientation() {
    let rotation: CGFloat = CGFloat(getDeviceOrientation().rawValue) * 90
    previewLayer?.transform = CATransform3DMakeRotation(rotation / 180 * CGFloat.pi, 0, 0, 1)
}

これらの関数をlayoutSubviewsに追加することで、デバイスの向きが変わるたびにカメラの向きも適切に調整されます。

参考文献様

以下の記事に助けられました感謝

https://zenn.dev/platina/articles/5b9683f6d50938

コイアイちゃん Avatar

この記事を書いたのは


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA