store/resources/js/composables/useWebcamCapture.ts

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,
};
}