简易版手淘视频播放器开发心路历程

需求背景

简单描述一下这个功能:在一个走马灯组件里面第一屏是一个视频,第二屏第三屏是图片,点击播放视频,播放过程中滚动窗口,视频 fixed 在窗口顶部,回到顶部,视频还原,两个窗口视频播放进度无缝衔接,类似于淘票票和手机淘宝的功能。

技术方案

在此之前不得不说 那些年我们踩过的坑了。。。

确定要做这个需求的时候,确定了以下几个方案:

  1. 用一个 video ,页面滚动 fixed 在顶部;但是视频是嵌套在 Carousel 里面的,display:fixed; 对于 parentNode 加了 transform 属性根本不生效,position: sticky; 根本就别想了。这时候你可能会想到 【画中画】video.requestPictureInPicture() 解决,但是 画中画 需要用户主动触发。。
  2. 《传送门 react.createProten》, 传送门可以任意挂载 dom ,但是一直拿不到合适的 currentTime(视频当前播放时间),并且部分浏览器(Safari)需要用户主动唤起 play()事件,最后选择放弃;
  3. 两个 video ,一个 在 Carousel 里面显示,一个在页面顶部 fixed,这里搞了个 黑科技,让 fixed 的 video display:none; 了,至于为什么这样做忘记了,目的就是让 dom 显示好像~等我记起来了补充在这。

下文中,便针对 方案三 进行阐述;

事件/方法
video.pause()  // 暂停
video.play() // 播放
video.webkitRequestFullScreen()  //全屏
video.currentTime //当前进度   
video.duration //总进度

详情请移步 mdn 或 w3cSchool。

顽固 bugfix

视频只播放音频没有画面,预发视频的 url 是 http 的不是 https 的,后端帮忙改成 https 的发现也没用,也是查了很久,没找到解决方案,最后发现 Carousel 才是始作俑者!也就是说这个问题根本跟环境无关,而是 Carousel 里面轮播了多少个 item 有关!
查看一下页面元素:
在这里插入图片描述发现 Carousel 里面轮播的内容多出了很多,看一下多出来了几个 video:
在这里插入图片描述
一个 video 是 fixed 的 video,默认 display:none; ,还有一个是 Carousel 里面轮播的 video ,另一个则是 Carousel 为了实现 无线循环 而多出来的 video!播放 video 的时候,触发了 onPlay,但其实真正播放的是隐藏起来为了实现 无限循环 的 video,并且 这两个 Carousel 里面的 video 的 index 是相同的~

『解决方案』:关掉 无限循环(infinite) !简单粗暴~

infinite
Type: bool
Default: true
Description: Infinitely wrap around contents
   <Carousel infinite={false} afterChange={afterChange}>
     // ……
   </Carousel>

Android 和 ios 表现得不同形式

由于测试设备有限,用了三部手机测试兼容:
android:vivo IQOO 3、小米 11
ios:iPhone12
为了避免更多的雷,video 禁用了 controls ,设计师帮忙切了个 ⏯ 的图定位到 video 上面了~通过 onClick 事件触发 video 的 play 和 pause。

实现方案详细阐述

页面采用两个 video,一个现实,一个 display:none; ,当窗口 scroll 到一定距离时 fixed 的video 显示,并且在 需要fixed 和 需要 fixed 的变换过程中互换两个视频的 currentTime ,保证视频播放的 currentTime 是可以衔接上的。

播放是否自动全屏

ios : 自动全屏;
android: 不会自动全屏;

影响:ios 播放自动全屏;
解决方案:

x5-playsinline="true" // 安卓需要设置的属性
playsInline // ios需要设置的属性
webkit-playsinline="true" // ios10需要设置的属性
preload="auto" // 预加载

一个页面两个 video

ios : fixed 的视频 play 时另一个 自动 pause;
android: fixed 的视频 play 时另一个不会 pause;

影响:此时你可能会听间视频播放的时候会有两个声音,一前一后,虽然不仔细听听不出来,但是影响毕竟是在的。。。
hack:判断 android 机时,一个视频播放暂停另一个;监听一下 onPlay 和 onPause 事件就好了~

判断机型代码段:

/* 判断android与ios */
export function phoneModel() {
  const u = navigator.userAgent;
  // const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器
  const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); // ios终端
  if (isiOS) {
    return false;
  }
  return true;
}
controls={false} 是否生效

ios : 生效,并且 play 之后也不会再出现;
android: 生效,但是 play 之后会出现自己的 播放/暂停/进度条/全屏 按钮,大概有 3s 左右的 delay;
在这里插入图片描述
框出来的都是 android 机下 video play 之后自带的 controls

影响:上文说到是通过 onClick 去控制 开关变量 操作 video 的 play 和 pause,但是 android play 之后自带了一些 controls ,如果用它自带的 controls 暂停播放的时候,是无法触发 onClick 事件的,关键没哟偶很好的办法禁用,就很头痛~
hack:监听 onPlay 和 onPause 事件,事件里面操作开关变量~监听开关变量,控制 play 和 pause~

video 一旦播放是否会置于顶层

ios:不会置于顶层;
android:置于顶层;
在这里插入图片描述
hack:Carousel 调用 afterChange 判断 currentIndex 和 当前 index 不同的时候隐藏掉就好了, 不建议用 display:none;用 width:0;height:0; 也可以完美解决~

  • 17
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值