初体验:H5与原生App使用JSBridge交互,百分百还原App竖屏,横屏播放体验

329 阅读4分钟

场景初遇

年初在开发中遇到用这样的场景:需要开发一个H5页面,并运行在App的webview容器。H5页面video 播放器,简介等。video 播放器需要竖屏, 横屏两种模式,并且自定义播放/暂停按钮,播放时间进度条,视频画质,播放倍速, 显示弹幕, 分享,收藏等功能。

众所周知,video标签在手机浏览器上播放视频,横屏时,无法在播放器页面显示更多的内容或者操作,因此,在App的webview容器使用JSBridge交互,真实展现横屏播放丝滑体验。

技术集成

1,提供一个使用JSBridge与H5交互调起手机横屏,竖屏的测试App(安卓版)

2, vite + Vue3 + Vant4 +Sass + postcss-pxtorem 开发H5

3, Nginx部署

Demo效果

废话多说,展示Demo画面

竖屏:

      

横屏:

技术难点

1,App原生与H5使用JSBridge交互。

解决方案: 麻烦原生大神开发封装。

2,video标签播放的钩子函数

解决方案:

查找资料,有如下钩子函数

const eventMap = {    

  /* 1、loadstart:视频查找。当浏览器开始寻找指定的音频/视频时触发,也就是当加载过程开始时 提示视频的元数据已加载 */  
  loadstart: () => {}, // console.log('提示视频的元数据已加载')   
 
  /* 2、durationchange:时长变化。当指定的音频/视频的时长数据发生变化时触发,加载后,时长由 NaN 变为音频/视频的实际时长 */   
  durationchange: () => {}, // console.log('提示视频的时长已改变')    

  /* 3、loadedmetadata :元数据加载。当指定的音频/视频的元数据已加载时触发,元数据包括:时长、尺寸(仅视频)以及文本轨道 */   
  loadedmetadata: () => this.loadedmetadata(),  // console.log('提示视频的元数据已加载') 
   
  /* 4、loadeddata:视频下载监听。当当前帧的数据已加载,但没有足够的数据来播放指定音频/视频的下一帧时触发 */  
  loadeddata: () => {}, // console.log('提示当前帧的数据是可用的')  
 
  /* 5、progress:浏览器下载监听。当浏览器正在下载指定的音频/视频时触发 */  
  progress: () => {}, // console.log('提示视频正在下载中')    

  /* 6、canplay:可播放监听。当浏览器能够开始播放指定的音频/视频时触发 */  
  canplay: () => {}, // console.log('提示该视频已准备好开始播放') 
 
  /* 7、canplaythrough:可流畅播放。当浏览器预计能够在不停下来进行缓冲的情况下持续播放指定的音频/视频时触发  */  
  canplaythrough: () => {}, // console.log('提示视频能够不停顿地一直播放') 

  /* 8、play:播放监听 */   
  play: () => {    }, // console.log('提示该视频正在播放中') 
 
  /* 9、pause:暂停监听 */   
  pause: () => {    }, // console.log('暂停播放') 
   
  /* 10、seeking:查找开始。当用户开始移动/跳跃到音频/视频中新的位置时触发*/    
  seeking: () => {}, // console.log('开始移动进度条')    

  /* 11、seeked:查找结束。当用户已经移动/跳跃到视频中新的位置时触发 */   
  seeked: () => {}, // console.log('进度条已经移动到了新的位置') 
   
  /* 12、waiting:视频加载等待。当视频由于需要缓冲下一帧而停止,等待时触发 */
   waiting: () => { }, // console.log('waiting')    

  /* 13、playing:当视频在已因缓冲而暂停或停止后已就绪时触发 */   
  playing: () => {}, // console.log('playing') 
   
  /* 14 timeupdate:目前的播放位置已更改时,播放时间更新 */   
  timeupdate:  () => {    }, // console.log('timeupdate') 
   
  /* 15、ended:播放结束 */    
  ended: () => {    }, // console.log('视频播放完了')    

  /* 16、error:播放错误 */    
  error: () => {}, // console.log('视频出错了') 
   
  /* 17、volumechange:当音量更改时 */    
  volumechange: () => {}, // console.log('volumechange') 
  
  /* 18、stalled:当浏览器尝试获取媒体数据,但数据不可用时 */
  stalled: () => {}, // console.log('stalled')   

  /* 19、ratechange:当视频的播放速度已更改时 */  
  ratechange: () => {}, // console.log('ratechange') 
}

 

3,调起横屏成功后,Ui变形问题

解决方案:

1, 默认进入竖屏时,获取当前模式的html标签的fontSize值,并缓存

2, 调起横屏成功后,强制设置html标签的fontSize值为竖屏时的fontSize值,即第1步的缓存值

代码参考

// rem的基准
const portraitScreenFontSize = ref('')
/* 获取竖屏rem的基准 */
function getHtmlFontSize() {  
   const dom = document.getElementsByTagName('html') 
   if (dom && dom[0]) {   
     portraitScreenFontSize.value = dom[0].style?.fontSize  
   }
}

/* 强制设置横屏的rem基准与竖屏的一致  */
 const dom = document.getElementsByTagName('html')  
 if (dom && dom[0]) {   
   dom[0].style.fontSize = props.portraitScreenFontSize  
 }

说在最后

该场景经常出现商品介绍视频/直播中,教育讲座类的App中,当你遇到类似的常见可以参照。。。

附上dome视频:

sixk.top/sources/mp4…