Skip to content

Commit a0bf474

Browse files
WEB-476-fix(clients): preserve aspect ratio when capturing client image (#2852)
* fix(clients): preserve aspect ratio when capturing client image * Remove aspect-ratio and change object-fit: cover to object-fit: contain
1 parent f1b4ec2 commit a0bf474

File tree

3 files changed

+32
-4
lines changed

3 files changed

+32
-4
lines changed

src/app/clients/clients-view/custom-dialogs/capture-image-dialog/capture-image-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div class="layout-column gap-2px">
22
<h1 mat-dialog-title align="center">{{ 'labels.heading.Capture Client Image' | translate }}</h1>
33

4-
<video #video width="540" height="480" autoplay></video>
4+
<video #video class="capture-video" autoplay></video>
55

66
<!-- Using a class will break renderer changes -->
77
<canvas #canvas [ngStyle]="{ display: 'none' }"></canvas>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@use '../../../../../assets/styles/colours' as colors;
2+
3+
.capture-video {
4+
width: 100%;
5+
max-width: 640px;
6+
height: auto;
7+
object-fit: contain;
8+
border-radius: 4px;
9+
background-color: colors.$black;
10+
}

src/app/clients/clients-view/custom-dialogs/capture-image-dialog/capture-image-dialog.component.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,13 @@ export class CaptureImageDialogComponent implements AfterViewInit, OnDestroy {
6060
*/
6161
startCamera() {
6262
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
63+
const videoConstraints: MediaTrackConstraints = {
64+
width: { ideal: 640 },
65+
height: { ideal: 480 },
66+
facingMode: 'user'
67+
};
6368
navigator.mediaDevices
64-
.getUserMedia({ video: true })
69+
.getUserMedia({ video: videoConstraints })
6570
.then((stream: MediaStream) => {
6671
this.renderer.setProperty(this.video.nativeElement, 'srcObject', stream);
6772
this.video.nativeElement.play();
@@ -101,13 +106,26 @@ export class CaptureImageDialogComponent implements AfterViewInit, OnDestroy {
101106

102107
/**
103108
* Captures the image by drawing video state on canvas, then converts canvas state to data URL.
109+
* Uses actual video dimensions to prevent aspect ratio distortion.
104110
* See https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL for details.
105111
*/
106112
capture() {
107113
this.isCaptured = true;
108114
this.video.nativeElement.pause();
109-
this.canvas.nativeElement.getContext('2d').drawImage(this.video.nativeElement, 0, 0, 150, 150);
110-
this.clientImageDataURL = this.canvas.nativeElement.toDataURL();
115+
116+
// Get actual video stream dimensions to preserve aspect ratio
117+
const videoWidth = this.video.nativeElement.videoWidth;
118+
const videoHeight = this.video.nativeElement.videoHeight;
119+
120+
// Set canvas dimensions to match video stream
121+
this.canvas.nativeElement.width = videoWidth;
122+
this.canvas.nativeElement.height = videoHeight;
123+
124+
// Draw the video frame at full resolution without distortion
125+
this.canvas.nativeElement.getContext('2d').drawImage(this.video.nativeElement, 0, 0, videoWidth, videoHeight);
126+
127+
// Convert to data URL with JPEG format for smaller file size
128+
this.clientImageDataURL = this.canvas.nativeElement.toDataURL('image/jpeg', 0.9);
111129
}
112130

113131
/**

0 commit comments

Comments
 (0)