@capgo/camera-preview 7.4.0-beta.15 → 7.4.0-beta.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +118 -25
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +160 -75
- package/android/src/main/java/com/ahm/capacitor/camera/preview/GridOverlayView.java +24 -7
- package/dist/docs.json +12 -0
- package/dist/esm/definitions.d.ts +7 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.js +43 -4
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +43 -4
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +43 -4
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreview/CameraController.swift +59 -8
- package/ios/Sources/CapgoCameraPreview/Plugin.swift +107 -95
- package/package.json +1 -1
|
@@ -137,26 +137,8 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
137
137
|
let height = heightValue - paddingBottom
|
|
138
138
|
|
|
139
139
|
// Handle auto-centering during rotation
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
self.updateCameraFrame()
|
|
143
|
-
} else {
|
|
144
|
-
// Manual positioning - use original rotation logic with no animation
|
|
145
|
-
CATransaction.begin()
|
|
146
|
-
CATransaction.setDisableActions(true)
|
|
147
|
-
|
|
148
|
-
if UIWindow.isLandscape {
|
|
149
|
-
previewView.frame = CGRect(x: posY, y: posX, width: max(height, width), height: min(height, width))
|
|
150
|
-
self.cameraController.previewLayer?.frame = previewView.bounds
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
if UIWindow.isPortrait {
|
|
154
|
-
previewView.frame = CGRect(x: posX, y: posY, width: min(height, width), height: max(height, width))
|
|
155
|
-
self.cameraController.previewLayer?.frame = previewView.bounds
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
CATransaction.commit()
|
|
159
|
-
}
|
|
140
|
+
// Always use the factorized method for consistent positioning
|
|
141
|
+
self.updateCameraFrame()
|
|
160
142
|
|
|
161
143
|
if let connection = self.cameraController.fileVideoOutput?.connection(with: .video) {
|
|
162
144
|
switch UIDevice.current.orientation {
|
|
@@ -205,48 +187,51 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
205
187
|
self.aspectRatio = newAspectRatio
|
|
206
188
|
|
|
207
189
|
DispatchQueue.main.async {
|
|
208
|
-
// When aspect ratio changes,
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
190
|
+
// When aspect ratio changes, always auto-center the view
|
|
191
|
+
// This ensures consistent behavior where changing aspect ratio recenters the view
|
|
192
|
+
self.posX = -1
|
|
193
|
+
self.posY = -1
|
|
194
|
+
|
|
195
|
+
// Calculate maximum size based on aspect ratio
|
|
196
|
+
let webViewWidth = self.webView?.frame.width ?? UIScreen.main.bounds.width
|
|
197
|
+
let webViewHeight = self.webView?.frame.height ?? UIScreen.main.bounds.height
|
|
198
|
+
let paddingBottom = self.paddingBottom ?? 0
|
|
199
|
+
|
|
200
|
+
// Calculate available space
|
|
201
|
+
let availableWidth: CGFloat
|
|
202
|
+
let availableHeight: CGFloat
|
|
203
|
+
|
|
204
|
+
if self.posX == -1 || self.posY == -1 {
|
|
205
|
+
// Auto-centering mode - use full dimensions
|
|
206
|
+
availableWidth = webViewWidth
|
|
207
|
+
availableHeight = webViewHeight - paddingBottom
|
|
208
|
+
} else {
|
|
209
|
+
// Manual positioning - calculate remaining space
|
|
210
|
+
availableWidth = webViewWidth - self.posX!
|
|
211
|
+
availableHeight = webViewHeight - self.posY! - paddingBottom
|
|
212
|
+
}
|
|
227
213
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
214
|
+
// Parse aspect ratio - convert to portrait orientation for camera use
|
|
215
|
+
let ratioParts = newAspectRatio.split(separator: ":").map { Double($0) ?? 1.0 }
|
|
216
|
+
// For camera, we want portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
|
|
217
|
+
let ratio = ratioParts[1] / ratioParts[0]
|
|
232
218
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
219
|
+
// Calculate maximum size that fits the aspect ratio in available space
|
|
220
|
+
let maxWidthByHeight = availableHeight * CGFloat(ratio)
|
|
221
|
+
let maxHeightByWidth = availableWidth / CGFloat(ratio)
|
|
236
222
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
print("[CameraPreview] Aspect ratio changed to \(newAspectRatio), new size: \(self.width!)x\(self.height!)")
|
|
223
|
+
if maxWidthByHeight <= availableWidth {
|
|
224
|
+
// Height is the limiting factor
|
|
225
|
+
self.width = maxWidthByHeight
|
|
226
|
+
self.height = availableHeight
|
|
227
|
+
} else {
|
|
228
|
+
// Width is the limiting factor
|
|
229
|
+
self.width = availableWidth
|
|
230
|
+
self.height = maxHeightByWidth
|
|
248
231
|
}
|
|
249
232
|
|
|
233
|
+
print("[CameraPreview] Aspect ratio changed to \(newAspectRatio), new size: \(self.width!)x\(self.height!)")
|
|
234
|
+
|
|
250
235
|
self.updateCameraFrame()
|
|
251
236
|
|
|
252
237
|
// Return the actual preview bounds
|
|
@@ -499,8 +484,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
499
484
|
// Display the camera preview on the configured view
|
|
500
485
|
try? self.cameraController.displayPreview(on: self.previewView)
|
|
501
486
|
|
|
502
|
-
|
|
503
|
-
self.cameraController.setupGestures(target: frontView ?? self.previewView, enableZoom: self.enableZoom!)
|
|
487
|
+
self.cameraController.setupGestures(target: self.previewView, enableZoom: self.enableZoom!)
|
|
504
488
|
|
|
505
489
|
// Add grid overlay if enabled
|
|
506
490
|
if self.gridMode != "none" {
|
|
@@ -679,11 +663,19 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
679
663
|
let withExifLocation = call.getBool("withExifLocation", false)
|
|
680
664
|
let width = call.getInt("width")
|
|
681
665
|
let height = call.getInt("height")
|
|
666
|
+
let aspectRatio = call.getString("aspectRatio")
|
|
682
667
|
|
|
683
|
-
|
|
668
|
+
// Check for conflicting parameters
|
|
669
|
+
if aspectRatio != nil && (width != nil || height != nil) {
|
|
670
|
+
print("[CameraPreview] Error: Cannot set both aspectRatio and size (width/height)")
|
|
671
|
+
call.reject("Cannot set both aspectRatio and size (width/height). Use setPreviewSize after start.")
|
|
672
|
+
return
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
print("[CameraPreview] Capture params - quality: \(quality), saveToGallery: \(saveToGallery), withExifLocation: \(withExifLocation), width: \(width ?? -1), height: \(height ?? -1), aspectRatio: \(aspectRatio ?? "nil")")
|
|
684
676
|
print("[CameraPreview] Current location: \(self.currentLocation?.description ?? "nil")")
|
|
685
677
|
|
|
686
|
-
self.cameraController.captureImage(width: width, height: height, quality: quality, gpsLocation: self.currentLocation) { (image, error) in
|
|
678
|
+
self.cameraController.captureImage(width: width, height: height, aspectRatio: aspectRatio, quality: quality, gpsLocation: self.currentLocation) { (image, error) in
|
|
687
679
|
print("[CameraPreview] captureImage callback received")
|
|
688
680
|
DispatchQueue.main.async {
|
|
689
681
|
print("[CameraPreview] Processing capture on main thread")
|
|
@@ -1304,65 +1296,79 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
1304
1296
|
}
|
|
1305
1297
|
}
|
|
1306
1298
|
|
|
1307
|
-
private func
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
DispatchQueue.main.async {
|
|
1315
|
-
self.updateCameraFrame()
|
|
1316
|
-
}
|
|
1317
|
-
return
|
|
1318
|
-
}
|
|
1299
|
+
private func calculateCameraFrame(x: CGFloat? = nil, y: CGFloat? = nil, width: CGFloat? = nil, height: CGFloat? = nil, aspectRatio: String? = nil) -> CGRect {
|
|
1300
|
+
// Use provided values or existing ones
|
|
1301
|
+
let currentWidth = width ?? self.width ?? UIScreen.main.bounds.size.width
|
|
1302
|
+
let currentHeight = height ?? self.height ?? UIScreen.main.bounds.size.height
|
|
1303
|
+
let currentX = x ?? self.posX ?? -1
|
|
1304
|
+
let currentY = y ?? self.posY ?? -1
|
|
1305
|
+
let currentAspectRatio = aspectRatio ?? self.aspectRatio
|
|
1319
1306
|
|
|
1320
1307
|
let paddingBottom = self.paddingBottom ?? 0
|
|
1321
|
-
|
|
1308
|
+
let adjustedHeight = currentHeight - CGFloat(paddingBottom)
|
|
1322
1309
|
|
|
1323
1310
|
// Cache webView dimensions for performance
|
|
1324
1311
|
let webViewWidth = self.webView?.frame.width ?? UIScreen.main.bounds.width
|
|
1325
1312
|
let webViewHeight = self.webView?.frame.height ?? UIScreen.main.bounds.height
|
|
1326
1313
|
|
|
1327
|
-
var finalX =
|
|
1328
|
-
var finalY =
|
|
1329
|
-
var finalWidth =
|
|
1330
|
-
var finalHeight =
|
|
1314
|
+
var finalX = currentX
|
|
1315
|
+
var finalY = currentY
|
|
1316
|
+
var finalWidth = currentWidth
|
|
1317
|
+
var finalHeight = adjustedHeight
|
|
1331
1318
|
|
|
1332
1319
|
// Handle auto-centering when position is -1
|
|
1333
|
-
if
|
|
1320
|
+
if currentX == -1 || currentY == -1 {
|
|
1334
1321
|
// Only override dimensions if aspect ratio is provided and no explicit dimensions given
|
|
1335
|
-
if let
|
|
1322
|
+
if let ratio = currentAspectRatio,
|
|
1323
|
+
currentWidth == UIScreen.main.bounds.size.width &&
|
|
1324
|
+
currentHeight == UIScreen.main.bounds.size.height {
|
|
1336
1325
|
finalWidth = webViewWidth
|
|
1337
1326
|
|
|
1338
1327
|
// Calculate height based on aspect ratio
|
|
1339
|
-
let ratioParts =
|
|
1328
|
+
let ratioParts = ratio.split(separator: ":").compactMap { Double($0) }
|
|
1340
1329
|
if ratioParts.count == 2 {
|
|
1341
1330
|
// For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
|
|
1342
|
-
let
|
|
1343
|
-
finalHeight = finalWidth / CGFloat(
|
|
1331
|
+
let ratioValue = ratioParts[1] / ratioParts[0]
|
|
1332
|
+
finalHeight = finalWidth / CGFloat(ratioValue)
|
|
1344
1333
|
}
|
|
1345
1334
|
}
|
|
1346
1335
|
|
|
1347
1336
|
// Center horizontally if x is -1
|
|
1348
|
-
if
|
|
1337
|
+
if currentX == -1 {
|
|
1349
1338
|
finalX = (webViewWidth - finalWidth) / 2
|
|
1350
1339
|
} else {
|
|
1351
|
-
finalX =
|
|
1340
|
+
finalX = currentX
|
|
1352
1341
|
}
|
|
1353
1342
|
|
|
1354
1343
|
// Center vertically if y is -1
|
|
1355
|
-
if
|
|
1344
|
+
if currentY == -1 {
|
|
1356
1345
|
// Use full screen height for centering
|
|
1357
1346
|
let screenHeight = UIScreen.main.bounds.size.height
|
|
1358
1347
|
finalY = (screenHeight - finalHeight) / 2
|
|
1359
1348
|
print("[CameraPreview] Centering vertically: screenHeight=\(screenHeight), finalHeight=\(finalHeight), finalY=\(finalY)")
|
|
1360
1349
|
} else {
|
|
1361
|
-
finalY =
|
|
1350
|
+
finalY = currentY
|
|
1362
1351
|
}
|
|
1363
1352
|
}
|
|
1364
1353
|
|
|
1365
|
-
|
|
1354
|
+
return CGRect(x: finalX, y: finalY, width: finalWidth, height: finalHeight)
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
private func updateCameraFrame() {
|
|
1358
|
+
guard let width = self.width, let height = self.height, let posX = self.posX, let posY = self.posY else {
|
|
1359
|
+
return
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// Ensure UI operations happen on main thread
|
|
1363
|
+
guard Thread.isMainThread else {
|
|
1364
|
+
DispatchQueue.main.async {
|
|
1365
|
+
self.updateCameraFrame()
|
|
1366
|
+
}
|
|
1367
|
+
return
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// Calculate the base frame using the factorized method
|
|
1371
|
+
var frame = calculateCameraFrame()
|
|
1366
1372
|
|
|
1367
1373
|
// Apply aspect ratio adjustments only if not auto-centering
|
|
1368
1374
|
if posX != -1 && posY != -1, let aspectRatio = self.aspectRatio {
|
|
@@ -1370,15 +1376,15 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
1370
1376
|
if ratioParts.count == 2 {
|
|
1371
1377
|
// For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
|
|
1372
1378
|
let ratio = ratioParts[1] / ratioParts[0]
|
|
1373
|
-
let currentRatio = Double(
|
|
1379
|
+
let currentRatio = Double(frame.width) / Double(frame.height)
|
|
1374
1380
|
|
|
1375
1381
|
if currentRatio > ratio {
|
|
1376
|
-
let newWidth = Double(
|
|
1377
|
-
frame.origin.x =
|
|
1382
|
+
let newWidth = Double(frame.height) * ratio
|
|
1383
|
+
frame.origin.x = frame.origin.x + (frame.width - CGFloat(newWidth)) / 2
|
|
1378
1384
|
frame.size.width = CGFloat(newWidth)
|
|
1379
1385
|
} else {
|
|
1380
|
-
let newHeight = Double(
|
|
1381
|
-
frame.origin.y =
|
|
1386
|
+
let newHeight = Double(frame.width) / ratio
|
|
1387
|
+
frame.origin.y = frame.origin.y + (frame.height - CGFloat(newHeight)) / 2
|
|
1382
1388
|
frame.size.height = CGFloat(newHeight)
|
|
1383
1389
|
}
|
|
1384
1390
|
}
|
|
@@ -1431,13 +1437,19 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
1431
1437
|
return
|
|
1432
1438
|
}
|
|
1433
1439
|
|
|
1434
|
-
//
|
|
1440
|
+
// Always set to -1 for auto-centering if not explicitly provided
|
|
1435
1441
|
if let x = call.getInt("x") {
|
|
1436
1442
|
self.posX = CGFloat(x)
|
|
1443
|
+
} else {
|
|
1444
|
+
self.posX = -1 // Auto-center if X not provided
|
|
1437
1445
|
}
|
|
1446
|
+
|
|
1438
1447
|
if let y = call.getInt("y") {
|
|
1439
1448
|
self.posY = CGFloat(y)
|
|
1449
|
+
} else {
|
|
1450
|
+
self.posY = -1 // Auto-center if Y not provided
|
|
1440
1451
|
}
|
|
1452
|
+
|
|
1441
1453
|
if let width = call.getInt("width") { self.width = CGFloat(width) }
|
|
1442
1454
|
if let height = call.getInt("height") { self.height = CGFloat(height) }
|
|
1443
1455
|
|
|
@@ -1487,7 +1499,7 @@ public class CameraPreview: CAPPlugin, CAPBridgedPlugin, CLLocationManagerDelega
|
|
|
1487
1499
|
}
|
|
1488
1500
|
let devicePoint = previewLayer.captureDevicePointConverted(fromLayerPoint: focusPoint)
|
|
1489
1501
|
|
|
1490
|
-
try self.cameraController.setFocus(at: devicePoint)
|
|
1502
|
+
try self.cameraController.setFocus(at: devicePoint, showIndicator: true, in: self.previewView)
|
|
1491
1503
|
call.resolve()
|
|
1492
1504
|
} catch {
|
|
1493
1505
|
call.reject("Failed to set focus: \(error.localizedDescription)")
|