我使用 Laravel 与 Alpinejs 和 webRTC 来检查用户是否打开了相机。 webRTC 部分工作正常并且可以检测相机。但显示相机是否打开或关闭的 x-text 值在获取 webRTC 流后不会更新。
<div class="card">
<div class="card-header font-bold">Preparation Page</div>
<div class="card-body">
{!! $exam->bo_exam_instruction !!}
<div class="mt-2">
Camera : <span x-text="isOpen ? 'On' : 'Off'" class="badge" :class="cameraClasses()"></span>
</div>
<div>
<form action="{{ route('student.startOlympiad', $exam->id) }}" method="POST"
x-ref="examForm">
@csrf
<button class="btn mt-2" :class="buttonClasses()"
x-on:click.prevent="confirmStartExam()">
Start Exam</button>
</form>
</div>
</div>
</div>
@push('extra_js')
<script>
function componentData() {
return {
isOpen: false,
cameraClasses() {
console.log("isOpen:", this.isOpen);
return {
// <span class="badge badge-danger">Danger</span>
'badge-danger': !this.isOpen,
'badge-success': this.isOpen
}
},
adapter: {
browserDetails: {
browser: navigator.userAgent,
version: navigator.appVersion
}
},
buttonClasses() {
return {
'btn-primary': !this.isOpen,
'btn-secondary': this.isOpen
};
},
confirmStartExam() {
if (this.isOpen) {
Swal.fire({
title: 'Are you sure?',
text: 'Once you start the exam, you cannot go back!',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, start the exam!'
}).then((result) => {
if (result.isConfirmed) {
this.startExam();
}
});
} else {
Swal.fire({
title: 'Camera Permission!',
text: 'Please allow camera permissions',
icon: 'info',
})
}
},
startExam() {
// Submit the form using Alpine.js
this.$refs.examForm.submit();
},
}
}
const data = componentData();
async function openMediaDevices(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
// If stream is obtained, set isOpen to true
if (stream) {
console.log(stream); //gets stream
data.isOpen = true;
console.log(data.isOpen); //comes true
}
return stream;
} catch (error) {
console.error('Error accessing media devices.', error);
return null;
}
}
window.onload = async function() {
await openMediaDevices({
video: true
});
console.log("Final isOpen:", data.isOpen);
}
</script>
@endpush
当data.isOpen = true; x-text="isOpen ? 'On' : 'Off'" 这应该显示“ON”。它仍然显示“OFF”
组件数据封装在该组件内,因此您无法像您尝试那样从组件外部直接编辑
isOpen
。
您可以使用事件与组件进行通信,但为什么不将
openMediaDevices
函数移至组件本身呢?然后您可以从组件的 init()
函数调用它并从那里更改 this.isOpen
的值:
function componentData() {
return {
isOpen: false,
// ... other properties and methods
async openMediaDevices(constraints) {
try {
const stream = await navigator.mediaDevices.getUserMedia(constraints);
// If stream is obtained, set isOpen to true
if (stream) {
console.log(stream); // gets stream
this.isOpen = true;
console.log(this.isOpen); // comes true
}
return stream;
} catch (error) {
console.error('Error accessing media devices.', error);
return null;
}
},
async init() {
await this.openMediaDevices({
video: true,
});
console.log('Final isOpen:', this.isOpen);
},
};
}