您现在的位置是:亿华云 > 数据库
如何用JS开发自定义播放栏的视频播放器
亿华云2025-10-02 21:10:06【数据库】4人已围观
简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com效果图原始控件效果图:修改后的效果图:看过了演示效果,接下来讲解如何开发。开发部分在开发之
想了解更多内容,何用请访问:
和华为官方合作共建的自定鸿蒙技术社区
https://harmonyos.51cto.com
效果图
原始控件效果图:

修改后的效果图:
看过了演示效果,接下来讲解如何开发。义播
开发部分
在开发之前,放栏放器我们要先翻阅文档,频播了解系统提供的何用能力。

我们从属性、自定事件、义播方法中可以得出,放栏放器以现在提供的频播能力,完全可以重写视频的何用控制栏。
接下来就是自定界面的构思和布局:
界面布局
1. 整体布局
整体界面分为:视频播放、视频列表、义播评论区三大部分。放栏放器
所以我们代码上先构建三个div。频播

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

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

再往下就是控制栏上细节上的控件了,包括文字、按钮、滑动条等,在此就不进行赘述了。
3.视频列表区域及评论区域
视频列表区域和评论区域排版相对比较简单,一个标题栏将显示区域进行分割,亿华云再一个list列表显示内容。
评论区域则多一栏评论功能,其结构排版如图:

整个排版结构大致介绍完毕,以下为hml页面的全部代码供参考:
<div class="container"> <!--播放区域--> <div class="video"> <!--播放区域--> <div class="video-play" show="{ { !isShowController}}"> <stack> <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> <!--工具栏,当触发屏幕时显示,n秒后自动隐藏--> <div class="vide-tools" show="{ { showToolsTime>0 }}" @touchend="toolsTouched" @touchmove="videoTouchMoved"> <div class="video-tools_child tools-top" @touchstart="childToolTouched"> <div class="tools-left"> <!--标题--> <text class="title">{ { playedVideo.name}}</text> </div> <div class="tools-top-right"> <!--流转--> <image class="control_button" @touchend="remoteIt" src="../../common/images/ic_hop.svg"></image > </div> </div> <div class="video-tools_child tools-bottom" @touchstart="childToolTouched"> <div class="tools-left"> <!--播放/暂停--> <button @touchend="playOrPause" class="tools-btn">{ { isPlayed?"‖":"▷"}}</button> <!--当前播放时长--> <text class="duration-text">{ { thisTimeStr}}</text> <!--滑块--> <slider class="v-slider" step="1" max="{ { totalTime }}" value="{ { thisTime}}" @change="sliderChanged"></slider> <!--总播放时长--> <text class="duration-text">{ { totalTimeStr}}</text> </div> <div class="tools-right"> <!--倍速--> <button id="speedBtn" @touchend="showSpeedMenu" class="tools-btn btn-speed">{ { speedStr}}</button> <popup id="speedPopup" target="speedBtn" placement="top" > <div> <text class="speed-child" @touchend="{ { speedChanged(2.0)}}">2.0X</text> <text class="speed-child" @touchend="{ { speedChanged(1.5)}}">1.5X</text> <text class="speed-child" @touchend="{ { speedChanged(1.0)}}">1.0X</text> <text class="speed-child" @touchend="{ { speedChanged(0.5)}}">0.5X</text> </div> </popup> <!--全屏--> <button class="tools-btn" @touchend="showAllScreen">{ { isAllScreen?"╬":"▞"}}</button> </div> </div> </div> </stack> </div> </div> <!--视频列表--> <div class="video-lists"> <text class="card-title">视频列表:</text> <list initialindex="{ { playIndex}}" selected="{ { playIndex}}" scrollbar="on" > <list-item for="{ { videoSource }}" @touchmove="listTouchMoved" @touchend="{ { checkVideo($idx)}}" > <div class="preview-video"> <image src="{ { $item.image}}"></image> <text>{ { $item.name}}</text> </div> </list-item> </list> </div> <!-- 评论区 --> <div class="comments"> <text class="card-title">评论区:</text> <!--评论列表--> <list divider="true"> <list-item for="thisComments"> <div class="comment-info"> <!--用户信息--> <div class="comment-user"> <label>用户:{ { $item.user}}</label> </div> <!--内容--> <div class="comment-content"> <text>{ { $item.content}}</text> </div> </div> </list-item> </list> <div class="comment-put"> <input id="commentMsg" @change="commentChanged" value="{ { commentContent }}" placeholder="请发表你的想法"></input> <button class="btn" @touchend="sendComment">发 布</button> </div> </div> </div>当然仅有hml是不够的,还需要样式的配合,样式相关文件请参考gitee:https://gitee.com/panda-coder/harmonyos-apps/tree/master/Player。
逻辑控制-js
逻辑控制是个复杂的过程,每个人都有不同的实现方式,不可能细讲,就挑一部分进行讲解。
1.实现控制栏的功能
要想实现控制栏的播放/暂停、滑动条、全屏等基础功能需要依赖video控件的方法。只需要执行对应函数即可。
this.$element(控件id).方法(参数)2.computed
computed是一个非常好用的属性方法。computed内的函数能在hml中直接使用,并且只要在computed函数的站群服务器data数据改变就会触发重新计算。
例如:
computed:{ playedVideo(){ //当前播放视频 return this.videoSource[this.playIndex] }, }获取当前播放视频的数据,在上述方法中,this.videoSource或this.playIndex其中任何一个值进行修改,都会触发playedVideo函数进行重新计算。
这样处理一些实时变化的数据就非常的方便。代码中的totalTimeStr、thisTimeStr、speedStr这些值就是通过计算来返回一个格式化的文字内容。
3.$watch
在视频中有个功能,就是点击屏幕后显示控制栏,不操作间隔5s后控制栏自动消失,但是点击非控制栏部分直接消失,点击控制栏部分刷新时间间隔为5s。
大家可以先思考一下该怎么去设计这部分的逻辑控制,以及需要的函数逻辑操作等再往下看。
我使用$watch部分对showToolsTime 参数进行监听。
$watch是当监听的值改变后执行回调函数,并回传监听值变化前几变化后的值。
在onInit函数中监听showToolsTime。网站模板
onInit() { this.$watch("showToolsTime",watchShowToolsTimeEvent) this.videoSource=data.videoSource this.commentsSource=data.comments this.playIndex=0; this.showToolsTime=5; }, /监听控制栏显示时间 watchShowToolsTimeEvent(newV,oldV){ if(newV>0){ clearTimeout(this.watchTimer) this.watchTimer=setTimeout(()=>{ if(newV>oldV) this.showToolsTime=newV --this.showToolsTime; },1000) }else{ this.$element("speedPopup").hide() } },在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事件中判断手指滑动方向。
判断代码如下:
getTouchMoveOrientation(source,num){ let orientation=[] for(let i=1;i<source.length;i++){ let startX=source[i-1].localX let startY=source[i-1].localY let moveEndX=source[i].localX let moveEndY=source[i].localY let X=moveEndX-startX; let Y=moveEndY-startY; if(Math.abs(X)>Math.abs(Y) && X>0){ orientation.push("left2right") }else if(Math.abs(X)>Math.abs(Y) && X<0){ orientation.push("right2left") }else if(Math.abs(X)<Math.abs(Y) && Y>0){ orientation.push("top2bottom") }else if(Math.abs(X)<Math.abs(Y) && Y<0){ orientation.push("bottom2top") } } let obj={ },maxNum=0 orientation.forEach((item,index)=>{ if(orientation.indexOf(item)==index){ obj[item]=1 }else{ obj[item]+=1 } }) for(let i in obj){ if(obj[i]>maxNum){ maxNum=obj[i] } } if(maxNum<num) return "none" for(let i in obj){ if(obj[i]==maxNum) return i } },先收集滑动方向,然后再找出滑动方向最多的值,再和**阈值(num)**进行比较,超过阈值则返回滑动方向信息,否则返回“none”。
接下来再根据返回的滑动方向进行一系列操作(如:视频切换则改变this.playedIndexed值)。
接下来谈谈不足和感受:
1.list控件在滑动的过程中会触发触摸事件,需要开发者自行处理,不友好。
2.当video全屏时暂未找到怎么显示我写的自定义控件栏。
3.js组件开发暂无引入三方包功能(仅能引入纯js),Java有对应的har,js的三方组件库还未见引入身影。
4.为什么会提到js的三方组件库尼,就是因为原生的组件不够美观。想通过引入三方库来构建不同体系的组件(可能只是改改样式)希望尽快安排相关文档。
想了解更多内容,请访问:
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com
很赞哦!(5129)