add: 前后摄像头切换

This commit is contained in:
lww155
2026-02-09 16:50:23 +08:00
parent 7b3db72285
commit c3da3e937e
4 changed files with 87 additions and 1 deletions
+41 -1
View File
@@ -25,6 +25,7 @@ class App {
this.audioPlayer = null;
this.live2dManager = null;
this.cameraStream = null;
this.currentFacingMode = 'user';
}
// 初始化应用
@@ -127,6 +128,8 @@ class App {
async initCamera() {
const cameraContainer = document.getElementById('cameraContainer');
const cameraVideo = document.getElementById('cameraVideo');
const cameraSwitch = document.getElementById('cameraSwitch');
const dialBtn = document.getElementById('dialBtn');
if (!cameraContainer || !cameraVideo) {
log('摄像头元素未找到,跳过初始化', 'warning');
@@ -188,11 +191,24 @@ class App {
}
log('正在请求摄像头权限...', 'info');
this.cameraStream = await navigator.mediaDevices.getUserMedia({
video: { width: 320, height: 240, facingMode: 'user' },
video: { width: 320, height: 240, facingMode: this.currentFacingMode },
audio: false
});
cameraVideo.srcObject = this.cameraStream;
const devices = await navigator.mediaDevices.enumerateDevices();
const videoDevices = devices.filter(device => device.kind === 'videoinput');
if (videoDevices.length > 1) {
if (cameraSwitch) cameraSwitch.classList.add('active');
}
cameraContainer.classList.add('active');
// 切换时挂断情况
const hasActive = dialBtn.classList.contains('dial-active');
if (!hasActive) {
cameraContainer.classList.remove('active');
cameraSwitch.classList.remove('active');
window.stopCamera();
}
log('摄像头已启动', 'success');
return true;
} catch (error) {
@@ -217,6 +233,30 @@ class App {
}
};
window.switchCamera = async() => {
if (window.switchCameraTimer) return;
if (this.cameraStream) {
const currentTransform = window.getComputedStyle(cameraContainer).transform;
const originalTransform = currentTransform === 'none' ? 'translate(0px, 0px)' : currentTransform;
cameraContainer.style.setProperty('--original-transform', originalTransform);
cameraContainer.classList.add('flip');
this.currentFacingMode = this.currentFacingMode === 'user' ? 'environment' : 'user';
window.stopCamera();
window.startCamera();
window.switchCameraTimer = setTimeout(() => {
if (this.currentFacingMode === 'user') {
cameraVideo.style.transform = 'scaleX(-1)';
} else {
cameraVideo.style.transform = 'scaleX(1)';
}
window.switchCameraTimer = null;
cameraContainer.classList.remove('flip');
cameraContainer.style.removeProperty('--original-transform');
}, 500);
}
};
window.takePhoto = (question = '描述一下看到的物品') => {
return new Promise(async (resolve) => {
const canvas = document.createElement('canvas');
@@ -98,6 +98,14 @@ class UIController {
});
}
// Camera switch button
const cameraSwitch = document.getElementById('cameraSwitch');
if (cameraSwitch) {
cameraSwitch.addEventListener('click', () => {
window.switchCamera();
})
}
// Dial button
const dialBtn = document.getElementById('dialBtn');
if (dialBtn) {
@@ -115,6 +123,7 @@ class UIController {
if (isConnected) {
wsHandler.disconnect();
this.updateDialButton(false);
if (cameraSwitch) cameraSwitch.classList.remove('active');
this.addChatMessage('Disconnected, see you next time~😊', false);
} else {
// Check if OTA URL is filled
@@ -153,6 +162,7 @@ class UIController {
if (isActive) {
// 关闭摄像头
if (typeof window.stopCamera === 'function') {
if (cameraSwitch) cameraSwitch.classList.remove('active');
window.stopCamera();
}
cameraContainer.classList.remove('active');