Swiper和Video.js组合使用进度条失效

834 阅读2分钟

背景

最近在做一个官网项目,客户要求轮播图内有视频,本着不重复造轮子(拿来把你)的优良品质,选择了SwiperVideo.js,然后开始撸,代码大概这样

代码

最小化的代码基本就这样,在大部分电脑上都正常,比如我的Windows 11和10都是最新版本的

<div class="swiper-container banner-container">
  <div class="swiper-wrapper">
    <div class="swiper-slide">
      // 视频
      <video class="video-js banner-video"></video>
    </div>
    <div class="swiper-slide">
      // 图片
      <img  class="adaptive-img" src="static/img/index/banner-01.jpg" alt="" />
    </div>
  </div>
</div>
  var bannerSwiper = new Swiper('.banner-container')
  
  var videoInstance =videojs(
        videoEl[0],
        {
          poster: '../cover.jpg',
          sources: [
            {
              src: '../demo.mp4',
              type: 'video/mp4',
            },
          ],
          controls: true,
          autoplay: false
        },
        function onPlayerReady() {
          // 播放器初始化完成
        }
      )

问题

但同事有两台是Windows 7系统,均为最新版本Chrome,打开出现了诡异的问题,Video的进度条无法拖动,无法点击,.vjs-control-bar这个bar整体失效了。

  1. 起初以为Swiper组件盖住了video,尝试调整z-index还是不行;
  2. 又以为是Swiper滑动事件和Video.js的事件冲突,但诡异的就是在我的Windows 10和11都没问题,还有一台Macbook也没问题。
  3. 本着不行咱就换的精神,迅速用DPlayer替换掉Video.js,结果依旧不行。

解决

正当想着不然把Swiper换掉时,突然觉得这俩第三方组件也算很知名的了,不至于出现低级错误,可能还是有办法通过配置什么解决,联想到事件冲突,突然记起swiper-no-swipingSwiper提供了一个类名,它不处理这个类名的滑动事件,vjs-control-bar这个容器加上swiper-no-swiping这个类名,果然好了。

Swiper的源码里onTouchStart.js相关的代码

  // change target el for shadow root component
  const swipingClassHasValue = !!params.noSwipingClass && params.noSwipingClass !== '';
  // eslint-disable-next-line
  const eventPath = event.composedPath ? event.composedPath() : event.path;
  if (swipingClassHasValue && e.target && e.target.shadowRoot && eventPath) {
    targetEl = eventPath[0];
  }

  const noSwipingSelector = params.noSwipingSelector
    ? params.noSwipingSelector
    : `.${params.noSwipingClass}`;
  const isTargetShadow = !!(e.target && e.target.shadowRoot);

  // use closestElement for shadow root element to get the actual closest for nested shadow root element
  if (
    params.noSwiping &&
    (isTargetShadow
      ? closestElement(noSwipingSelector, targetEl)
      : targetEl.closest(noSwipingSelector))
  ) {
    swiper.allowClick = true;
    return;
  }

最后

虽然最终修复了这个问题,但按我的理解:

系统层面应该提供的只是鼠标位置给浏览器,浏览器再包装成相应事件给开发者,按理说Chrome版本相同内核相同应该不会出这个问题的吧,但这里我这里确实出现了,有没有大佬遇到过给解释一下原理