73 lines
1.8 KiB
TypeScript
73 lines
1.8 KiB
TypeScript
export const CameraMixin = (SuperClass) => {
|
|
return class CameraMixinClass extends SuperClass {
|
|
private _video;
|
|
private _canvas;
|
|
private _framerate;
|
|
|
|
constructor() {
|
|
super();
|
|
this._framerate = 2;
|
|
|
|
window.addEventListener(
|
|
"pointerdown",
|
|
() => {
|
|
this._setup_camera();
|
|
},
|
|
{ once: true }
|
|
);
|
|
}
|
|
|
|
async _setup_camera() {
|
|
if (this._video) return;
|
|
await this.connectionPromise;
|
|
if (!this.cameraEnabled) return;
|
|
const video = (this._video = document.createElement("video"));
|
|
video.autoplay = true;
|
|
video.playsInline = true;
|
|
video.style.display = "none";
|
|
|
|
const canvas = (this._canvas = document.createElement("canvas"));
|
|
canvas.style.display = "none";
|
|
|
|
document.body.appendChild(video);
|
|
document.body.appendChild(canvas);
|
|
|
|
if (!navigator.mediaDevices) return;
|
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
video: true,
|
|
audio: false,
|
|
});
|
|
|
|
video.srcObject = stream;
|
|
video.play();
|
|
this.update_camera();
|
|
}
|
|
|
|
async update_camera() {
|
|
if (!this.cameraEnabled) {
|
|
const stream = this._video?.srcObject;
|
|
if (stream) {
|
|
stream.getTracks().forEach((t) => t.stop());
|
|
this._video.scrObject = undefined;
|
|
}
|
|
return;
|
|
}
|
|
const video = this._video;
|
|
const width = video.videoWidth;
|
|
const height = video.videoHeight;
|
|
this._canvas.width = width;
|
|
this._canvas.height = height;
|
|
const context = this._canvas.getContext("2d");
|
|
context.drawImage(video, 0, 0, width, height);
|
|
|
|
this.sendUpdate({
|
|
camera: this._canvas.toDataURL("image/jpeg"),
|
|
});
|
|
|
|
const interval = Math.round(1000 / this._framerate);
|
|
setTimeout(() => this.update_camera(), interval);
|
|
}
|
|
};
|
|
};
|