文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Javascript如何实现类似西瓜视频的视频队列自动播放?

2024-12-14 00:53

关注

这里有一个很常见的例子,平时喜欢看短视频的朋友可能会注意到,我们在浏览某视频头条时,滚动视频列表,当某一个视频滚动到手机的一定位置时(一般可以看成是屏幕中心),该视频会自动播放,当移出指定区域后视频会自动关闭并播放移入指定区域的下一个视频,如下:

作为一名好奇心极强的前端工程师,有必要好好研究一下其内部实现。

我的第一思路就是监听滚动位置来判断某个视频元素是否到达指定区域内,但是这种方式需要处理的条件很多,比如边界条件判断,滚动方向判断等,而且频繁触发还会出现性能问题。

好在之前深入研究过Intersection Observer API,发现可以使用它提供的API,很方便的监听到元素在指定根元素下的位置变化,并做一些自定义操作:

接下来我将利用Intersection Observer提供的api来实现视频在滚动的过程中自动播放的功能,如果对该api不太熟悉的朋友可以移步

几个非常有意思的javascript知识点总结

视频播放插件笔者将使用比较流行的Dplayer,它可以很方便的操作视频的展现并实现很好的排他性播放控制,并且支持弹幕。

正文

根据以上的介绍我们大致了解了具体的需求,接下来我们就来基于Intersection Observer API实现一下它。思路大致如下图所示:

具体思路就是我们可以把Intersection Observer的根元素的rootMargin(即根元素的外边距)设置为如上图蓝色所示区域,然后当视频完全进入该区域内后(也就是thresholds阈值为1时),触发当前视频的播放即可。因为我们使用的是Dplayer,所以我们只要将其配置属性中的mutex属性设置为true(为true时会阻止多个播放器同时播放,当前播放器播放时暂停其他播放器)。有关设置rootMargin的知识,可以参考下图介绍:

rootMargin接收格式如下:"10px 0px 10px 0px",从左到右数字依次代表top(上) right(右) bottom(下) left(左)边距,当然我们单位也可以使用百分比(%),为正值时代表扩大更元素的边距范围,负值代表缩小根元素的边距范围,这里我们应该缩小范围,所以rootMargin我们可以这么设置"-180px 0px -180px 0px",这样上下的边距就会缩小,当然大家也可以根据需求设置不同的值。

有了以上思路之后我们就可以实现上文动图所展示的效果了。笔者将采用react来实现,在实现之前我们先准备几个视频素材,然后实现列表基本框架:

  1. import React, { useEffect, useState } from 'react' 
  2. import VideoItem from 'components/VideoItem' 
  3. import styles from './videoList.less' 
  4.  
  5. const data = [ 
  6.     // 视频列表 
  7.  
  8. function VideoList(props) { 
  9.   useEffect(() => { 
  10.     let observerVideo = new IntersectionObserver( 
  11.         (entries, observer) => { 
  12.             entries.forEach(entry => { 
  13.                 // 当移入指定区域内后,播放视频 
  14.                 if(entry.intersectionRatio === 1) { 
  15.                     // 一些操作 
  16.                     return 
  17.                 } 
  18.                 // 停止监听 
  19.                 // observer.unobserve(entry.target); 
  20.               }); 
  21.             }, 
  22.             { 
  23.               root: document.getElementById('scrollView'), 
  24.               rootMargin: '-180px 0px -180px 0px'
  25.               threshold: 1 
  26.             } 
  27.         ); 
  28.         document.querySelectorAll('.video-item').forEach(video => { observerVideo.observe(video) }); 
  29.   }, []) 
  30.   return  
  31.     "scrollView"
  32.         { 
  33.             data.map(item => { 
  34.                 return "video-item" key={item} /> 
  35.             }) 
  36.         } 
  37.     
 
  •   
  •  
  •  
  • export default VideoList 
  • 以上代码中VideoItem组件我们后面会介绍,现在有个问题是我们已经监听到了需要自动播放的视频元素,但是我们如何通知VideoItem组件让其播放呢?这里笔者实现思路是给VideoItem添加一个自定义属性,该属性的值就是当前video的src,我们在监听到某个视频元素需要播放时,我们可以获取到之前设置的自定义属性,然后作为prop传给VideoItem,当VideoItem组件监听到该prop变化时,并且等于自身的src,此时则触发视频播放。代码如下:

    1. // VideoItem.js 
    2. import React, { useRef, useEffect } from 'react'
    3. import DPlayer from 'dplayer'
    4.  
    5. export default (props) => { 
    6.     let videoRef = useRef(null
    7.     let dpRef = useRef(null
    8.     let { src, groupName, curPlaySrc } = props 
    9.     useEffect(() => { 
    10.         dpRef.current = new DPlayer({ 
    11.             container: videoRef.current
    12.             screenshot: true
    13.             video: { 
    14.                 url: src, 
    15.                 thumbnails: 'logo.png' 
    16.             }, 
    17.             logo: 'logo.png' 
    18.         }); 
    19.     }, []) 
    20.  
    21.     useEffect(() => { 
    22.         // 当当当前应该播放的视频url等于当前视频组件的src时,播放视频 
    23.         if(curPlaySrc === src) { 
    24.             dpRef.current.play() 
    25.         } 
    26.     }, [curPlaySrc]) 
    27.     return  
    28.          
    29.      

    此时视频列表页代码如下:

    1. // ... 
    2. function VideoList(props) { 
    3.   const [curPlaySrc, setCurPlaySrc] = useState(''
    4.   useEffect(() => { 
    5.     let observerVideo = new IntersectionObserver( 
    6.         (entries, observer) => { 
    7.             entries.forEach(entry => { 
    8.                 // 当移入指定区域内后,播放视频 
    9.                 if(entry.intersectionRatio === 1) { 
    10.                     // 设置当前因该播放的视频url 
    11.                     setCurPlaySrc(entry.target.dataset.src) 
    12.                     return 
    13.                 } 
    14.               }); 
    15.             }, 
    16.             { 
    17.               root: document.getElementById('scrollView'), 
    18.               rootMargin: '-180px 0px -180px 0px'
    19.               threshold: 1 
    20.             } 
    21.         ); 
    22.         document.querySelectorAll('.video-item').forEach(video => { observerVideo.observe(video) }); 
    23.   }, []) 
    24.   return  
    25.     "scrollView"
    26.         { 
    27.             data.map(item => { 
    28.                 return "video-item" key={item} curPlaySrc={curPlaySrc} /> 
    29.             }) 
    30.         } 
    31.      
    32.    

    以上步骤即完成了基于指定区域自动播放视频的功能,效果如下:

    体验地址

    视频自动播放demo

    仿微信朋友圈动态demo

    最后

     

    如果想学习更多H5游戏, webpack,node,gulp,css3,javascript,nodeJS,canvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。

     

    来源:趣谈前端内容投诉

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    软考中级精品资料免费领

    • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

      难度     813人已做
      查看
    • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

      难度     354人已做
      查看
    • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

      难度     318人已做
      查看
    • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

      难度     435人已做
      查看
    • 2024年上半年系统架构设计师考试综合知识真题

      难度     224人已做
      查看

    相关文章

    发现更多好内容

    猜你喜欢

    AI推送时光机
    位置:首页-资讯-后端开发
    咦!没有更多了?去看看其它编程学习网 内容吧
    首页课程
    资料下载
    问答资讯