diff --git a/src/views/ToolboxView/Other/Msu2UsbMonitorController/Msu2UsbMonitorController.vue b/src/views/ToolboxView/Other/Msu2UsbMonitorController/Msu2UsbMonitorController.vue
index 218e4c3..0e95dcd 100644
--- a/src/views/ToolboxView/Other/Msu2UsbMonitorController/Msu2UsbMonitorController.vue
+++ b/src/views/ToolboxView/Other/Msu2UsbMonitorController/Msu2UsbMonitorController.vue
@@ -41,6 +41,18 @@
@click="isUseNewDisplayDataConvertFunction = false"
>显示数据转换算法:旧
+
+ 开始屏幕捕获
+ 停止屏幕捕获
+
@@ -143,6 +155,10 @@ const DISPLAY_MODES = {
label: '数字时钟',
value: 'digitalClock',
},
+ screenCapture: {
+ label: '屏幕捕获',
+ value: 'screenCapture',
+ },
};
/** 分辨率配置选项 */
@@ -182,6 +198,9 @@ const displayMode = ref('dataText');
/** 是否使用新的显示数据转换算法 */
const isUseNewDisplayDataConvertFunction = ref(true);
+/** 屏幕捕获是否已就绪 */
+const isScreenCaptureReady = ref(false);
+
/** 渲染间隔,毫秒 */
const renderInterval = ref(100);
@@ -247,6 +266,20 @@ let CANVAS_HEIGHT = 0; // 画布显示高度
let LCD_WIDTH = 0; // 设备实际宽度
let LCD_HEIGHT = 0; // 设备实际高度
+// 屏幕捕获相关变量
+
+/** @type {MediaStream} */
+let displayStream = null;
+
+/** @type {HTMLVideoElement} */
+let displayVideo = null;
+
+/** @type {ReturnType} */
+let displayVideoTrack = null;
+
+/** 屏幕捕获是否已激活 */
+let isScreenCaptureActive = false;
+
/** 处理更改显示模式 */
function handleChangeDisplayMode() {
@@ -383,6 +416,17 @@ function handleStopRender() {
}
+/** 开始屏幕捕获处理 */
+async function handleStartScreenCapture() {
+ await startScreenCapture();
+ isScreenCaptureReady.value = true;
+}
+
+/** 停止屏幕捕获处理 */
+function handleStopScreenCapture() {
+ stopScreenCapture();
+}
+
/** 初始化 */
function initData() {
@@ -571,6 +615,64 @@ function audioAnalyserStop() {
}
+/** 开始屏幕捕获 */
+async function startScreenCapture() {
+ try {
+ displayStream = await navigator.mediaDevices.getDisplayMedia({
+ video: {
+ displaySurface: 'monitor',
+ },
+ audio: false,
+ });
+
+ displayVideo = document.createElement('video');
+ displayVideo.srcObject = displayStream;
+ displayVideo.autoplay = true;
+ displayVideo.playsInline = true;
+
+ await displayVideo.play();
+
+ displayVideoTrack = displayStream.getVideoTracks()[0];
+
+ displayVideoTrack.onended = () => {
+ stopScreenCapture();
+ };
+
+ isScreenCaptureActive = true;
+ isScreenCaptureReady.value = true;
+ console.info('屏幕捕获已开始');
+
+ } catch (error) {
+ console.error('屏幕捕获失败:', error);
+ isScreenCaptureActive = false;
+ isScreenCaptureReady.value = false;
+ }
+}
+
+/** 停止屏幕捕获 */
+function stopScreenCapture() {
+
+ if (displayVideoTrack) {
+ displayVideoTrack.stop();
+ displayVideoTrack = null;
+ }
+
+ if (displayStream) {
+ displayStream.getTracks().forEach(track => track.stop());
+ displayStream = null;
+ }
+
+ if (displayVideo) {
+ displayVideo.srcObject = null;
+ displayVideo = null;
+ }
+
+ isScreenCaptureActive = false;
+ isScreenCaptureReady.value = false;
+ console.info('屏幕捕获已停止');
+
+}
+
/** 将 32 位整数拆分为 4 个字节 */
function convertDigitToInts(di) {
return [(di >> 24) & 0xFF, (di >> 16) & 0xFF, (di >> 8) & 0xFF, di & 0xFF];
@@ -1059,6 +1161,9 @@ async function renderCanvas(timestamp = 0) {
case 'digitalClock':
await renderDigitalClock();
break;
+ case 'screenCapture':
+ await renderScreenCapture();
+ break;
default:
break;
}
@@ -1330,6 +1435,51 @@ async function renderDigitalClock() {
}
+/** 渲染屏幕捕获内容 */
+async function renderScreenCapture() {
+
+ if (displayVideo && isScreenCaptureActive) {
+ // 清空画布
+ canvasCtx.value.fillStyle = '#000000';
+ canvasCtx.value.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
+ } else {
+ // 显示提示文字
+ await renderCustomText('屏幕捕获未启动');
+ return;
+ }
+
+ let videoWidth = displayVideo.videoWidth;
+ let videoHeight = displayVideo.videoHeight;
+
+ if (videoWidth === 0 || videoHeight === 0) {
+ return;
+ }
+
+ let videoAspectRatio = videoWidth / videoHeight;
+ let canvasAspectRatio = CANVAS_WIDTH / CANVAS_HEIGHT;
+
+ let drawWidth, drawHeight, offsetX, offsetY;
+
+ if (videoAspectRatio > canvasAspectRatio) {
+ drawWidth = CANVAS_WIDTH;
+ drawHeight = CANVAS_WIDTH / videoAspectRatio;
+ offsetX = 0;
+ offsetY = (CANVAS_HEIGHT - drawHeight) / 2;
+ } else {
+ drawHeight = CANVAS_HEIGHT;
+ drawWidth = CANVAS_HEIGHT * videoAspectRatio;
+ offsetX = (CANVAS_WIDTH - drawWidth) / 2;
+ offsetY = 0;
+ }
+
+ canvasCtx.value.drawImage(
+ displayVideo,
+ offsetX, offsetY,
+ drawWidth, drawHeight
+ );
+
+}
+
onMounted(() => {
initData();
});
@@ -1337,6 +1487,7 @@ onMounted(() => {
onBeforeUnmount(() => {
handleDisconnectDevice();
handleStopRender();
+ handleStartScreenCapture();
});