diff --git a/src/components.d.ts b/src/components.d.ts index e6b3846..4e0123d 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -9,6 +9,7 @@ import { HTMLStencilElement, JSXBase } from '@stencil/core/internal'; import { ActionSheetOption, + FacingMode, } from './definitions'; export namespace Components { @@ -18,7 +19,7 @@ export namespace Components { 'options': ActionSheetOption[]; } interface PwaCamera { - 'facingMode': string; + 'facingMode': FacingMode; 'handleNoDeviceError': (e?: any) => void; 'handlePhoto': (photo: Blob) => void; 'noDevicesButtonText': string; @@ -26,11 +27,11 @@ export namespace Components { } interface PwaCameraModal { 'dismiss': () => Promise; - 'facingMode': string; + 'facingMode': FacingMode; 'present': () => Promise; } interface PwaCameraModalInstance { - 'facingMode': string; + 'facingMode': FacingMode; 'noDevicesButtonText': string; 'noDevicesText': string; } @@ -89,19 +90,19 @@ declare namespace LocalJSX { 'options'?: ActionSheetOption[]; } interface PwaCamera { - 'facingMode'?: string; + 'facingMode'?: FacingMode; 'handleNoDeviceError'?: (e?: any) => void; 'handlePhoto'?: (photo: Blob) => void; 'noDevicesButtonText'?: string; 'noDevicesText'?: string; } interface PwaCameraModal { - 'facingMode'?: string; + 'facingMode'?: FacingMode; 'onNoDeviceError'?: (event: CustomEvent) => void; 'onOnPhoto'?: (event: CustomEvent) => void; } interface PwaCameraModalInstance { - 'facingMode'?: string; + 'facingMode'?: FacingMode; 'noDevicesButtonText'?: string; 'noDevicesText'?: string; 'onNoDeviceError'?: (event: CustomEvent) => void; diff --git a/src/components/camera-modal/camera-modal-instance.tsx b/src/components/camera-modal/camera-modal-instance.tsx index 80cf6e4..9218809 100644 --- a/src/components/camera-modal/camera-modal-instance.tsx +++ b/src/components/camera-modal/camera-modal-instance.tsx @@ -1,4 +1,5 @@ import { h, Event, EventEmitter, Component, Listen, Element, Prop } from '@stencil/core'; +import { FacingMode } from '../../definitions'; @Component({ tag: 'pwa-camera-modal-instance', @@ -9,7 +10,7 @@ export class PWACameraModal { @Element() el; @Event() onPhoto: EventEmitter; @Event() noDeviceError: EventEmitter; - @Prop() facingMode: string = 'user'; + @Prop() facingMode: FacingMode = 'user'; @Prop() noDevicesText = 'No camera found'; @Prop() noDevicesButtonText = 'Choose image'; diff --git a/src/components/camera-modal/camera-modal.tsx b/src/components/camera-modal/camera-modal.tsx index 23da668..4bfa1a7 100644 --- a/src/components/camera-modal/camera-modal.tsx +++ b/src/components/camera-modal/camera-modal.tsx @@ -1,4 +1,5 @@ import { h, Event, EventEmitter, Component, Method, Prop } from '@stencil/core'; +import { FacingMode } from '../../definitions'; @Component({ tag: 'pwa-camera-modal', @@ -6,8 +7,9 @@ import { h, Event, EventEmitter, Component, Method, Prop } from '@stencil/core'; shadow: true }) export class PWACameraModal { - @Prop() facingMode: string = 'user'; + @Prop() facingMode: FacingMode = 'user'; + @Event() onPhoto: EventEmitter; @Event() noDeviceError: EventEmitter; diff --git a/src/components/camera/camera.css b/src/components/camera/camera.css index b328579..abcf441 100644 --- a/src/components/camera/camera.css +++ b/src/components/camera/camera.css @@ -92,6 +92,8 @@ video { min-height: 100%; object-fit: cover; background-color: black; + -webkit-transform: initial; + transform: initial; } .pick-image { diff --git a/src/components/camera/camera.tsx b/src/components/camera/camera.tsx index 9f575bd..93c6593 100644 --- a/src/components/camera/camera.tsx +++ b/src/components/camera/camera.tsx @@ -1,6 +1,6 @@ import { h, Component, Element, Prop, State } from '@stencil/core'; -import { FlashMode } from '../../definitions'; +import { FacingMode, FlashMode } from '../../definitions'; import './imagecapture'; @@ -13,11 +13,13 @@ declare var window: any; shadow: true }) export class CameraPWA { + protected isRotate: boolean; + @Element() el; @Prop({ context: 'isServer' }) private isServer: boolean; - @Prop() facingMode: string = 'user'; + @Prop() facingMode: FacingMode = 'user'; @Prop() handlePhoto: (photo: Blob) => void; @Prop() handleNoDeviceError: (e?: any) => void; @@ -94,7 +96,7 @@ export class CameraPWA { this.hasCamera = !!videoDevices.length; this.hasMultipleCameras = videoDevices.length > 1; - } catch(e) { + } catch (e) { this.deviceError = e; } } @@ -110,9 +112,8 @@ export class CameraPWA { audio: false, ...constraints }); - this.initStream(stream); - } catch(e) { + } catch (e) { this.deviceError = e; this.handleNoDeviceError && this.handleNoDeviceError(e); } @@ -129,7 +130,7 @@ export class CameraPWA { this.deviceError = 'No image capture'; this.handleNoDeviceError && this.handleNoDeviceError(); } - + this.isRotate = false; // Always re-render this.el.forceUpdate(); } @@ -158,12 +159,13 @@ export class CameraPWA { } async capture() { + this.photo = null; if (this.hasImageCapture()) { try { const photo = await this.imageCapture.takePhoto({ fillLightMode: this.flashModes.length > 1 ? this.flashMode : undefined }); - + await this.flashScreen(); this.promptAccept(photo); @@ -203,7 +205,7 @@ export class CameraPWA { break; } } - + this.photoSrc = URL.createObjectURL(photo); } @@ -246,36 +248,29 @@ export class CameraPWA { }); } - rotate() { - this.stopStream(); - - const track = this.stream && this.stream.getTracks()[0]; - if (!track) { - return; + getFacingMode(stream) { + const track = stream && stream.getTracks()[0]; + if (track) { + let c = track.getConstraints() || track.getCapabilities() || { facingMode: [] }; + return Array.isArray(c.facingMode) ? c.facingMode[0] : c.facingMode; } + return; + } - let c = track.getConstraints(); - let facingMode = c.facingMode; - - if (!facingMode) { - let c = track.getCapabilities(); - if (c.facingMode) { - facingMode = c.facingMode[0]; - } + rotate() { + if (this.isRotate) { + return; } - - if (facingMode === 'environment') { + if (this.hasMultipleCameras) { + this.isRotate = true; + this.stopStream(); this.initCamera({ video: { - facingMode: 'user' + facingMode: this.getFacingMode(this.stream) === 'user' ? 'environment' : 'user' } }); } else { - this.initCamera({ - video: { - facingMode: 'environment' - } - }); + console.warn('not has multiples cameras'); } } @@ -296,7 +291,7 @@ export class CameraPWA { this.showShutterOverlay = true; setTimeout(() => { this.showShutterOverlay = false; - resolve(); + resolve(true); }, 100); }); } @@ -305,7 +300,6 @@ export class CameraPWA { } handleShutterClick = (_e: Event) => { - console.debug('shutter click'); this.capture(); } @@ -322,15 +316,14 @@ export class CameraPWA { } handleCancelPhoto = (_e: Event) => { - const track = this.stream && this.stream.getTracks()[0]; - let c = track && track.getConstraints(); + const facingMode = this.getFacingMode(this.stream); this.photo = null; this.photoSrc = null; - if (c) { + if (facingMode) { this.initCamera({ video: { - facingMode: c.facingMode + facingMode } }); } else { @@ -366,7 +359,7 @@ export class CameraPWA { iconPhotos() { return ( - + ); } @@ -408,11 +401,11 @@ export class CameraPWA {
this.handleFlashClick(e)}> {this.flashModes.length > 0 && ( -
- {this.flashMode == 'off' ? : ''} - {this.flashMode == 'auto' ? : ''} - {this.flashMode == 'flash' ? : ''} -
+
+ {this.flashMode == 'off' ? : ''} + {this.flashMode == 'auto' ? : ''} + {this.flashMode == 'flash' ? : ''} +
)}
@@ -435,64 +428,64 @@ export class CameraPWA { )} {/* Show the taken photo for the Accept UI*/} {this.photoSrc ? ( -
-
-
+
+
+
) : ( -
- {this.showShutterOverlay && ( -
+
+ {this.showShutterOverlay && ( +
+
+ )} + {this.hasImageCapture() ? ( +
- )} - {this.hasImageCapture() ? ( -
- )} + )} {this.hasCamera && ( - + )}
); diff --git a/src/definitions.ts b/src/definitions.ts index 9e666e4..d17498b 100644 --- a/src/definitions.ts +++ b/src/definitions.ts @@ -11,6 +11,8 @@ export interface PhotoCapabilities { fillLightMode: string[]; } +export type FacingMode = 'user' | 'environment'; + export type FlashMode = "auto" | "off" | "flash"; export interface ActionSheetOption { diff --git a/src/index.html b/src/index.html index 6a0f5b6..59cf169 100644 --- a/src/index.html +++ b/src/index.html @@ -29,6 +29,7 @@ var b = document.querySelector('#camera-button'); b.addEventListener('click', async (ev) => { const camera = document.createElement('pwa-camera-modal'); + camera.facingMode = 'environment'; document.body.appendChild(camera);