select für kamera-input
This commit is contained in:
parent
60fbe46fbf
commit
6158c9d9e0
@ -24,6 +24,11 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="camera-select-wrap" class="mt-3 w-full max-w-xs hidden">
|
||||||
|
<select id="camera-select"
|
||||||
|
class="w-full rounded-full bg-black/50 text-white border border-white/20 px-5 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-white/40 appearance-none text-center"></select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button id="capture-btn"
|
<button id="capture-btn"
|
||||||
wire:loading.attr="disabled"
|
wire:loading.attr="disabled"
|
||||||
@disabled($hasProcessing)
|
@disabled($hasProcessing)
|
||||||
@ -101,20 +106,73 @@
|
|||||||
const flash = document.getElementById('flash');
|
const flash = document.getElementById('flash');
|
||||||
const countdown = document.getElementById('countdown');
|
const countdown = document.getElementById('countdown');
|
||||||
const countdownNum = document.getElementById('countdown-num');
|
const countdownNum = document.getElementById('countdown-num');
|
||||||
|
const cameraSelectWrap = document.getElementById('camera-select-wrap');
|
||||||
|
const cameraSelect = document.getElementById('camera-select');
|
||||||
|
|
||||||
|
const CAMERA_STORAGE_KEY = 'photobox_camera_id';
|
||||||
|
|
||||||
|
function videoConstraints(deviceId) {
|
||||||
|
const base = { width: { ideal: 4096 }, height: { ideal: 2160 } };
|
||||||
|
return deviceId ? { ...base, deviceId: { exact: deviceId } } : base;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startCamera(deviceId) {
|
||||||
|
if (video.srcObject) {
|
||||||
|
video.srcObject.getTracks().forEach(track => track.stop());
|
||||||
|
}
|
||||||
|
|
||||||
async function startCamera() {
|
|
||||||
try {
|
try {
|
||||||
const stream = await navigator.mediaDevices.getUserMedia({
|
const stream = await navigator.mediaDevices.getUserMedia({
|
||||||
video: { width: { ideal: 4096 }, height: { ideal: 2160 } },
|
video: videoConstraints(deviceId),
|
||||||
audio: false,
|
audio: false,
|
||||||
});
|
});
|
||||||
video.srcObject = stream;
|
video.srcObject = stream;
|
||||||
} catch {
|
btn.disabled = false;
|
||||||
|
} catch (err) {
|
||||||
|
if (deviceId && err.name === 'OverconstrainedError') {
|
||||||
|
localStorage.removeItem(CAMERA_STORAGE_KEY);
|
||||||
|
return startCamera(null);
|
||||||
|
}
|
||||||
$wire.set('status', 'Camera access denied or unavailable.');
|
$wire.set('status', 'Camera access denied or unavailable.');
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function populateCameraList() {
|
||||||
|
let devices;
|
||||||
|
try {
|
||||||
|
devices = await navigator.mediaDevices.enumerateDevices();
|
||||||
|
} catch {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cameras = devices.filter(d => d.kind === 'videoinput');
|
||||||
|
if (cameras.length < 2) {
|
||||||
|
cameraSelectWrap.classList.add('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraSelect.innerHTML = '';
|
||||||
|
cameras.forEach((cam, index) => {
|
||||||
|
const option = document.createElement('option');
|
||||||
|
option.value = cam.deviceId;
|
||||||
|
option.textContent = cam.label || `Camera ${index + 1}`;
|
||||||
|
cameraSelect.appendChild(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
const storedId = localStorage.getItem(CAMERA_STORAGE_KEY);
|
||||||
|
if (storedId && cameras.some(cam => cam.deviceId === storedId)) {
|
||||||
|
cameraSelect.value = storedId;
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraSelectWrap.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
cameraSelect.addEventListener('change', () => {
|
||||||
|
localStorage.setItem(CAMERA_STORAGE_KEY, cameraSelect.value);
|
||||||
|
startCamera(cameraSelect.value);
|
||||||
|
});
|
||||||
|
|
||||||
function triggerFlash() {
|
function triggerFlash() {
|
||||||
flash.style.opacity = '0.8';
|
flash.style.opacity = '0.8';
|
||||||
setTimeout(() => flash.style.opacity = '0', 150);
|
setTimeout(() => flash.style.opacity = '0', 150);
|
||||||
@ -149,7 +207,10 @@
|
|||||||
await $wire.capture(imageData);
|
await $wire.capture(imageData);
|
||||||
});
|
});
|
||||||
|
|
||||||
startCamera();
|
(async () => {
|
||||||
|
await startCamera(localStorage.getItem(CAMERA_STORAGE_KEY));
|
||||||
|
await populateCameraList();
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
@endscript
|
@endscript
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user