纯JS分布式视频播放应用 原创 精华

发布于 2021-10-13 11:43
浏览
8收藏

一, 前言

       今时今日,不管是大人,还是小孩,都喜欢刷视频,生活中刷视频的APP也多得是,如:抖音,快手,视频号,今日头条,火山… 数也不数不清了,然而华为论坛鸿蒙版块搞活动,做一个属于自己的视频应用,说真的,看到这个活动我很开心,又可以用所学的鸿蒙知识来做一个小应用了,看了小提示,都是JS组件来实现的,当我看到分布式也可以用JS来写时,当时觉得JS也太强大了,因为之前写的Demo都是用Java来写分布式的,本人工作也是从事Java后台开发,对于JS前端知识,也就是入门级水平,然后就在想是用Java来写这个视频应用,还是用JS来写呢,通过看了JS参考API实例后,决定使用JS来写,简单易懂,同时也希望现在还在观望鸿蒙应用开发的前端开发人员,不要怕自己不会Java开发,而一直在观望,没有踏出第一步来写Demo,我写的这个视频应用取名为 爱视频 ,99%是用JS前端知识完成的,只有1%Java代码是复制过来的,也就是动态授权代码,所以希望还在观望的前端开发者,就从这个 爱视频 APP开始你们的第一个鸿蒙应用吧!

二, 实现效果
       开发环境下视频:https://www.bilibili.com/video/BV1kf4y177h2/?spm_id_from=333.788
       手机下视频:https://www.bilibili.com/video/BV1qr4y127s5?spm_id_from=333.999.0.0
纯JS分布式视频播放应用-开源基础软件社区       
三, 创建工程

       在这当作你已经安装好最新版本DevEco-Studio开发工具, 点击File -> New -> New Project… 弹出Create HarmonyOS Project窗口, 这里我选择空白JS模板创建, 写界面还是JS比较方便些, 对于有一定前端知识的小伙伴来说.
纯JS分布式视频播放应用-开源基础软件社区纯JS分布式视频播放应用-开源基础软件社区

四, 主界面开发

       在展示源代码之前,先介绍一下使用到了JS哪些组件:滑动容器(swiper),视频播放(video),可滑动面板(panel),列表组件(list),图片组件(image),文本组件(text),交互式组件(input),按钮组件(button) 通过查看JS API参考文档,就可以做出你喜欢的视频应用了。
       先介绍简单的1% Java代码,如果之前做过分布式Demo,直接复制过来就可以使用:

JAVA代码:

public class MainAbility extends AceAbility {
    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        // 动态判断权限
        if (verifySelfPermission("ohos.permission.DISTRIBUTED_DATASYNC") != IBundleManager.PERMISSION_GRANTED) {
            // 应用未被授予权限
            if (canRequestPermission("ohos.permission.DISTRIBUTED_DATASYNC")) {
                // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
                requestPermissionsFromUser(new String[]{"ohos.permission.DISTRIBUTED_DATASYNC"}, 0);
            }
        }
    }

    @Override
    public void onStop() {
        super.onStop();
    }
}

HML代码: 重要界面布局文件

