Created
January 29, 2025 15:07
Camera composable for Vue written in Typescript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const useCamera = () => { | |
// State | |
const cameraFacing = useState<ConstrainDOMString | undefined>("cameraFacing", () => 'environment') | |
const cameraStream = useState<MediaStream | undefined>("cameraStream", () => undefined) | |
// Start camera | |
// ---------- | |
const start = async () => { | |
// Promise | |
return new Promise(async (resolve, revoke) => { | |
try { | |
// Get camera | |
const stream = await navigator.mediaDevices.getUserMedia({ | |
video: { | |
facingMode: cameraFacing.value | |
} | |
}) | |
// Get video tag | |
let video = document.getElementById("cameraVideo") as HTMLMediaElement | |
// If video null | |
if (video === null) { | |
// Log | |
console.error("Video tag not found.") | |
// Revoke | |
revoke() | |
} else { | |
// Replace video tag source | |
video.srcObject = stream | |
// Video ready | |
video.onloadedmetadata = async () => { | |
// Update camera stream | |
cameraStream.value = stream | |
// Resolve | |
resolve("Camera successfully started.") | |
} | |
} | |
} catch (e: any) { | |
// Camera error | |
switch (e.name) { | |
case "NotFoundError": | |
revoke("Please enable the camera on your device.") | |
break | |
case "NotAllowedError": | |
revoke("Please allow access to your camera.") | |
break | |
case "NotReadableError": | |
revoke("Please close all other tabs which are using your camera.") | |
break | |
default: | |
revoke("This experience requires access to your camera.") | |
} | |
} | |
}) | |
} | |
// Stop camera | |
// ---------- | |
const stop = async () => { | |
// If stream exists | |
if (cameraStream.value) { | |
// Stop all streams | |
cameraStream.value.getTracks().forEach(track => track.stop()) | |
// Set stream to undefined | |
cameraStream.value = undefined | |
} | |
} | |
// Flip camera | |
// ---------- | |
const flip = async () => { | |
// Stop camera | |
stop() | |
// Check facing | |
if (cameraFacing.value == 'environment') { | |
// Face user | |
cameraFacing.value = 'user' | |
} else { | |
// Face environment | |
cameraFacing.value = 'environment' | |
} | |
// Start camera | |
start() | |
} | |
// Return | |
return { | |
flip, | |
start, | |
stop | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment