forked from trent_larson/crowd-funder-for-time-pwa
Update: front-facing camera mirrored preview
This commit is contained in:
@@ -94,6 +94,19 @@
|
||||
<strong>Platform:</strong>
|
||||
{{ platformCapabilities.isMobile ? "Mobile" : "Desktop" }}
|
||||
</p>
|
||||
<p><strong>Camera Mode:</strong> {{ currentFacingMode }}</p>
|
||||
<p>
|
||||
<strong>Video Mirrored:</strong>
|
||||
{{ shouldMirrorVideo ? "Yes" : "No" }}
|
||||
</p>
|
||||
<p>
|
||||
<strong>Mirror Logic:</strong>
|
||||
{{
|
||||
platformCapabilities.isMobile
|
||||
? "Mobile: user mode only"
|
||||
: "Desktop: always mirrored"
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,10 +122,19 @@
|
||||
<video
|
||||
ref="videoElement"
|
||||
class="camera-video w-full h-full object-cover"
|
||||
:class="{ 'mirror-video': shouldMirrorVideo }"
|
||||
autoplay
|
||||
playsinline
|
||||
muted
|
||||
></video>
|
||||
<!-- Mirror indicator -->
|
||||
<div
|
||||
v-if="shouldMirrorVideo"
|
||||
class="absolute top-2 left-2 bg-black/50 text-white px-2 py-1 rounded text-xs"
|
||||
>
|
||||
<font-awesome icon="mirror" class="w-[1em] mr-1" />
|
||||
Mirrored
|
||||
</div>
|
||||
<div :class="cameraControlsClasses">
|
||||
<button
|
||||
:class="cameraControlButtonClasses"
|
||||
@@ -444,6 +466,22 @@ export default class ImageMethodDialog extends Vue {
|
||||
return "max-h-[50vh] max-w-[90vw] object-contain";
|
||||
}
|
||||
|
||||
/**
|
||||
* Computed property to determine if video should be mirrored
|
||||
* Mirrors video for front-facing camera (user-facing) but not back camera
|
||||
* This applies to both desktop and mobile when using front-facing cameras
|
||||
*/
|
||||
get shouldMirrorVideo(): boolean {
|
||||
// On desktop, most webcams face the user, so we should mirror regardless of facingMode
|
||||
// On mobile, only mirror when using front-facing camera (user mode)
|
||||
if (this.platformCapabilities.isMobile) {
|
||||
return this.currentFacingMode === "user";
|
||||
} else {
|
||||
// Desktop: mirror by default since webcams typically face the user
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Props
|
||||
@Prop({ default: true }) isRegistered!: boolean;
|
||||
@Prop({
|
||||
@@ -482,8 +520,15 @@ export default class ImageMethodDialog extends Vue {
|
||||
this.crop = !!crop;
|
||||
this.imageCallback = setImageFn;
|
||||
this.visible = true;
|
||||
|
||||
// Use provided default camera mode, or intelligently choose based on platform
|
||||
this.currentFacingMode = this.defaultCameraMode as "environment" | "user";
|
||||
|
||||
// Log camera mode for debugging
|
||||
logger.debug("Camera facing mode:", this.currentFacingMode);
|
||||
logger.debug("Should mirror video:", this.shouldMirrorVideo);
|
||||
logger.debug("Platform capabilities:", this.platformCapabilities);
|
||||
|
||||
// Start camera preview immediately
|
||||
logger.debug("Starting camera preview from open()");
|
||||
this.startCameraPreview();
|
||||
@@ -646,7 +691,19 @@ export default class ImageMethodDialog extends Vue {
|
||||
canvas.width = videoElement.videoWidth;
|
||||
canvas.height = videoElement.videoHeight;
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx?.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
if (!ctx) {
|
||||
throw new Error("Could not get canvas context");
|
||||
}
|
||||
|
||||
// If video is mirrored, flip the canvas horizontally
|
||||
// to capture the image in the correct orientation
|
||||
if (this.shouldMirrorVideo) {
|
||||
ctx.scale(-1, 1);
|
||||
ctx.translate(-canvas.width, 0);
|
||||
}
|
||||
|
||||
ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
||||
|
||||
canvas.toBlob(
|
||||
(blob) => {
|
||||
@@ -833,4 +890,9 @@ export default class ImageMethodDialog extends Vue {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Mirror video for front-facing camera */
|
||||
.mirror-video {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user