HarmonyOS开发案例:【视频播放器】

devtools/2024/9/24 5:03:46/

介绍

基于video、swiper和slider组件,实现简单的视频播放器,可支持海报轮播、视频播放等功能。

相关概念

  • [video组件]:视频播放组件。
  • [swiper组件]:滑动容器,提供切换子组件显示的能力。
  • [slider组件]:滑动z条组件,用来快速调节设置值,如音量、亮度等。

环境搭建

软件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release及以上版本。
  • OpenHarmony SDK版本:API version 9及以上版本。

硬件要求

  • 开发板类型:[润和RK3568开发板]。
  • OpenHarmony系统:3.2 Release及以上版本。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. [获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:

  2. 搭建烧录环境。

    1. [完成DevEco Device Tool的安装]
    2. [完成RK3568开发板的烧录]
  3. 搭建开发环境。

    1. 开始前请参考[工具准备],完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考[使用工程向导]创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用[真机进行调测]。
    4. 鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。

搜狗高速浏览器截图20240326151450.png

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。、

HarmonyOS与OpenHarmony鸿蒙文档籽料:mau123789是v直接拿

├──entry/src/main/js                          // 代码区
│  └──MainAbility   
│     ├──common
│     │  ├──constant
│     │  │  └──commonConstants.js             // 公共常量类
│     │  ├──images                            // 图片文件
│     │  └──video
│     │     └──video.mp4                      // 视频文件
│     ├──i18n
│     │  ├──en-US.json	                      // 英文国际化
│     │  └──zh-CN.json	                      // 中文国际化
│     ├──pages
│     │  ├──homePage
│     │  │  ├──homePage.css                   // 主页面样式
│     │	 │  ├──homePage.hml                   // 主页面
│     │	 │  └──homePage.js                    // 主页面逻辑
│     │  └──videoPage
│     │     ├──videoPage.css                  // 播放页面样式
│     │	    ├──videoPage.hml                  // 播放页面
│     │	    └──videoPage.js                   // 播放页面逻辑
│     └──app.js                               // 程序入口
└──entry/src/main/resource                    // 应用静态资源目录

主页面

主页面分为轮播图区域和滑动图区域两部分,效果如图所示:

轮播图使用swiper组件自动播放轮播图片,点击图片跳转到视频播放页面。

<!-- homePage.hml -->
<div class="container"><swiper class="swiper" id="swiper" index="0" autoplay='true' indicator="true"loop="true" digital="false"><image class="swiper-img" src="{{ swiperVideos[0] }}" onclick="playVideo"></image><image class="swiper-img" src="{{ swiperVideos[1] }}" onclick="playVideo"></image><image class="swiper-img" src="{{ swiperVideos[2] }}" onclick="playVideo"></image></swiper>...
</div>
// homePage.js
export default {data: {swiperVideos: [],...},// 初始化数据onInit() {...},// 跳转到视频播放页面playVideo() {router.push({url: CommonConstants.PLAY_PAGE});},
};

滑动图区域分为最近播放和为你推荐两部分,使用List组件进行纵向排列;最近播放和为你推荐中的图片使用List组件进行横向排列,可滑动图片,点击图片跳转到播放页面。

<!-- homePage.hml -->
<div class="container">...<div class="horizontal-area"><list class="todo-wrapper"><list-item for="{{ horizontal_description }}" class="todo-item" clickeffect="false"><div class="horizontal-area-div"><text class="horizontal-area-description">{{ $item }}</text><list class="todo-wrapper"><list-item for="{{ horizontal_videos }}" clickeffect="false" class="todo-item"><div class="image-area" onclick="playVideo"><image src="{{ $item.image }}"></image><text>{{ $item.name }}</text></div></list-item></list></div></list-item></list></div>
</div>
// homePage.js
export default {data: {...horizontal_description: [],horizontal_videos: []},// 初始化数据onInit() {...},// 跳转到视频播放页面playVideo() {router.push({url: CommonConstants.PLAY_PAGE});},
};

视频播放页面

视频播放页面主要分为标题栏、视频播放区域和进度条三个部分,效果如图所示:

标题栏包括返回图标和“视频”字样。

<!-- videoPage.hml -->
<div class="container"><div class="title"><image src="{{ playIcons.backSrc }}" onclick="back"></image><text>{{ $t('strings.play') }}</text></div>...
</div>
// videoPage.js
export default {data: {playIcons: {},...},// 初始化数据onInit() {this.playIcons = CommonConstants.PLAY_ICONS;...},...
};

当视频暂停时,视频区域展示暂停图标;当视频播放时,视频区域暂停图标隐藏,效果如图所示:

<!-- videoPage.hml -->
<div class="container">...<video id="video" ...></video><image class="play-image" show="{{ !isPlay }}" src="{{ playIcons.publicPlayIcon }}"></image>...
</div>
// videoPage.js
export default {data: {playIcons: {},...src: '',...isPlay: false,...},// 初始化数据onInit() {this.playIcons = CommonConstants.PLAY_ICONS;this.src = CommonConstants.VIDEO_SRC;},...
};

进度条分为播放/暂停图标和进度条(进度条左边为当前视频播放时间,进度条右边为视频总时长)两部分。

<div class="container">...<div class="progress"><div class="image-div"><image src="{{ isPlay ? playIcons.pauseIcon : playIcons.playIcon }}" onclick="startOrPause"></image></div><div class="slider-div"><text class="now-time">{{ nowTime }}</text><slider min="{{ sliderMin }}" max="{{ sliderMax }}" value="{{ sliderValue }}"mode="outset" onchange="change"></slider><text class="duration-time">{{ durationTime }}</text></div></div>
</div>
// videoPage.js
export default {data: {playIcons: {},...sliderMin: 0,sliderMax: 100,sliderValue: 0,nowTime: '00:00',duration: 0,durationTime: '00:00',isPlay: false,secondUnit: 60,zero: '0',initTime: '00:00',paddingLen: 2,milliSeconds: 1000,...},// 初始化数据onInit() {this.playIcons = CommonConstants.PLAY_ICONS;...},...
};

视频播放逻辑

视频播放器可设置是否静音播放、视频路径、是否自动播放、是否显示控制栏、是否循环播放等属性。

<!-- index.hml -->
<video id="video"muted="{{ muted }}"src="{{ src }}"autoplay="{{ autoplay }}"controls="{{ controlShow }}"loop="{{ loop }}"...
>
</video>
// index.js
data: {...videoId: 'video', // 播放器idmuted: false, // 是否静音播放src: '', // 视频地址autoplay: true, // 是否自动播放controlShow: false, // 是否显示控制栏loop: false, // 是否循环播放...
},

视频加载完成后获取视频总时长,当视频开始播放后获取视频当前播放时间(单位:秒)并更新进度条的值;拖动进度条可设置视频播放位置,点击播放/暂停图标可对视频进行控制。

<!-- index.hml -->
<video id="video"...onprepared="prepared"onstart="start"onpause="pause"onfinish="finish"ontimeupdate="timeUpdate">
</video>
...
<div class="progress"><div class="imageDiv"><image src="{{ isPlay ? playIcons.pauseIcon : playIcons.playIcon }}" onclick="startOrPause"></image></div><div class="sliderDiv">...<slider min="{{ sliderMin }}" max="{{ sliderMax }}" value="{{ sliderValue }}"mode="outset" onchange="change"></slider>...</div>
</div>
// index.js
...
// 视频准备完成
prepared(event) {this.duration = event.duration;this.durationTime = this.secondToTime(event.duration);
},// 视频开始播放
start() {this.isPlay = true;
},
// 视频暂停播放
pause() {this.isPlay = false;
},// 视频播放完成
finish() {setTimeout(() => {this.nowTime = this.initTime;this.sliderValue = this.sliderMin;}, this.milliSeconds);
},// 播放进度变化
timeUpdate(event) {if ((this.currentTime != -1) && (this.currentTime !== event.currenttime)) {return;}this.currentTime = -1;let currSliderValue = event.currenttime / this.duration * this.sliderMax;this.sliderValue = ((this.sliderValue > currSliderValue) ? this.sliderValue : currSliderValue);let currTime = this.sliderValue * this.duration / this.sliderMax;this.nowTime = this.secondToTime(Math.round(currTime));
},// 暂停或播放
startOrPause() {if (this.isPlay) {this.$element(this.videoId).pause();} else {this.$element(this.videoId).start();}
},// 拖动进度条
change(event) {this.sliderValue = event.progress;this.currentTime = Math.round(this.duration * event.progress / this.sliderMax);this.$element(this.videoId).setCurrentTime({currenttime: this.currentTime});
},
...

http://www.ppmy.cn/devtools/9607.html

相关文章

MATLAB初学者入门(11)—— 贪心算法

贪心算法是一种简单直观的算法设计方法&#xff0c;常用于解决需要做出一系列选择以达到最优解的问题。贪心算法的核心思想是每一步都选择当前看起来最好的选项&#xff0c;而不考虑大局。这种方法通常易于实现&#xff0c;但不总是能得到全局最优解。下面&#xff0c;将详细介…

本地搭建属于你自己的AI搜索引擎 支持多家AI模型

FreeAskInternet 是一个完全免费、私有且本地运行的搜索聚合器&#xff0c;并使用 MULTI LLM 生成答案&#xff0c;无需 GPU。用户可以提出问题&#xff0c;系统将进行多引擎搜索&#xff0c;并将搜索结果合并到LLM中&#xff0c;并根据搜索结果生成答案。全部免费使用。 项目…

CSS字体样式

字体样式包含字体的类型&#xff0c;大小&#xff0c;颜色等基本效果也包含字体粗细&#xff0c;下划线&#xff0c;斜体等特殊效果 字体的类型 CSS中font-family属性用来表示字体类型&#xff0c;基本格式&#xff1a;font-family:name。它可以指定多个字体&#xff0c;这些…

SpringBoot整合Mybatis

目录 一、引入依赖 二、创建实体类 三、编写mapper接口以及映射文件 Mapper接口 映射文件 四、编写application.yml配置文件 五、进行测试 之前搭建项目的时候&#xff0c;没有什么问题包括引入依赖&#xff0c;结果在测试的时候一直报错&#xff0c;后面原因竟然是引入…

设计模式:生活中的状态模式

让我们通过一个生活中的例子来深入理解状态模式&#xff1a;咖啡机的工作流程。想象一下&#xff0c;一个咖啡机有几种状态&#xff1a;无币状态、有币状态、制作咖啡状态和咖啡制作完成状态。用户在每个状态下与咖啡机的互动都是不同的。 状态模式在咖啡机中的应用 无币状态…

ElasticSearch:查询操作合集

先看下我的数据&#xff1a; 1、查询所有文档&#xff1a; GET /cartest/_search或者 GET /cartest/_search {"query": {"match_all": {}} }2、匹配查询&#xff1a; match匹配类型查询&#xff0c;会把查询条件进行分词&#xff0c;然后进行查询&…

Web3钱包开发获取测试币-Base Sepolia(二)

Web3钱包开发获取测试币-Base Sepolia(二) ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b0c0ac86b04a496087471388532bc54a.png) 基于上篇 Web3钱包开发获取测试币-Polygon Mumbai(一) &#xff1a;https://suwu150.blog.csdn.net/article/details/137949473 我…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用CFMIME Encoder方法进行图像压缩保存(C++)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK使用CFMIME Encoder方法进行图像压缩保存&#xff08;C&#xff09; Baumer工业相机Baumer工业相机通过NEOSDK进行图像压缩的技术背景代码分析第一步&#xff1a;先引用对应的NET框架的DLL文件第二步&#xff1a;在回调函数里进行…