feat: Implement resizeMode prop for iOS (#1838)

* feat: Implement `resizeMode` prop for iOS

- `"cover"`: Keep aspect ratio, but fill entire parent view (centered).
- `"contain"`: Keep aspect ratio, but make sure the entire content is visible even if it introduces additional blank areas (centered).

* chore: Update prop docs

* Update CameraProps.ts

* Lint & Format
This commit is contained in:
Marc Rousavy
2023-09-23 10:14:27 +02:00
committed by GitHub
parent c0b80b342b
commit 3169444697
14 changed files with 120 additions and 38 deletions

View File

@@ -59,6 +59,12 @@ public final class CameraView: UIView {
@objc var zoom: NSNumber = 1.0 // in "factor"
@objc var enableFpsGraph = false
@objc var videoStabilizationMode: NSString?
@objc var resizeMode: NSString = "cover" {
didSet {
previewView.resizeMode = ResizeMode(fromTypeScriptUnion: resizeMode as String)
}
}
// events
@objc var onInitialized: RCTDirectEventBlock?
@objc var onError: RCTDirectEventBlock?

View File

@@ -47,6 +47,7 @@ RCT_EXPORT_VIEW_PROPERTY(zoom, NSNumber);
RCT_EXPORT_VIEW_PROPERTY(enableZoomGesture, BOOL);
RCT_EXPORT_VIEW_PROPERTY(enableFpsGraph, BOOL);
RCT_EXPORT_VIEW_PROPERTY(orientation, NSString);
RCT_EXPORT_VIEW_PROPERTY(resizeMode, NSString);
// Camera View Events
RCT_EXPORT_VIEW_PROPERTY(onError, RCTDirectEventBlock);
RCT_EXPORT_VIEW_PROPERTY(onInitialized, RCTDirectEventBlock);

View File

@@ -11,13 +11,29 @@ import Foundation
import UIKit
class PreviewView: UIView {
/// Convenience wrapper to get layer as its statically known type.
/**
Convenience wrapper to get layer as its statically known type.
*/
var videoPreviewLayer: AVCaptureVideoPreviewLayer {
// swiftlint:disable force_cast
return layer as! AVCaptureVideoPreviewLayer
// swiftlint:enable force_cast
}
/**
Gets or sets the resize mode of the PreviewView.
*/
var resizeMode: ResizeMode = .cover {
didSet {
switch resizeMode {
case .cover:
videoPreviewLayer.videoGravity = .resizeAspectFill
case .contain:
videoPreviewLayer.videoGravity = .resizeAspect
}
}
}
override public class var layerClass: AnyClass {
return AVCaptureVideoPreviewLayer.self
}

View File

@@ -0,0 +1,35 @@
//
// ResizeMode.swift
// VisionCamera
//
// Created by Marc Rousavy on 22.09.23.
// Copyright © 2023 mrousavy. All rights reserved.
//
import Foundation
/**
A ResizeMode used for the PreviewView.
*/
enum ResizeMode {
/**
Keep aspect ratio, but fill entire parent view (centered).
*/
case cover
/**
Keep aspect ratio, but make sure the entire content is visible even if it introduces additional blank areas (centered).
*/
case contain
init(fromTypeScriptUnion union: String) {
switch union {
case "cover":
self = .cover
case "contain":
self = .contain
default:
// TODO: Use the onError event for safer error handling!
fatalError("Invalid value passed for resizeMode! (\(union))")
}
}
}

View File

@@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
B80175EC2ABDEBD000E7DE90 /* ResizeMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80175EB2ABDEBD000E7DE90 /* ResizeMode.swift */; };
B80C0E00260BDDF7001699AB /* FrameProcessorPluginRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = B80C0DFF260BDDF7001699AB /* FrameProcessorPluginRegistry.m */; };
B80E06A0266632F000728644 /* AVAudioSession+updateCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = B80E069F266632F000728644 /* AVAudioSession+updateCategory.swift */; };
B81BE1BF26B936FF002696CC /* AVCaptureDevice.Format+videoDimensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B81BE1BE26B936FF002696CC /* AVCaptureDevice.Format+videoDimensions.swift */; };
@@ -80,6 +81,7 @@
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libVisionCamera.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libVisionCamera.a; sourceTree = BUILT_PRODUCTS_DIR; };
B80175EB2ABDEBD000E7DE90 /* ResizeMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeMode.swift; sourceTree = "<group>"; };
B80C02EB2A6A954D001975E2 /* FrameProcessorPluginHostObject.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FrameProcessorPluginHostObject.mm; sourceTree = "<group>"; };
B80C02EC2A6A9552001975E2 /* FrameProcessorPluginHostObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorPluginHostObject.h; sourceTree = "<group>"; };
B80C0DFE260BDD97001699AB /* FrameProcessorPluginRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FrameProcessorPluginRegistry.h; sourceTree = "<group>"; };
@@ -174,6 +176,7 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
B80175EA2ABDEBBB00E7DE90 /* Types */,
B8DCF2D725EA940700EA5C72 /* Frame Processor */,
B887515E25E0102000DB86D6 /* CameraBridge.h */,
B84760DE2608F57D004C3180 /* CameraQueues.swift */,
@@ -201,6 +204,14 @@
);
sourceTree = "<group>";
};
B80175EA2ABDEBBB00E7DE90 /* Types */ = {
isa = PBXGroup;
children = (
B80175EB2ABDEBD000E7DE90 /* ResizeMode.swift */,
);
path = Types;
sourceTree = "<group>";
};
B887516125E0102000DB86D6 /* Extensions */ = {
isa = PBXGroup;
children = (
@@ -418,6 +429,7 @@
B881D35E2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift in Sources */,
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */,
B88751A625E0102000DB86D6 /* CameraViewManager.swift in Sources */,
B80175EC2ABDEBD000E7DE90 /* ResizeMode.swift in Sources */,
B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift in Sources */,
B8D22CDC2642DB4D00234472 /* AVAssetWriterInputPixelBufferAdaptor+initWithVideoSettings.swift in Sources */,
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */,