媒体库视频
介绍
本示例使用Video组件展示了视频组件的基本功能,包括视频组件化,全屏化,窗口化,上下轮播视频等。
效果预览
使用说明:
- 进入首页点击播放按键;
- 点击视频播放按钮,视频开始播放,再次点击视频进入视频全屏页;
- 首页下滑500vp后,视频小窗口化;
- 点击直播按钮进入直播页,上下滑动视频。
具体实现
- 视频播放:start方法视频开始播放,源码参考[VideoPage.ets];
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { router } from '@kit.ArkUI';
@Component
export struct VideoPage {
@State videoSrc: Resource = $rawfile('video1.mp4');
@State controls: boolean = false;
@State isFull: boolean = false;
@State isPause: boolean = true;
@State isPlayClick: boolean = true;
@State firstClick: boolean = true;
@State isHidden: boolean = true;
@Link isStart: boolean;
@Consume('playTime') updateTime: number;
detailVideoController: VideoController = new VideoController();
build() {
Column() {
Stack() {
Video({
src: this.videoSrc,
controller: this.detailVideoController
})
.width('100%')
.backgroundColor(this.isHidden ? '#ffffff' : '#000000')
.aspectRatio(1.12)
.controls(this.controls)
.objectFit(ImageFit.Contain)
.onUpdate((e) => {
this.updateTime = e.time;
})
.onPrepared((e) => {
console.info('VideoPage_onPrepared:' + e.duration);
})
.onClick(() => {
// Check whether the play button has been used. If not, go to this layer.
if (this.isPlayClick) {
// Click the video for the first time to start playing.
// Click the video again to enter the full screen.
if (this.firstClick) {
this.detailVideoController.start();
this.isHidden = !this.isHidden;
this.isStart = true;
this.firstClick = !this.firstClick;
} else {
router.pushUrl({ url: 'pages/FullPage',
params: { videoSrc: this.videoSrc, videoTime: this.updateTime } });
}
} else {
router.pushUrl({ url: 'pages/FullPage',
params: { videoSrc: this.videoSrc, videoTime: this.updateTime } });
}
})
.onFinish(() => {
this.isHidden = true;
this.isStart = false;
})
// Blank layer preview.
if(this.isHidden){
Column() {
Image($r('app.media.previewImg'))
.id('previewImg')
.objectFit(ImageFit.Contain)
}
.width('100%')
.aspectRatio(1.12)
.backgroundColor('#ffffff')
}
if(this.isHidden){
Column() {
Image($r('app.media.play'))
.id('playBtn')
.width(76)
.height(76)
.onClick(() => {
this.detailVideoController.start();
this.isHidden = !this.isHidden;
this.isStart = true;
this.isPlayClick = false;
})
}
}
}
.width('100%')
.height('100%')
}
}
}
- 全屏播放:再次点击视频进入全屏播放页面,使用setCurrentTime参数设定当前播放时间,pause方法停止播放,源码参考[FullPage.ets];
/*
* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { router } from '@kit.ArkUI';
import { mediaquery } from '@kit.ArkUI';
import { Callback } from '@kit.BasicServicesKit';
@Entry
@Component
export struct FullPage {
@State fullParams: routerParams | null = null;
@State fullSrc: Resource = $rawfile('video1.mp4');
@State isHidden: boolean = false;
@State maxValue: number = 0; // Total duration of the bottom time bar.
@State nowValue: number = 0; // Current seconds of the bottom time bar.
@State playTime: number = 0; // Playback time transferred from the previous page.
@State isPhone: boolean = false;
portraitFunc: Callback<mediaquery.MediaQueryResult> = (mediaQueryResult: mediaquery.MediaQueryResult): void => {
this.onPortrait(mediaQueryResult);
};
listenerIsPhone = mediaquery.matchMediaSync('(orientation:landscape)');
fullVideoController: VideoController = new VideoController();
onPortrait(mediaQueryResult: mediaquery.MediaQueryResult) {
this.isPhone = !mediaQueryResult.matches;
}
aboutToAppear() {
this.fullParams = router.getParams() as routerParams;
this.fullSrc = this.fullParams.videoSrc;
this.playTime = this.fullParams.videoTime;
this.listenerIsPhone.on('change', this.portraitFunc);
}
changTime(times: number): string {
if (times <= 0) {
return '00:00';
} else {
let mm = Math.floor(times / 60);
let ss = Math.floor(times % 60);
return (mm < 10 ? '0' + mm : mm) + ':' + (ss < 10 ? '0' + ss : ss);
}
}
build() {
Scroll() {
Column() {
Stack() {
Video({
src: this.fullSrc,
controller: this.fullVideoController
})
.width('100%')
.height('100%')
.autoPlay(true)
.loop(true)
.controls(false)
.objectFit(ImageFit.Contain)
.id('fullVideo')
.onPause(() => {
this.isHidden = true;
})
.onFullscreenChange((e) => {
this.isHidden = false;
})
.onStart(() => {
this.isHidden = false;
})
.onPrepared((e) => {
this.fullVideoController.setCurrentTime(this.playTime);
this.maxValue = e.duration;
})
.onUpdate((e) => {
this.nowValue = e.time;
})
.onClick(() => {
this.fullVideoController.pause();
})
if(this.isHidden){
Column() {
Image($r('app.media.play'))
.id('fullPlayBtn')
.width(78)
.height(78)
.onClick(() => {
this.fullVideoController.start();
this.isHidden = !this.isHidden;
})
}
.position({ x: this.isPhone ? '42%' : '47%', y: '45%' })
}
}
.width('100%')
.height('100%')
Column() {
Image($r('app.media.back'))
.id('backBtn')
.width(42)
.height(42)
.onClick(() => {
router.back();
})
}
.position({ x: '5%', y: '5%' })
Column() {
Image($r('app.media.share'))
.width(42)
.height(42)
}
.position({ x: this.isPhone ? '86%' : '95%', y: '5%' })
// Bottom Time Bar.
Row() {
Text(this.changTime(Number.parseInt(this.nowValue.toFixed(0)))).fontSize(18).fontColor(Color.White)
Slider({
value: this.nowValue,
min: 0,
max: this.maxValue,
style: SliderStyle.OutSet
})
.width('75%')
.blockColor(Color.White)
.trackColor('#cccccc')
.selectedColor('#E92F4F')
.showSteps(false)
.onChange((value: number, mode: SliderChangeMode) => {
this.nowValue = value;
this.fullVideoController.setCurrentTime(value);
console.info('value:' + value + 'mode:' + mode.toString());
})
Text(this.changTime(Number.parseInt(this.maxValue.toFixed(0))))
.fontSize(18)
.fontColor(Color.White)
}
.padding({ top: 50 })
.width('100%')
.position({ x: this.isPhone ? '3%' : '10%', y: '88%' })
}
.width('100%')
.height('100%')
.backgroundColor('#000000')
}
}
}
interface routerParams {
videoSrc: Resource;
videoTime: number;
}
- 小窗口播放:记录当前播放时间,小窗口页面渲染之前设置视频当前播放时间,页面滚动到固定距离开始展示组件;
- 直播:使用http接口的request方法获取直播数据,代码参考[Utils.ets];
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { http } from '@kit.NetworkKit';
let httpRequest = http.createHttp();
export function Live() {
return httpRequest.request(
"http://123.60.114.86:8090/goods/liveInfo?id=2",
{
header: {
'Content-Type': 'application/json'
},
readTimeout: 60000,
connectTimeout: 60000
});
}
以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下:
内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!
鸿蒙【北向应用开发+南向系统层开发】文档
鸿蒙【基础+实战项目】视频
鸿蒙面经
为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!