69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
export function useWebcamCapture() {
|
|
let stream: MediaStream | null = null;
|
|
|
|
async function startCamera(videoElement: HTMLVideoElement): Promise<void> {
|
|
stream = await navigator.mediaDevices.getUserMedia({
|
|
video: {
|
|
facingMode: 'user',
|
|
width: { ideal: 1280 },
|
|
height: { ideal: 720 },
|
|
},
|
|
audio: false,
|
|
});
|
|
|
|
videoElement.srcObject = stream;
|
|
await videoElement.play();
|
|
}
|
|
|
|
function stopCamera(): void {
|
|
stream?.getTracks().forEach((track) => track.stop());
|
|
stream = null;
|
|
}
|
|
|
|
function captureWithLocationTag(videoElement: HTMLVideoElement, locationTag: string): string {
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = videoElement.videoWidth;
|
|
canvas.height = videoElement.videoHeight;
|
|
|
|
const context = canvas.getContext('2d');
|
|
|
|
if (!context) {
|
|
throw new Error('Gagal menyiapkan kanvas foto.');
|
|
}
|
|
|
|
context.save();
|
|
context.translate(canvas.width, 0);
|
|
context.scale(-1, 1);
|
|
context.drawImage(videoElement, 0, 0, canvas.width, canvas.height);
|
|
context.restore();
|
|
|
|
const lines = locationTag.split('\n').filter((line) => line.trim() !== '');
|
|
const fontSize = Math.max(14, Math.round(canvas.height * 0.028));
|
|
const padding = 12;
|
|
const lineHeight = fontSize + 8;
|
|
const barHeight = lines.length * lineHeight + padding * 2;
|
|
|
|
context.fillStyle = 'rgba(0, 0, 0, 0.7)';
|
|
context.fillRect(0, canvas.height - barHeight, canvas.width, barHeight);
|
|
|
|
context.fillStyle = '#ffffff';
|
|
context.font = `600 ${fontSize}px system-ui, sans-serif`;
|
|
|
|
lines.forEach((line, index) => {
|
|
context.fillText(
|
|
line,
|
|
padding,
|
|
canvas.height - barHeight + padding + fontSize + index * lineHeight,
|
|
);
|
|
});
|
|
|
|
return canvas.toDataURL('image/jpeg', 0.85);
|
|
}
|
|
|
|
return {
|
|
startCamera,
|
|
stopCamera,
|
|
captureWithLocationTag,
|
|
};
|
|
}
|