<div class="container">
    <swiper class="swiper" id="swiper" index="{{ continueAbilityData.currentIndex }}" indicator="false" loop="true" digital="false" vertical="true" onchange="changeSwiper">
        <div class = "swiperContent" >
            <video id='videoOne' src='{{ continueAbilityData.videoList[0] }}' muted='false' autoplay='true'ontimeupdate='timeupdateCallback' style="object-fit:fill; width:100%; height: 100%;" controls="false" onclick="change_start_pause_one" loop='true' starttime = '{{ ontinueAbilityData.timeupdatetime }}'></video>
        </div>
        <div class = "swiperContent">
            <video id='videoTwo' src='{{ continueAbilityData.videoList[1] }}' muted='false' autoplay='false' ontimeupdate='timeupdateCallback' style="object-fit:fill; width:100%; height: 100%;" controls="false" onclick="change_start_pause_two" loop='true' starttime = '{{ ontinueAbilityData.timeupdatetime }}'></video>
        </div>
        <div class = "swiperContent">
            <video id='videoThree' src='{{ continueAbilityData.videoList[2] }}' muted='false' autoplay='false' ontimeupdate='timeupdateCallback' style="object-fit:fill; width:100%; height: 100%;" controls="false" onclick="change_start_pause_three" loop='true' starttime = '{{ continueAbilityData.timeupdatetime }}'></video>
        </div>
    </swiper>
    <div class="btn-footer">
        <image class="comment-icon icon" src="/common/army_icon.jpg"></image>
        <text class="footer-label">#HarmonyOS挑战赛第二期#</text>
        <image class="comment-icon" src="/common/share.png" onclick="tryContinueAbility"></image>
        <image class="comment-icon" src="/common/bxs-message.png" onclick="showPanel"></image>
    </div>
    <panel id="simplepanel" type="foldable" mode="half" miniheight="400px">
        <div class="panel-div">
            <list class="todo-wrapper">
                <list-item for="{{continueAbilityData.todolist}}" class="todo-item">
                    <image class="todo-icon" src="/common/avatar04.png"></image>
                    <text class="todo-title">{{$item.title}}</text>
                </list-item>
            </list>
            <div class="inner-btn">
                <input id="input" class="input" type="text" value="{{continueAbilityData.comment}}" maxlength="20" enterkeytype="send" placeholder="请输入评论内容" onchange="changeValue" onenterkeyclick="enterkeyClick" style="margin-right: 10px;"></input>
                <button type="capsule" value="关闭" onclick="closePanel"></button>
            </div>
        </div>
    </panel>
</div>

JS代码: 重要逻辑代码,各组件事件

// @ts-nocheck
import app from '@system.app';
export default {
    data: {
        img: "resources/media/pic_tv.png",
        continueAbilityData: {
            currentIndex: 0,
            videoList: [
                "/common/000001.mp4",
                "/common/000002.mp4",
                "/common/000003.mp4"
            ],
            timeupdatetime: 2,
            isStart: true,
            todolist: [
                {title: 'HDC2021活动门票进行中'},
                {title: '我期待HarmonyOS生态越来越完善'},
                {title: 'HarmonyOS你值得拥有'}],
            comment: ''
        }
    },
    onInit() {
    },
    changeSwiper(e) {
        console.info("onRestoreData:changeSwiper");
        this.switchPlay(e.index);
    },
    switchPlay(index) {
        console.info("onRestoreData:onShow <> " + index);
        this.continueAbilityData.currentIndex = index;
        if(index == 0) {
            this.$element('videoOne').start();
            this.$element('videoTwo').pause();
            this.$element('videoThree').pause();
            console.info("onRestoreData:videoOne <> start " + this.$element('videoOne').starttime);
        }else if(index == 1) {
            this.$element('videoOne').pause();
            this.$element('videoTwo').start();
            this.$element('videoThree').pause();
            console.info("onRestoreData:videoTwo <> start " + this.$element('videoTwo').starttime);
        }else if(index == 2) {
            this.$element('videoOne').pause();
            this.$element('videoTwo').pause();
            this.$element('videoThree').start();
            console.info("onRestoreData:videoThree <> start " + this.$element('videoThree').starttime);
        }
    },

    //流转事件
    tryContinueAbility: async function() {
        // 应用进行迁移
        let result = await FeatureAbility.continueAbility();
        console.info("result:" + JSON.stringify(result));
    },
    onStartContinuation() {
        // 判断当前的状态是不是适合迁移
        console.info("onStartContinuation");
        return true;
    },
    onCompleteContinuation(code) {
        // 迁移操作完成,code返回结果
        console.info("CompleteContinuation: code = " + code);
        app.terminate();

    },
    onSaveData(saveData) {
        // 数据保存到savedData中进行迁移。
        var data = this.continueAbilityData;
        console.info("onSaveData:" + JSON.stringify(data));
        Object.assign(saveData, data)
    },
    onRestoreData(restoreData) {
        console.info("onRestoreData:" + JSON.stringify(restoreData));
        // 收到迁移数据,恢复。
        this.continueAbilityData = restoreData;

        var currentIndex = this.continueAbilityData.currentIndex;
        var currentTime = this.continueAbilityData.timeupdatetime;

        this.$element('videoOne').pause();
        this.$element('videoTwo').pause();
        this.$element('videoThree').pause();

        this.$element('videoOne').starttime = currentTime;
        this.$element('videoTwo').starttime = currentTime;
        this.$element('videoThree').starttime = currentTime;

        this.switchPlay(currentIndex);
    },

    //评论事件
    showPanel() {
        this.$element('simplepanel').show()
    },
    closePanel() {
        this.$element('simplepanel').close()
    },
    changeValue(e) {
        this.continueAbilityData.comment = e.value;
    },
    enterkeyClick(e) {
        this.continueAbilityData.todolist.push({title: this.continueAbilityData.comment});
        this.continueAbilityData.comment = "";
    },
    timeupdateCallback:function(e){ this.continueAbilityData.timeupdatetime = e.currenttime;},
    change_start_pause_one: function() {
        if(this.continueAbilityData.isStart) {
            this.$element('videoOne').pause();
            this.continueAbilityData.isStart = false;
        } else {
            this.$element('videoOne').start();
            this.continueAbilityData.isStart = true;
        }
    },
    change_start_pause_two: function() {
        if(this.continueAbilityData.isStart) {
            this.$element('videoTwo').pause();
            this.continueAbilityData.isStart = false;
        } else {
            this.$element('videoTwo').start();
            this.continueAbilityData.isStart = true;
        }
    },
    change_start_pause_three: function() {
        if(this.continueAbilityData.isStart) {
            this.$element('videoThree').pause();
            this.continueAbilityData.isStart = false;
        } else {
            this.$element('videoThree').start();
            this.continueAbilityData.isStart = true;
        }
    }
}

CSS代码: 重要化妆技术

.container {
    width: 100%;
    height: 100%;
    flex-direction: column;
}

.img {
    object-fit: cover;
    background-color: #808080;
}

.swiper {
    flex-direction: column;
    align-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    background-color: black;
}
.swiperContent {
    height: 100%;
    justify-content: center;
    background-color: black;
}

.btn-footer {
    height: 60px;
    line-height: 60px;
    width: 100%;
    background-color: black;
    flex-direction: row;
}
.footer-label {
    font-size: 16px;
    color: white;
    padding-top: 0px;
    flex-weight: 1;
    line-height: 20px;
}
.comment-icon {
    width: 32px;
    height: 32px;
    margin: 8px;
}
.icon {
    border-radius: 16px;
}

.panel-div {
    flex-direction: column;
    align-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
}
.inner-btn {
    height: 70px;
    padding: 10px;
}
.todo-wrapper {
    width: 100%;
    height: 100%;
}
.todo-item {
    width: 100%;
    height: 30px;
    padding-left: 10px;
    padding-right: 10px;
}
.todo-icon {
    width: 16px;
    height: 16px;
    margin-top: 10px;
    margin-right: 10px;
}
.todo-title {
    width: 100%;
    height: 100%;
    text-align: left;
    font-size: 14fp;
}

代码就写到此了,不要忘记了config.json文件的权限配置哦,在module下添加

"reqPermissions": [
   {
      "name": "ohos.permission.DISTRIBUTED_DATASYNC"
   }
]

五, 总结

       说实存的,当看到这个活动时间才几天时,感觉时间不太够用,要滑动视频,要评论功能,要分布式的,加上都是用空闲时间来做的,然而当深入去理解相关组件用法后,发现应该一天时间就可以了。
       有兴趣的小伙伴可以下载源码查看, 项目代码写得还不算靓仔, 很多为了实现效果,都是Hardcode的,有空可以把重复代码抽出来,视频源也可以放到服务器上,然后就可以更愉快的刷更多视频了,源码同步到gitee码云,项目素材没有上传,自行添加。

源码在这: https://gitee.com/army16/qin-hong-jun-video

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-10-13 11:43:03修改
15
收藏 8
回复
举报
回复
添加资源
添加资源将有机会获得更多曝光,你也可以直接关联已上传资源 去关联
    相关推荐