如何用JS开发自定义播放栏的视频播放器

开发 前端
我们从属性、事件、方法中可以得出,以现在提供的能力,完全可以重写视频的控制栏。接下来就是界面的构思和布局。

[[429579]]

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

效果图

原始控件效果图:

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

修改后的效果图:

看过了演示效果,接下来讲解如何开发。

开发部分

在开发之前,我们要先翻阅文档,了解系统提供的能力。

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

我们从属性、事件、方法中可以得出,以现在提供的能力,完全可以重写视频的控制栏。

接下来就是界面的构思和布局:

界面布局

1. 整体布局

整体界面分为:视频播放、视频列表、评论区三大部分。

所以我们代码上先构建三个div。

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

2.video区域布局

想要把控制栏覆盖到video上面我们就需要借助stack组件,如下图:

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

视频控制栏我们分为上下两个部分,所以需要构建两个div来包裹里面控件,如下图:

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

再往下就是控制栏上细节上的控件了,包括文字、按钮、滑动条等,在此就不进行赘述了。

3.视频列表区域及评论区域

视频列表区域和评论区域排版相对比较简单,一个标题栏将显示区域进行分割,再一个list列表显示内容。

评论区域则多一栏评论功能,其结构排版如图:

如何用JS开发自定义播放栏的视频播放器 -鸿蒙HarmonyOS技术社区

整个排版结构大致介绍完毕,以下为hml页面的全部代码供参考:

  1. <div class="container"
  2.     <!--播放区域--> 
  3.     <div class="video"
  4.         <!--播放区域--> 
  5.         <div class="video-play" show="{{!isShowController}}"
  6.             <stack> 
  7.                 <video if="{{resetVideo}}" speed="{{playSpeed}}" @touchmove="videoTouchMoved" direction="horizontal" @error="resetVideo" id="m_video" src="{{playedVideo.src}}" @timeupdate="timeChanged" @prepared="mPrepared" @start="mStart" @pause="mStop" @finish="mStop" direction="horizontal" poster="{{playedVideo.image}}" @touchend="toolsTouched" controls="false"></video> 
  8.                 <!--工具栏,当触发屏幕时显示,n秒后自动隐藏--> 
  9.                 <div class="vide-tools" show="{{ showToolsTime>0 }}" @touchend="toolsTouched" @touchmove="videoTouchMoved"
  10.                     <div class="video-tools_child tools-top" @touchstart="childToolTouched"
  11.                         <div class="tools-left"
  12.                             <!--标题--> 
  13.                             <text class="title">{{playedVideo.name}}</text> 
  14.                         </div> 
  15.                         <div class="tools-top-right"
  16.                             <!--流转--> 
  17.                             <image class="control_button" @touchend="remoteIt" src="../../common/images/ic_hop.svg"></image > 
  18.                         </div> 
  19.                     </div> 
  20.  
  21.                     <div class="video-tools_child tools-bottom" @touchstart="childToolTouched"
  22.                         <div class="tools-left"
  23.                             <!--播放/暂停--> 
  24.                             <button @touchend="playOrPause" class="tools-btn">{{isPlayed?"‖":"▷"}}</button> 
  25.                             <!--当前播放时长--> 
  26.                             <text class="duration-text">{{thisTimeStr}}</text> 
  27.                             <!--滑块--> 
  28.                             <slider class="v-slider" step="1" max="{{ totalTime }}" value="{{thisTime}}" @change="sliderChanged"></slider> 
  29.                             <!--总播放时长--> 
  30.                             <text class="duration-text">{{totalTimeStr}}</text> 
  31.                         </div> 
  32.                         <div class="tools-right"
  33.                             <!--倍速--> 
  34.                             <button id="speedBtn" @touchend="showSpeedMenu" class="tools-btn btn-speed">{{speedStr}}</button> 
  35.                             <popup id="speedPopup" target="speedBtn" placement="top" > 
  36.                                 <div> 
  37.                                     <text class="speed-child" @touchend="{{speedChanged(2.0)}}">2.0X</text> 
  38.                                     <text class="speed-child" @touchend="{{speedChanged(1.5)}}">1.5X</text> 
  39.                                     <text class="speed-child" @touchend="{{speedChanged(1.0)}}">1.0X</text> 
  40.                                     <text class="speed-child" @touchend="{{speedChanged(0.5)}}">0.5X</text> 
  41.                                 </div> 
  42.                             </popup> 
  43.                             <!--全屏--> 
  44.                             <button class="tools-btn" @touchend="showAllScreen">{{isAllScreen?"╬":"▞"}}</button> 
  45.                         </div> 
  46.                     </div> 
  47.                 </div> 
  48.             </stack> 
  49.         </div> 
  50.     </div> 
  51.     <!--视频列表--> 
  52.     <div class="video-lists"
  53.         <text class="card-title">视频列表:</text> 
  54.         <list initialindex="{{playIndex}}" selected="{{playIndex}}" scrollbar="on" > 
  55.             <list-item for="{{ videoSource }}" @touchmove="listTouchMoved"  @touchend="{{checkVideo($idx)}}" > 
  56.                 <div class="preview-video"
  57.                     <image src="{{$item.image}}"></image> 
  58.                     <text>{{$item.name}}</text> 
  59.                 </div> 
  60.             </list-item> 
  61.         </list> 
  62.     </div> 
  63.     <!-- 评论区   --> 
  64.     <div class="comments"
  65.         <text class="card-title">评论区:</text> 
  66.         <!--评论列表--> 
  67.         <list divider="true"
  68.             <list-item for="thisComments"
  69.                 <div class="comment-info"
  70.                     <!--用户信息--> 
  71.                     <div class="comment-user"
  72.                         <label>用户:{{$item.user}}</label> 
  73.                     </div> 
  74.                     <!--内容--> 
  75.                     <div class="comment-content"
  76.                         <text>{{$item.content}}</text> 
  77.                     </div> 
  78.                 </div> 
  79.             </list-item> 
  80.         </list> 
  81.         <div class="comment-put"
  82.             <input id="commentMsg" @change="commentChanged" value="{{ commentContent }}" placeholder="请发表你的想法"></input> 
  83.             <button class="btn" @touchend="sendComment">发 布</button> 
  84.         </div> 
  85.     </div> 
  86. </div> 

当然仅有hml是不够的,还需要样式的配合,样式相关文件请参考gitee:https://gitee.com/panda-coder/harmonyos-apps/tree/master/Player。

逻辑控制-js

逻辑控制是个复杂的过程,每个人都有不同的实现方式,不可能细讲,就挑一部分进行讲解。

1.实现控制栏的功能

要想实现控制栏的播放/暂停、滑动条、全屏等基础功能需要依赖video控件的方法。只需要执行对应函数即可。

  1. this.$element(控件id).方法(参数) 

2.computed

computed是一个非常好用的属性方法。computed内的函数能在hml中直接使用,并且只要在computed函数的data数据改变就会触发重新计算。

例如:

  1. computed:{ 
  2.         playedVideo(){//当前播放视频 
  3.             return this.videoSource[this.playIndex] 
  4.         }, 

获取当前播放视频的数据,在上述方法中,this.videoSource或this.playIndex其中任何一个值进行修改,都会触发playedVideo函数进行重新计算。

这样处理一些实时变化的数据就非常的方便。代码中的totalTimeStr、thisTimeStr、speedStr这些值就是通过计算来返回一个格式化的文字内容。

3.$watch

在视频中有个功能,就是点击屏幕后显示控制栏,不操作间隔5s后控制栏自动消失,但是点击非控制栏部分直接消失,点击控制栏部分刷新时间间隔为5s。

大家可以先思考一下该怎么去设计这部分的逻辑控制,以及需要的函数逻辑操作等再往下看。

我使用$watch部分对showToolsTime 参数进行监听。

$watch是当监听的值改变后执行回调函数,并回传监听值变化前几变化后的值。

在onInit函数中监听showToolsTime。

  1. onInit() { 
  2.        this.$watch("showToolsTime",'watchShowToolsTimeEvent'
  3.        this.videoSource=data.videoSource 
  4.        this.commentsSource=data.comments 
  5.        this.playIndex=0; 
  6.        this.showToolsTime=5; 
  7.    },   
  8. /监听控制栏显示时间 
  9.    watchShowToolsTimeEvent(newV,oldV){ 
  10.        if(newV>0){ 
  11.            clearTimeout(this.watchTimer) 
  12.            this.watchTimer=setTimeout(()=>{ 
  13.                if(newV>oldV) 
  14.                    this.showToolsTime=newV 
  15.                --this.showToolsTime; 
  16.            },1000) 
  17.        }else
  18.            this.$element("speedPopup").hide() 
  19.        } 
  20.    }, 

在watchShowToolsTimeEvent中有两个关键点,一个是clearTimeout,另一个是返回值不能与newV相同。

js中的setTimeOut是异步执行,不清理掉timer(setTimeOut)在外部赋值后就会导致数据异步赋值问题。

返回值与newV一致$watch就失效了(除非外部激发),所以执行了this.showToolsTime=newV后也要执行–this.showToolsTime。

这样不管任何地方修改this.showToolsTime的值之后,都会进行每秒减1的运算(大于0的情况下)。

4.分布式能力

分布式能力参考官方文档,无特殊处理。

文档:https://developer.harmonyos.com/cn/docs/documentation/doc-references/js-apis-distributed-migration-0000001050024965

5.左右滑动切换视频

首先通过touchmove事件先收集手指滑动的坐标。

然后在touchend事件中判断手指滑动方向。

判断代码如下:

  1. getTouchMoveOrientation(source,num){ 
  2.         let orientation=[] 
  3.         for(let i=1;i<source.length;i++){ 
  4.             let startX=source[i-1].localX 
  5.             let startY=source[i-1].localY 
  6.             let moveEndX=source[i].localX 
  7.             let moveEndY=source[i].localY 
  8.             let X=moveEndX-startX; 
  9.             let Y=moveEndY-startY; 
  10.             if(Math.abs(X)>Math.abs(Y) && X>0){ 
  11.                 orientation.push("left2right"
  12.             }else if(Math.abs(X)>Math.abs(Y) && X<0){ 
  13.                 orientation.push("right2left"
  14.             }else if(Math.abs(X)<Math.abs(Y) && Y>0){ 
  15.                 orientation.push("top2bottom"
  16.             }else if(Math.abs(X)<Math.abs(Y) && Y<0){ 
  17.                 orientation.push("bottom2top"
  18.             } 
  19.         } 
  20.         let obj={},maxNum=0 
  21.         orientation.forEach((item,index)=>{ 
  22.             if(orientation.indexOf(item)==index){ 
  23.                 obj[item]=1 
  24.             }else
  25.                 obj[item]+=1 
  26.             } 
  27.         }) 
  28.  
  29.         for(let i in obj){ 
  30.             if(obj[i]>maxNum){ 
  31.                 maxNum=obj[i] 
  32.             } 
  33.         } 
  34.         if(maxNum<num) 
  35.            return "none" 
  36.         for(let i in obj){ 
  37.             if(obj[i]==maxNum) 
  38.                 return i 
  39.         } 
  40.     }, 

先收集滑动方向,然后再找出滑动方向最多的值,再和**阈值(num)**进行比较,超过阈值则返回滑动方向信息,否则返回“none”。

接下来再根据返回的滑动方向进行一系列操作(如:视频切换则改变this.playedIndexed值)。

接下来谈谈不足和感受:

1.list控件在滑动的过程中会触发触摸事件,需要开发者自行处理,不友好。

2.当video全屏时暂未找到怎么显示我写的自定义控件栏。

3.js组件开发暂无引入三方包功能(仅能引入纯js),Java有对应的har,js的三方组件库还未见引入身影。

4.为什么会提到js的三方组件库尼,就是因为原生的组件不够美观。想通过引入三方库来构建不同体系的组件(可能只是改改样式)希望尽快安排相关文档。

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-05-06 15:48:24

播放器鸿蒙

2022-08-16 17:37:06

视频播放器鸿蒙

2015-05-21 15:25:42

VLC播放器

2022-11-12 08:26:04

VLC视频播放器裁剪视频

2020-12-21 05:58:09

JavaScript视频播放器开发

2009-06-24 15:13:36

自定义JSF组件

2011-07-20 16:21:20

iPhone 视频 播放器

2018-05-25 14:37:58

2023-08-26 19:07:40

VLC旋转视频

2022-06-21 14:41:38

播放器适配西瓜视频

2011-06-13 09:33:04

2020-06-28 14:35:54

OBSWebSockets开源

2021-10-21 16:00:07

鸿蒙HarmonyOS应用

2021-10-19 14:27:07

鸿蒙HarmonyOS应用

2012-05-25 10:31:44

HTML5

2020-12-29 05:26:27

视频播放器Vuevideo

2012-06-04 13:44:08

2011-06-27 11:23:21

Qt 音乐播放器

2023-03-29 09:37:49

视频播放器应用鸿蒙

2023-03-28 09:44:02

开发应用鸿蒙
点赞
收藏

51CTO技术栈公众号