【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

coiai.netでは案件受付中です。
Vtuber、建築モデリング、EC構築、ネイティブアプリ制作、制服の制作(実は縫製業もメイン)、Vision Pro向けアプリ etc…
様々な制作開発を行っています。

ご気軽にご相談ください!

コイアイちゃんのアバター

この記事を書いたのは


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


Top
Blog
Works
contact