@capgo/camera-preview 8.2.1 → 8.3.0
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 +31 -29
- package/android/build.gradle +4 -0
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraPreview.java +87 -20
- package/android/src/main/java/app/capgo/capacitor/camera/preview/CameraXView.java +665 -188
- package/android/src/main/java/app/capgo/capacitor/camera/preview/model/CameraSessionConfiguration.java +13 -0
- package/dist/docs.json +17 -1
- package/dist/esm/definitions.d.ts +9 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +1 -1
- package/dist/esm/web.js +120 -92
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +119 -92
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +119 -92
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreviewPlugin/CameraController.swift +14 -12
- package/ios/Sources/CapgoCameraPreviewPlugin/Plugin.swift +16 -14
- package/package.json +9 -8
package/dist/plugin.cjs.js
CHANGED
|
@@ -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
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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 (
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
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
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
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
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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(
|
|
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');
|