Created
January 29, 2025 15:07
-
-
Save leemartin/6c7f8c6d563af8db3a76749938d35592 to your computer and use it in GitHub Desktop.
Camera composable for Vue written in Typescript
This file contains hidden or 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