@capgo/camera-preview 8.2.2 → 8.3.1

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.
Files changed (33) hide show
  1. package/README.md +31 -29
  2. package/android/build.gradle +4 -0
  3. package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +87 -20
  4. package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraXView.java +551 -157
  5. package/android/src/main/java/app/capgo/capacitor/camera/preview/model/CameraSessionConfiguration.java +13 -0
  6. package/dist/docs.json +17 -1
  7. package/dist/esm/definitions.d.ts +9 -1
  8. package/dist/esm/definitions.js.map +1 -1
  9. package/dist/esm/web.d.ts +1 -1
  10. package/dist/esm/web.js +120 -92
  11. package/dist/esm/web.js.map +1 -1
  12. package/dist/plugin.cjs.js +119 -92
  13. package/dist/plugin.cjs.js.map +1 -1
  14. package/dist/plugin.js +119 -92
  15. package/dist/plugin.js.map +1 -1
  16. package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +14 -12
  17. package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +16 -14
  18. package/package.json +8 -7
  19. package/android/.gradle/8.14.4/checksums/checksums.lock +0 -0
  20. package/android/.gradle/8.14.4/checksums/md5-checksums.bin +0 -0
  21. package/android/.gradle/8.14.4/checksums/sha1-checksums.bin +0 -0
  22. package/android/.gradle/8.14.4/executionHistory/executionHistory.bin +0 -0
  23. package/android/.gradle/8.14.4/executionHistory/executionHistory.lock +0 -0
  24. package/android/.gradle/8.14.4/fileChanges/last-build.bin +0 -0
  25. package/android/.gradle/8.14.4/fileHashes/fileHashes.bin +0 -0
  26. package/android/.gradle/8.14.4/fileHashes/fileHashes.lock +0 -0
  27. package/android/.gradle/8.14.4/fileHashes/resourceHashesCache.bin +0 -0
  28. package/android/.gradle/8.14.4/gc.properties +0 -0
  29. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  30. package/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  31. package/android/.gradle/buildOutputCleanup/outputFiles.bin +0 -0
  32. package/android/.gradle/file-system.probe +0 -0
  33. package/android/.gradle/vcs-1/gc.properties +0 -0
@@ -307,103 +307,130 @@ class CameraPreviewWeb extends core.WebPlugin {
307
307
  height: container.offsetHeight,
308
308
  id: container.id,
309
309
  });
310
+ const containerWidth = container.offsetWidth || window.innerWidth;
311
+ const containerHeight = container.offsetHeight || window.innerHeight;
310
312
  // Now adjust video element size based on camera's native aspect ratio
311
- if (!options.width && !options.height && !options.aspectRatio) {
312
- // No size specified, fit camera view within container bounds
313
- const containerWidth = container.offsetWidth || window.innerWidth;
314
- const containerHeight = container.offsetHeight || window.innerHeight;
315
- // Calculate dimensions that fit within container while maintaining camera aspect ratio
316
- let targetWidth, targetHeight;
317
- // Try fitting to container width first
318
- targetWidth = containerWidth;
319
- targetHeight = targetWidth / cameraAspectRatio;
320
- // If height exceeds container, fit to height instead
321
- if (targetHeight > containerHeight) {
322
- targetHeight = containerHeight;
323
- targetWidth = targetHeight * cameraAspectRatio;
324
- }
325
- console.log('Video element dimensions:', {
326
- width: targetWidth,
327
- height: targetHeight,
328
- container: { width: containerWidth, height: containerHeight },
329
- });
330
- this.videoElement.width = targetWidth;
331
- this.videoElement.height = targetHeight;
332
- this.videoElement.style.width = `${targetWidth}px`;
333
- this.videoElement.style.height = `${targetHeight}px`;
334
- // Center the video element within its parent container
335
- if (needsCenterX || options.x === undefined) {
336
- const x = Math.round((containerWidth - targetWidth) / 2);
337
- this.videoElement.style.left = `${x}px`;
313
+ if (!options.width && !options.height) {
314
+ if (aspectMode === 'cover') {
315
+ // Fill the container and rely on object-fit: cover to crop
316
+ const targetWidth = containerWidth;
317
+ const targetHeight = containerHeight;
318
+ this.videoElement.width = targetWidth;
319
+ this.videoElement.height = targetHeight;
320
+ this.videoElement.style.width = `${targetWidth}px`;
321
+ this.videoElement.style.height = `${targetHeight}px`;
322
+ if (needsCenterX || options.x === undefined) {
323
+ const x = Math.round((containerWidth - targetWidth) / 2);
324
+ this.videoElement.style.left = `${x}px`;
325
+ }
326
+ if (needsCenterY || options.y === undefined) {
327
+ let y;
328
+ switch (positioning) {
329
+ case 'top':
330
+ y = 0;
331
+ break;
332
+ case 'bottom':
333
+ y = containerHeight - targetHeight;
334
+ break;
335
+ case 'center':
336
+ default:
337
+ y = Math.round((containerHeight - targetHeight) / 2);
338
+ break;
339
+ }
340
+ this.videoElement.style.setProperty('top', `${y}px`, 'important');
341
+ }
338
342
  }
339
- if (needsCenterY || options.y === undefined) {
340
- let y;
341
- switch (positioning) {
342
- case 'top':
343
- y = 0;
344
- break;
345
- case 'bottom':
346
- y = window.innerHeight - targetHeight;
347
- break;
348
- case 'center':
349
- default:
350
- y = Math.round((window.innerHeight - targetHeight) / 2);
351
- break;
343
+ else if (!options.aspectRatio) {
344
+ // No size specified, fit camera view within container bounds
345
+ // Calculate dimensions that fit within container while maintaining camera aspect ratio
346
+ let targetWidth = containerWidth;
347
+ let targetHeight = targetWidth / cameraAspectRatio;
348
+ // If height exceeds container, fit to height instead
349
+ if (targetHeight > containerHeight) {
350
+ targetHeight = containerHeight;
351
+ targetWidth = targetHeight * cameraAspectRatio;
352
352
  }
353
- this.videoElement.style.setProperty('top', `${y}px`, 'important');
354
- // Force a style recalculation
355
- this.videoElement.offsetHeight;
356
- console.log('Positioning video:', {
357
- positioning,
358
- viewportHeight: window.innerHeight,
359
- targetHeight,
360
- calculatedY: y,
361
- actualTop: this.videoElement.style.top,
362
- position: this.videoElement.style.position,
353
+ console.log('Video element dimensions:', {
354
+ width: targetWidth,
355
+ height: targetHeight,
356
+ container: { width: containerWidth, height: containerHeight },
363
357
  });
358
+ this.videoElement.width = targetWidth;
359
+ this.videoElement.height = targetHeight;
360
+ this.videoElement.style.width = `${targetWidth}px`;
361
+ this.videoElement.style.height = `${targetHeight}px`;
362
+ // Center the video element within its parent container
363
+ if (needsCenterX || options.x === undefined) {
364
+ const x = Math.round((containerWidth - targetWidth) / 2);
365
+ this.videoElement.style.left = `${x}px`;
366
+ }
367
+ if (needsCenterY || options.y === undefined) {
368
+ let y;
369
+ switch (positioning) {
370
+ case 'top':
371
+ y = 0;
372
+ break;
373
+ case 'bottom':
374
+ y = window.innerHeight - targetHeight;
375
+ break;
376
+ case 'center':
377
+ default:
378
+ y = Math.round((window.innerHeight - targetHeight) / 2);
379
+ break;
380
+ }
381
+ this.videoElement.style.setProperty('top', `${y}px`, 'important');
382
+ // Force a style recalculation
383
+ this.videoElement.offsetHeight;
384
+ console.log('Positioning video:', {
385
+ positioning,
386
+ viewportHeight: window.innerHeight,
387
+ targetHeight,
388
+ calculatedY: y,
389
+ actualTop: this.videoElement.style.top,
390
+ position: this.videoElement.style.position,
391
+ });
392
+ }
364
393
  }
365
- }
366
- else if (effectiveAspectRatio && !options.width && !options.height) {
367
- // Aspect ratio specified but no size
368
- const [widthRatio, heightRatio] = effectiveAspectRatio.split(':').map(Number);
369
- const targetRatio = widthRatio / heightRatio;
370
- const viewportWidth = window.innerWidth;
371
- const viewportHeight = window.innerHeight;
372
- let targetWidth, targetHeight;
373
- // Try fitting to viewport width first
374
- targetWidth = viewportWidth;
375
- targetHeight = targetWidth / targetRatio;
376
- // If height exceeds viewport, fit to height instead
377
- if (targetHeight > viewportHeight) {
378
- targetHeight = viewportHeight;
379
- targetWidth = targetHeight * targetRatio;
380
- }
381
- this.videoElement.width = targetWidth;
382
- this.videoElement.height = targetHeight;
383
- this.videoElement.style.width = `${targetWidth}px`;
384
- this.videoElement.style.height = `${targetHeight}px`;
385
- // Center the video element within its parent container
386
- if (needsCenterX || options.x === undefined) {
387
- const parentWidth = container.offsetWidth || viewportWidth;
388
- const x = Math.round((parentWidth - targetWidth) / 2);
389
- this.videoElement.style.left = `${x}px`;
390
- }
391
- if (needsCenterY || options.y === undefined) {
392
- const parentHeight = container.offsetHeight || viewportHeight;
393
- let y;
394
- switch (positioning) {
395
- case 'top':
396
- y = 0;
397
- break;
398
- case 'bottom':
399
- y = parentHeight - targetHeight;
400
- break;
401
- case 'center':
402
- default:
403
- y = Math.round((parentHeight - targetHeight) / 2);
404
- break;
394
+ else if (effectiveAspectRatio) {
395
+ // Aspect ratio specified but no size
396
+ const [widthRatio, heightRatio] = effectiveAspectRatio.split(':').map(Number);
397
+ const targetRatio = widthRatio / heightRatio;
398
+ const viewportWidth = window.innerWidth;
399
+ const viewportHeight = window.innerHeight;
400
+ let targetWidth = viewportWidth;
401
+ let targetHeight = targetWidth / targetRatio;
402
+ // If height exceeds viewport, fit to height instead
403
+ if (targetHeight > viewportHeight) {
404
+ targetHeight = viewportHeight;
405
+ targetWidth = targetHeight * targetRatio;
406
+ }
407
+ this.videoElement.width = targetWidth;
408
+ this.videoElement.height = targetHeight;
409
+ this.videoElement.style.width = `${targetWidth}px`;
410
+ this.videoElement.style.height = `${targetHeight}px`;
411
+ // Center the video element within its parent container
412
+ if (needsCenterX || options.x === undefined) {
413
+ const parentWidth = container.offsetWidth || viewportWidth;
414
+ const x = Math.round((parentWidth - targetWidth) / 2);
415
+ this.videoElement.style.left = `${x}px`;
416
+ }
417
+ if (needsCenterY || options.y === undefined) {
418
+ const parentHeight = container.offsetHeight || viewportHeight;
419
+ let y;
420
+ switch (positioning) {
421
+ case 'top':
422
+ y = 0;
423
+ break;
424
+ case 'bottom':
425
+ y = parentHeight - targetHeight;
426
+ break;
427
+ case 'center':
428
+ default:
429
+ y = Math.round((parentHeight - targetHeight) / 2);
430
+ break;
431
+ }
432
+ this.videoElement.style.top = `${y}px`;
405
433
  }
406
- this.videoElement.style.top = `${y}px`;
407
434
  }
408
435
  }
409
436
  this.videoElement.srcObject = stream;
@@ -633,7 +660,7 @@ class CameraPreviewWeb extends core.WebPlugin {
633
660
  recorder.stop();
634
661
  });
635
662
  }
636
- async startRecordVideo(_options) {
663
+ async startRecordVideo(options) {
637
664
  const video = document.getElementById(DEFAULT_VIDEO_ID);
638
665
  if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
639
666
  throw new Error('camera is not running');