web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器
小职 2021-10-28 来源 :鸿蒙社区 阅读 1572 评论 0

摘要:本篇主要介绍了web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器,通过具体的内容展现,希望对大家web前端JavaScript开发的学习有一定的帮助。

本篇主要介绍了web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器,通过具体的内容展现,希望对大家web前端JavaScript开发的学习有一定的帮助。

web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器

效果图


原始控件效果图:

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器



修改后的效果图:

 

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器

 

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

 

开发部分

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

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器

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

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

 

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

 

界面布局

1. 整体布局

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

 

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

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器

2.video区域布局

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

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器


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

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器


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

 

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

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

 

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

 web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器


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

 

<div>

    <!--播放区域-->

    <div>

        <!--播放区域-->

        <div 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 show="{{ showToolsTime>0 }}" @touchend="toolsTouched" @touchmove="videoTouchMoved">

                    <div class="video-tools_child tools-top" @touchstart="childToolTouched">

                        <div>

                            <!--标题-->

                            <text>{{playedVideo.name}}</text>

                        </div>

                        <div>

                            <!--流转-->

                            <image @touchend="remoteIt" src="../../common/images/ic_hop.svg"></image >

                        </div>

                    </div>

 

                    <div class="video-tools_child tools-bottom" @touchstart="childToolTouched">

                        <div>

                            <!--播放/暂停-->

                            <button @touchend="playOrPause">{{isPlayed?"‖":"▷"}}</button>

                            <!--当前播放时长-->

                            <text>{{thisTimeStr}}</text>

                            <!--滑块-->

                            <slider step="1" max="{{ totalTime }}" value="{{thisTime}}" @change="sliderChanged"></slider>

                            <!--总播放时长-->

                            <text>{{totalTimeStr}}</text>

                        </div>

                        <div>

                            <!--倍速-->

                            <button id="speedBtn" @touchend="showSpeedMenu" class="tools-btn btn-speed">{{speedStr}}</button>

                            <popup id="speedPopup" target="speedBtn" placement="top" >

                                <div>

                                    <text @touchend="{{speedChanged(2.0)}}">2.0X</text>

                                    <text @touchend="{{speedChanged(1.5)}}">1.5X</text>

                                    <text @touchend="{{speedChanged(1.0)}}">1.0X</text>

                                    <text @touchend="{{speedChanged(0.5)}}">0.5X</text>

                                </div>

                            </popup>

                            <!--全屏-->

                            <button @touchend="showAllScreen">{{isAllScreen?"╬":"▞"}}</button>

                        </div>

                    </div>

                </div>

            </stack>

        </div>

    </div>

    <!--视频列表-->

    <div>

        <text>视频列表:</text>

        <list initialindex="{{playIndex}}" selected="{{playIndex}}" scrollbar="on" >

            <list-item for="{{ videoSource }}" @touchmove="listTouchMoved"  @touchend="{{checkVideo($idx)}}" >

                <div>

                    <image src="{{$item.image}}"></image>

                    <text>{{$item.name}}</text>

                </div>

            </list-item>

        </list>

    </div>

    <!-- 评论区   -->

    <div>

        <text>评论区:</text>

        <!--评论列表-->

        <list divider="true">

            <list-item for="thisComments">

                <div>

                    <!--用户信息-->

                    <div>

                        <label>用户:{{$item.user}}</label>

                    </div>

                    <!--内容-->

                    <div>

                        <text>{{$item.content}}</text>

                    </div>

                </div>

            </list-item>

        </list>

        <div>

            <input id="commentMsg" @change="commentChanged" value="{{ commentContent }}" placeholder="请发表你的想法"></input>

            <button @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的三方组件库尼,就是因为原生的组件不够美观。想通过引入三方库来构建不同体系的组件(可能只是改改样式)希望尽快安排相关文档。


我是小职,记得找我

✅ 解锁高薪工作

✅ 免费获取基础课程·答疑解惑·职业测评

web前端Javascript开发实战之用JS开发自定义播放栏的视频播放器

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved