From 09a11fec9c43b2852ba169fd8f7331f541670ecd Mon Sep 17 00:00:00 2001 From: yujiaxinwt <1157613664@qq.com> Date: Tue, 25 Jul 2023 14:39:06 +0800 Subject: [PATCH 01/21] =?UTF-8?q?=E5=85=A8=E5=B1=8F=E4=B8=8B=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=B5=8F=E8=A7=88=E5=99=A8=E6=97=8B=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sdk/demo/demo.html | 3 +- sdk/index.html | 3 +- sdk/src/AppController.js | 57 ++++++++++++++++++++++++-- sdk/src/CloudApp.js | 33 ++++++++------- sdk/src/DirectionHandler.js | 70 +++++++++++++++++++++----------- sdk/src/Fullscreen.js | 7 ++-- sdk/src/TouchHandler.js | 6 ++- sdk/src/config/commonConfig.js | 9 +++- sdk/src/config/protocolConfig.js | 3 +- 9 files changed, 139 insertions(+), 52 deletions(-) diff --git a/sdk/demo/demo.html b/sdk/demo/demo.html index 818362c..a892a2b 100644 --- a/sdk/demo/demo.html +++ b/sdk/demo/demo.html @@ -146,7 +146,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. border-radius: 5px; transform: translate(-50%, -50%); } - .button-network,.button-exit{ + .button-network,.button-exit, .fullscreen-btn{ width: 100%; height: 25%; margin-bottom: 10px; @@ -254,6 +254,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. + diff --git a/sdk/index.html b/sdk/index.html index 1993dcc..21c2e5c 100644 --- a/sdk/index.html +++ b/sdk/index.html @@ -146,7 +146,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. border-radius: 5px; transform: translate(-50%, -50%); } - .button-network,.button-exit{ + .button-network,.button-exit, .fullscreen-btn{ width: 100%; height: 25%; margin-bottom: 10px; @@ -254,6 +254,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. + diff --git a/sdk/src/AppController.js b/sdk/src/AppController.js index 3300047..0405544 100644 --- a/sdk/src/AppController.js +++ b/sdk/src/AppController.js @@ -34,8 +34,10 @@ import { PACKAGE_HEADER_LENGTH, MEDIA_MSG_HEADER_COUNT, DEFAULT_DEFINITION, - FRAME_TYPE_MAP + FRAME_TYPE_MAP, + BROWSER_ORIENTATION_ANGLE } from './config/commonConfig'; +import FullScreen from './Fullscreen'; /*global __IS_DEBUG__*/ if (__IS_DEBUG__) { @@ -161,6 +163,15 @@ class AppController { }; this.appState = null; this.socketHasOpenned = false; // 标识socket是否已open过,用于重连时判断发送connect还是reconnect cmd + + // 初始化全屏类 + this.fullscreen = new FullScreen({ + containerId: this.options.containerId, + autoRotate: this.options.autoRotate, + isMobile: this.options.isMobile + }); + this.fullscreen.init(); + this.triggerFullscreen(); } getVolume() { @@ -447,7 +458,7 @@ class AppController { } // 增加播放状态条件限制,避免destroy后播放报错 - if (this.options.supportAudio && this.playing) { + if (this.options.supportAudio && this.playing && this.audioPlayer) { const frame = this.frameParser.shiftPackage('Audio'); frame && this.audioPlayer.feed(frame); } @@ -473,6 +484,7 @@ class AppController { let pkgBody = orientationPkg & 0xFF; const orientation = PROTOCOL_CONFIG.ORIENTATION[pkgBody]; Logger.debug('Orientation change:' + orientation); + this.pkgBody = pkgBody; this.orientation = orientation; this.updateResolutionAndTouch(); } @@ -495,8 +507,13 @@ class AppController { this.directionHandler.updateCanvasSize(this.orientation, this.isMSE); } this.touchHandler.updateOrientation(this.orientation); - this.autoRotation && this.autoRotation.updateOrientation(this.orientation); this.directionHandler.update(this.orientation, this.touchHandler.displayBox); + if (!this.options.isMobile) { + this.autoRotation && this.autoRotation.updateOrientation(this.orientation); + } else { + // 触发浏览器旋转 + this.browserOrientation(this.pkgBody); + } } } @@ -667,6 +684,9 @@ class AppController { this.updateResolution(); // 按照参数设置清晰度 this.setResolution(DEFAULT_DEFINITION); + + // 进入全屏模式 + this.triggerFullscreen(); break; case codeConfig.INVALID_OPERATION: case codeConfig.RECONNECT_FAILED: @@ -1334,6 +1354,8 @@ class AppController { exit() { this.disconnect(this.terminateSocketWorker.bind(this)); this.destroy(true); + this.fullscreen.destroy(); + this.fullscreen = null; } terminateSocketWorker() { @@ -1353,6 +1375,35 @@ class AppController { && this.socketWorkerState.socket !== WEBSOCKET_READY_STATE.CLOSED; } + // fullscreenElementId: 全屏元素ID。不能在同一个dom上旋转和全屏,所以若自动旋转则需另提供全屏的dom id,如containerId的父级dom + fullscreenToggle(fullscreenElementId = 'fullscreen-container') { + this.fullscreen.fullscreenToggle(fullscreenElementId, this.playerContainerId, this.isMSE); + } + + isFullscreen() { + return this.fullscreen.isFullscreen(); + } + + triggerFullscreen() { + const fullscreenBtn = document.getElementById('toggleFullscreen'); + if (fullscreenBtn) { + fullscreenBtn.addEventListener('click', () => { + this.fullscreenToggle(); + }); + } + } + + browserOrientation(pkgBody) { + if (screen.orientation.lock) { + try { + const orientationType = BROWSER_ORIENTATION_ANGLE[pkgBody]; + screen.orientation.lock(orientationType); + } catch (error) { + console.log(error) + } + } + } + /** * 销毁 * @param {boolean}} reserveSocketWorker 是否需要销毁socket,exit场景,延迟close socket,close前需保留socket diff --git a/sdk/src/CloudApp.js b/sdk/src/CloudApp.js index 60e2456..e8a33db 100644 --- a/sdk/src/CloudApp.js +++ b/sdk/src/CloudApp.js @@ -14,7 +14,7 @@ import AppController from './AppController'; import PROTOCOL_CONFIG from './config/protocolConfig'; -import FullScreen from './Fullscreen'; +// import FullScreen from './Fullscreen'; import Logger from './Logger'; import NoDebugger from './NoDebugger'; @@ -115,19 +115,18 @@ class CloudApp { const clientWidth = document.documentElement.clientWidth; const clientHeight = document.documentElement.clientHeight; fullscreenContainer.style.width = `${clientWidth}px`; - // 需要给操作按钮留出空间 fullscreenContainer.style.height = `${clientHeight}px`; } this.appController = CloudApp.setAppController.bind(this)(); this.appController.start(); - this.fullscreen = new FullScreen({ - containerId: this.options.containerId, - autoRotate: this.appController.options.autoRotate, - isMSE: this.appController.isMSE, - isMobile: isMobile - }); - this.fullscreen.init(); + // this.fullscreen = new FullScreen({ + // containerId: this.options.containerId, + // autoRotate: this.appController.options.autoRotate, + // isMSE: this.appController.isMSE, + // isMobile: isMobile + // }); + // this.fullscreen.init(); window.addEventListener('unload', () => { this.exit(); }); @@ -325,9 +324,9 @@ class CloudApp { exit() { this.appController.exit(); - this.fullscreen.destroy(); + // this.fullscreen.destroy(); this.appController = null; - this.fullscreen = null; + // this.fullscreen = null; } pause() { @@ -343,13 +342,13 @@ class CloudApp { } // fullscreenElementId: 全屏元素ID。不能在同一个dom上旋转和全屏,所以若自动旋转则需另提供全屏的dom id,如containerId的父级dom - fullscreenToggle(fullscreenElementId) { - this.fullscreen.fullscreenToggle(fullscreenElementId, this.appController.playerContainerId); - } + // fullscreenToggle(fullscreenElementId) { + // this.fullscreen.fullscreenToggle(fullscreenElementId, this.appController.playerContainerId); + // } - isFullscreen() { - return this.fullscreen.isFullscreen(); - } + // isFullscreen() { + // return this.fullscreen.isFullscreen(); + // } on(eventName, callback) { if (eventName === 'logReceived') { diff --git a/sdk/src/DirectionHandler.js b/sdk/src/DirectionHandler.js index fa0663c..aaef88a 100644 --- a/sdk/src/DirectionHandler.js +++ b/sdk/src/DirectionHandler.js @@ -91,6 +91,30 @@ class DirectionHandler { } } else { // 横屏时 + let transformAngle = null; + let netWorkInfoLeft = null; + let netWorkInfoTop = null; + let ctrlEleTop = null; + let ctrlEleLeft = null; + let commonLeft = null; + let buttonModalLst = null; + if (orientation === PROTOCOL_CONFIG.ORIENTATION[8]) { + transformAngle = 90; + netWorkInfoLeft = containerEle.clientWidth - 40; + netWorkInfoTop = -40; + ctrlEleTop = '5%'; + ctrlEleLeft = '80%'; + commonLeft = '50%'; + } else { + netWorkInfo.style.width = containerEle.clientHeight; + transformAngle = -90; + netWorkInfoLeft = 40; + netWorkInfoTop = containerEle.clientHeight - 40; + ctrlEleTop = '80%'; + ctrlEleLeft = '5%'; + commonLeft = `${(containerEle.clientWidth - Number(messageModal.style.width.split('px')[0]))/2 - 100}px`; + buttonModalLst = `${(containerEle.clientWidth - Number(buttonModal.style.width.split('px')[0]))/2 - 100}px`; + } const transformCssText = ` display: none; width: 300px; @@ -98,27 +122,27 @@ class DirectionHandler { position: absolute; z-index: 999; top: 50%; - left: 50%; + left: ${commonLeft}; background-color: #fff; border: 1px solid #dfe1e6; border-radius: 5px; - -webkit-transform: rotate(90deg); - -moz-transform: rotate(90deg); - -ms-transform: rotate(90deg); - -o-transform: rotate(90deg); - transform: rotate(90deg); + -webkit-transform: rotate(${transformAngle}deg); + -moz-transform: rotate(${transformAngle}deg); + -ms-transform: rotate(${transformAngle}deg); + -o-transform: rotate(${transformAngle}deg); + transform: rotate(${transformAngle}deg); transform-origin: top; `; messageModal.style.cssText = transformCssText; exitModal.style.cssText = transformCssText; keyboardInputContent.style.cssText = ` display: none; - -webkit-transform: rotate(90deg); - -moz-transform: rotate(90deg); - -ms-transform: rotate(90deg); - -o-transform: rotate(90deg); + -webkit-transform: rotate(${transformAngle}deg); + -moz-transform: rotate(${transformAngle}deg); + -ms-transform: rotate(${transformAngle}deg); + -o-transform: rotate(${transformAngle}deg); transform-origin: left; - transform: rotate(90deg); + transform: rotate(${transformAngle}deg); position: absolute; top: -20px; left: 20px; @@ -126,31 +150,31 @@ class DirectionHandler { width: ${containerEle.clientHeight}px;`; netWorkInfo.style.cssText = ` transform-origin: left; - transform: rotate(90deg); + transform: rotate(${transformAngle}deg); pointer-events: none; position: absolute; - left: ${containerEle.clientWidth - 40}px; + left: ${netWorkInfoLeft}px; height: 40px; line-height: 40px; text-align: center; width: ${containerEle.clientHeight}px; - top: -40px; + top: ${netWorkInfoTop}px; color: #fff; `; buttonModal.style.cssText = ` - -webkit-transform: rotate(90deg); - -moz-transform: rotate(90deg); - -ms-transform: rotate(90deg); - -o-transform: rotate(90deg); + -webkit-transform: rotate(${transformAngle}deg); + -moz-transform: rotate(${transformAngle}deg); + -ms-transform: rotate(${transformAngle}deg); + -o-transform: rotate(${transformAngle}deg); transform-origin: top; - transform: rotate(90deg); + transform: rotate(${transformAngle}deg); display: none; width: 255px; height: 155px; position: absolute; z-index: 999; top: 50%; - left: 50%; + left: ${buttonModalLst}; background-color: rgba(0, 0, 0, 0.4); border-radius: 5px; `; @@ -158,14 +182,14 @@ class DirectionHandler { const top = (containerEle.offsetHeight - displayBox.width)/2 + 40; const left = (containerEle.offsetWidth - displayBox.height)/2 + containerEle.offsetWidth - 50; if (this.options.isMobile) { - ctrlEle.style.top = `5%`; - ctrlEle.style.left = `80%`; + ctrlEle.style.top = ctrlEleTop; + ctrlEle.style.left = ctrlEleLeft; } else { ctrlEle.style.top = `${top}px`; ctrlEle.style.left = `${left}px`; } - ctrlEle.style.transform = 'rotate(90deg)'; + ctrlEle.style.transform = `rotate(${transformAngle}deg)`; ctrlEle.style.transformOrigin = 'top'; } } diff --git a/sdk/src/Fullscreen.js b/sdk/src/Fullscreen.js index aafe433..2c79dc5 100644 --- a/sdk/src/Fullscreen.js +++ b/sdk/src/Fullscreen.js @@ -75,15 +75,16 @@ export default class FullScreen { || document.webkitFullscreenElement); Logger.debug('inFullscreenStatus = ', this.inFullscreenStatus); - this.updateContainerSize(); + // this.updateContainerSize(); // 按下F11键进入全屏或退出全屏,不会触发resize事件,强制触发,否则触控点错位 window.dispatchEvent && window.dispatchEvent(new Event('resize')); } - fullscreenToggle(fullscreenElementId, playerContainerId) { + fullscreenToggle(fullscreenElementId, playerContainerId, isMSE) { this.playerContainerId = playerContainerId; this.fullscreenElementId = fullscreenElementId; + this.isMSE = isMSE; if (!fullscreenElementId && this.options.autoRotate) { Logger.debug('Can not use fullscreenToggle API success, because fullscreenElementId is undefined but auto_rotate is true'); @@ -130,7 +131,7 @@ export default class FullScreen { `; // canvas无法使用百分比设置大小,故全屏和取消全屏需要手动设置宽高 - if (!this.options.isMSE) { + if (!this.isMSE) { this.updateCanvasSize(fullWidth, fullHeight); } } diff --git a/sdk/src/TouchHandler.js b/sdk/src/TouchHandler.js index c07eea6..a0b8372 100644 --- a/sdk/src/TouchHandler.js +++ b/sdk/src/TouchHandler.js @@ -24,13 +24,15 @@ const ORIENTATION_DEGRESS = { 'PORTRAIT': 0, 'LANDSCAPE': 90, 'REVERSE_LANDSCAPE': -90, - 'REVERSE_PORTRAIT': 180 + 'REVERSE_PORTRAIT': 180, + 'LANDSCAPE_24': -90 }; const ORIENTATION_ORIGIN = { 'PORTRAIT': 0, 'LANDSCAPE': 1, 'REVERSE_LANDSCAPE': 3, - 'REVERSE_PORTRAIT': 2 + 'REVERSE_PORTRAIT': 2, + 'LANDSCAPE_24': 0 }; const KEYBOARD_MODE = { 'KEYBOARD_MAP': 'KEYBOARD_MAP', diff --git a/sdk/src/config/commonConfig.js b/sdk/src/config/commonConfig.js index 4542682..c937070 100644 --- a/sdk/src/config/commonConfig.js +++ b/sdk/src/config/commonConfig.js @@ -43,4 +43,11 @@ export const MIC_START_RECORD_RSP_LEN = MEDIA_MSG_HEADER_COUNT + 4; // pc场景摄像头最大高度 export const PC_CAMERA_MAX_HEIGHT = 720; // 默认画质 -export const DEFAULT_DEFINITION = 'HD'; \ No newline at end of file +export const DEFAULT_DEFINITION = 'HD'; +// 浏览器旋转角度 +export const BROWSER_ORIENTATION_ANGLE = { + 0: 'portrait-primary', // 竖屏0 + 1: 'landscape-primary', // 横屏90 + 8: 'landscape-primary', //横屏90 + 24: 'landscape-secondary', //横屏180 +} \ No newline at end of file diff --git a/sdk/src/config/protocolConfig.js b/sdk/src/config/protocolConfig.js index 05b1e78..09037b7 100644 --- a/sdk/src/config/protocolConfig.js +++ b/sdk/src/config/protocolConfig.js @@ -103,7 +103,8 @@ const PROTOCOL_CONFIG = { ORIENTATION: { 0: 'PORTRAIT', 1: 'LANDSCAPE', // 从竖屏逆时针旋转90度 - 8: 'REVERSE_LANDSCAPE' + 8: 'REVERSE_LANDSCAPE', + 24: 'LANDSCAPE_24', }, RESOLUTIONS: { DISPLAY_480P: { -- Gitee From c4572f12807796015256654efb2ee143c75db386 Mon Sep 17 00:00:00 2001 From: CaiFeng <2397707574@qq.com> Date: Tue, 25 Jul 2023 20:38:11 +0800 Subject: [PATCH 02/21] support full screen --- sdk/src/AppController.js | 3 ++- sdk/src/TouchHandler.js | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/sdk/src/AppController.js b/sdk/src/AppController.js index 2c960fd..d078e9a 100644 --- a/sdk/src/AppController.js +++ b/sdk/src/AppController.js @@ -347,7 +347,8 @@ class AppController { sendHandler: this.send, isDebug: this.options.isDebug, autoRotate: this.options.autoRotate, - inputId: this.keyboardInput && this.keyboardInput.inputId || '' + inputId: this.keyboardInput && this.keyboardInput.inputId || '', + isFullscreen: this.isFullscreen.bind(this) }); this.touchHandler.start(); if(this.touchHandler.displayBox.width && this.touchHandler.displayBox.height) { diff --git a/sdk/src/TouchHandler.js b/sdk/src/TouchHandler.js index a0b8372..53f3e77 100644 --- a/sdk/src/TouchHandler.js +++ b/sdk/src/TouchHandler.js @@ -40,7 +40,7 @@ const KEYBOARD_MODE = { }; export default class TouchHandler { - constructor({player, isMobile, sendHandler, isDebug, autoRotate, inputId = ''}) { + constructor({player, isMobile, sendHandler, isDebug, autoRotate, inputId = '', isFullscreen}) { // 监听触控鼠键事件的Dom this.displayDom = player; // 事件回调,可通过该函数获取模拟事件 @@ -88,6 +88,8 @@ export default class TouchHandler { this.viewportOrientation = window.orientation; this.isApple = /(iPhone|iPad|iPod|iOS|Macintosh)/i.test(navigator && navigator.userAgent || ''); this.inputId = inputId; + // 判断是否全屏状态 + this.isFullscreen = isFullscreen; } start() { @@ -449,14 +451,25 @@ export default class TouchHandler { if (touch.x > this.displayBox.width || touch.x < 0 || touch.y < 0 || touch.y > this.displayBox.height) { return; } - let oritenation = this.isMobile && this.orientation === ORIENTATION_REVERSE_LANDSCAPE ? 0 : ORIENTATION_ORIGIN[this.orientation]; + + let orientation; + if (this.isMobile) { + if (this.isFullscreen()) { + orientation = this.orientation === ORIENTATION_PORTRAIT ? 0 : 1; + } else { + orientation = 0; + } + } else { + orientation = ORIENTATION_ORIGIN[this.orientation]; + } + // let orientation = this.isMobile && this.orientation === ORIENTATION_REVERSE_LANDSCAPE ? 0 : ORIENTATION_ORIGIN[this.orientation]; const msg = { ...touch, action: PROTOCOL_CONFIG.ACTIONS_TYPE[action], id: touch.vId, pressure: 129, time: -1, - orientation: oritenation, + orientation: orientation, height: this.displayBox.height, width: this.displayBox.width }; -- Gitee From 2e793a09c4bdf3246097f3391997752cf7539f64 Mon Sep 17 00:00:00 2001 From: yujiaxinwt <1157613664@qq.com> Date: Wed, 26 Jul 2023 17:18:48 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sdk/demo/demo.html | 17 ++++ sdk/enter.html | 6 +- sdk/index.html | 19 ++++- sdk/src/AppController.js | 22 +++-- sdk/src/DirectionHandler.js | 10 ++- sdk/src/DragHandler.js | 164 ++++++++++++++++++++++++++++++++++++ sdk/src/Fullscreen.js | 19 ++++- 7 files changed, 241 insertions(+), 16 deletions(-) create mode 100644 sdk/src/DragHandler.js diff --git a/sdk/demo/demo.html b/sdk/demo/demo.html index ebad517..240723a 100644 --- a/sdk/demo/demo.html +++ b/sdk/demo/demo.html @@ -121,6 +121,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. } .control-btn { display: none; + user-select: none; font-size: 14px; line-height: 40px; text-align: center; @@ -571,8 +572,14 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. const buttonModalEle = document.getElementById('buttonModal'); const playContainer = document.querySelector('article'); const playerElement = playContainer.shadowRoot.querySelector('#playCanvas') || playContainer.shadowRoot.querySelector('#phoenixVideo'); + const fullscreenBtn = document.getElementById('toggleFullscreen'); ctrlEle.style.display = 'block'; + let isClick = 'true'; ctrlEle.addEventListener('click', (event) => { + isClick = ctrlEle.getAttribute('click-flag'); + if (isClick === 'false') { + return; + } if(buttonModalEle.style.display !== 'block') { buttonModalEle.style.display = 'block'; } else { @@ -581,13 +588,23 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. }); if (/(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent)) { + fullscreenBtn.style.display = 'block'; playerElement.addEventListener('touchend', (event) => { + isClick = ctrlEle.getAttribute('click-flag'); + if (isClick === 'false') { + return; + } if(!buttonModalEle.contains(event.target) && !ctrlEle.contains(event.target)) { buttonModalEle.style.display = 'none'; } }); } else { + fullscreenBtn.style.display = 'none'; document.addEventListener('click', (event) => { + isClick = ctrlEle.getAttribute('click-flag'); + if (isClick === 'false') { + return; + } if(!buttonModalEle.contains(event.target) && !ctrlEle.contains(event.target)) { buttonModalEle.style.display = 'none'; } diff --git a/sdk/enter.html b/sdk/enter.html index b108e9f..14beaaf 100644 --- a/sdk/enter.html +++ b/sdk/enter.html @@ -132,10 +132,10 @@ let localHref = window.location.href + 'index'; if (window.location.href.indexOf('enter.html') > -1) { - localHref = window.location.href.replace('enter.html', 'index.html'); + localHref = window.location.href.replace('enter.html', 'demo.html'); if (localHref === window.location.href) { - localHref = window.location.href.replace('enter.html', 'demo.html'); - } + localHref = window.location.href.replace('enter.html', 'demo.html'); + } } window.location.href = localHref; diff --git a/sdk/index.html b/sdk/index.html index feaaa24..3a005cd 100644 --- a/sdk/index.html +++ b/sdk/index.html @@ -121,6 +121,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. } .control-btn { display: none; + user-select: none; font-size: 14px; line-height: 40px; text-align: center; @@ -293,7 +294,7 @@ Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. + src="sdk/CloudApp.min.js"> + src="<%= htmlWebpackPlugin.files.chunks.CloudApp.entry %>">