export function useWebcamCapture() { let stream: MediaStream | null = null; async function startCamera(videoElement: HTMLVideoElement): Promise { 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, }; }