HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染
HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染
import { TimeBigMediaComponent } from './video'
import { TimeBigMediaVM } from './vm'
// xxx.ets
@Component
struct VideoCreateComponent {
timeBigMediaVM: TimeBigMediaVM = new TimeBigMediaVM()
// 视频
swiperVideoList: string[] = [
'http://vjs.zencdn.net/v/oceans.mp4',
'https://prod-streaming-video-msn-com.akamaized.net/ba258271-89c7-47bc-9742-bcae67c23202/f7ff4fe4-1346-47bb-9466-3f4662c1ac3a.mp4',
'https://prod-streaming-video-msn-com.akamaized.net/bc3e9341-3243-4d2c-8469-940fef56ca2d/4720a02b-eabd-4593-a1d9-5c5d61916853.mp4',
'https://prod-streaming-video-msn-com.akamaized.net/b701c37f-3464-4d0a-a165-4a9468080ebd/7afe0873-a1f4-4fad-b771-a917687fcfc6.mp4'
]
build() {
Stack({alignContent:Alignment.Bottom}) {
Swiper() {
this.builderVideo()
}
.onChange(() => {
this.timeBigMediaVM.controller.reset()
})
.height('100%')
.width('100%')
this.builderSlider()
}
}
@Builder
builderVideo() {
ForEach(this.swiperVideoList, (url: string) => {
Row() {
TimeBigMediaComponent({
timeBigMediaVM: this.timeBigMediaVM,
isVideo: true,
resourceUrl: url
})
}
})
}
// 自定义进度条
@Builder
builderSlider() {
Row() {
Row() {
Image(this.timeBigMediaVM.isVideoPlaying ?
'http://pic06.babytreeimg.com/knowledge/2024/1204/FiMmhAGAlKQTwhY78Wl3YuffJBdF' :
'http://pic08.babytreeimg.com/knowledge/2024/1203/Flui7PYdzn7YlewzZiXYzQinoY5d')
.width(this.timeBigMediaVM.handlePercentage(24))
.margin({ right: 4 })
}.onClick(() => { // 点击视频本体控制暂停播放
this.timeBigMediaVM.isVideoPlaying = !this.timeBigMediaVM.isVideoPlaying
this.timeBigMediaVM.isVideoPlaying == true ? this.timeBigMediaVM.controller.start() :
this.timeBigMediaVM.controller.pause()
})
Text(this.timeBigMediaVM.currentVideoProgressTime)
.lineHeight(20)
.fontColor('#FFFFFF')
.fontSize(14)
Slider({
value: this.timeBigMediaVM.currentVideoProgressInSecond,
max: this.timeBigMediaVM.videoLengthInSecond,
step: 1,
style: SliderStyle.OutSet
})
.margin({ left: 10, right: 10 })
.trackColor('rgba(255, 255, 255, 0.3)')
.selectedColor('#FFFFFF')
.blockSize({
width: 10,
height: 10
})//设置滑块大小
.width(this.timeBigMediaVM.handlePercentage(219))
.onChange((value: number, mode: SliderChangeMode) => {
this.timeBigMediaVM.currentVideoProgressInSecond = value
this.timeBigMediaVM.controller.setCurrentTime(value, SeekMode.Accurate)
this.timeBigMediaVM.currentVideoProgressTime = this.timeBigMediaVM.processSecondToTime(value)
})
Text(this.timeBigMediaVM.videoLengthTime)
.lineHeight(20)
.fontColor('#FFFFFF')
.fontSize(14)
}
.height(48)
.margin({ bottom: 34 + 48 })
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.Center)
.margin({ bottom: 32 + 48 })
.width('100%')
}
}
import { TimeBigMediaVM } from "./vm"
//视频图片组件
@Component
export struct TimeBigMediaComponent {
@Prop resourceUrl: string
@Prop isVideo: boolean //是否是视频类型
@Require timeBigMediaVM: TimeBigMediaVM = new TimeBigMediaVM()
aboutToAppear(): void {
this.isVideo = this.isVideo
}
build() {
Stack() {
if (this.isVideo) {
this.builderVideo()
} else {
Image(this.resourceUrl)
.objectFit(ImageFit.Contain)
}
}
.height('100%')
.width('100%');
}
@Builder
builderVideo() {
Stack({ alignContent: Alignment.BottomEnd }) {
Video({
src: this.resourceUrl,
controller: this.timeBigMediaVM.controller
})
.muted(false)//设置是否静音
.controls(false)//设置是否显示默认控制条
.autoPlay(true)//设置是否自动播放
.loop(true)//设置是否循环播放
.objectFit(ImageFit.Contain)
.onPrepared((e) => { // 视频加载完毕
this.timeBigMediaVM.videoLengthInSecond = e.duration
this.timeBigMediaVM.videoLengthTime = this.timeBigMediaVM.processSecondToTime(e.duration)
})
.onFinish(() => { // 播放结束的时候
this.timeBigMediaVM.currentVideoProgressTime = '00.00'
})
.onUpdate((e) => { // 播放进度变化的时候
this.timeBigMediaVM.currentVideoProgressInSecond = e.time // 用于把播放进度同步到自定义进度条的当前值中
this.timeBigMediaVM.currentVideoProgressTime = this.timeBigMediaVM.processSecondToTime(e.time)
})
}
.width('100%')
.height('100%')
}
}
@ObservedV2
export class TimeBigMediaVM{
controller: VideoController = new VideoController() //视频控制器
@Trace currentVideoProgressTime: string = '00.00'; //视频进度值
@Trace videoLengthTime: string = '00:00' // 视频进度最大值
@Trace currentVideoProgressInSecond: number = 0 // 视频当前滑块进度值
@Trace videoLengthInSecond: number = 0 // 视频总长度滑块最大值
@Trace isVideoPlaying: boolean = true // 控制是否播放
@Trace isVideo: boolean=false //是否是视频类型
//处理百分比
handlePercentage(number: number): string {
let result = (number / 375) * 100;
return result + '%'; // 将计算结果拼接上%符号后返回字符串形式
}
// 处理数据为 mm:ss 格式
processSecondToTime(seconds: number): string {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${String(minutes).padStart(2, '0')}:${String(remainingSeconds).padStart(2, '0')}`;
}
}
export class VideoPlayModel {
public currentTime: number = 0;
public currentStringTime: string = '00:00';
public durationTime: number = 0;
public durationStringTime: string = '00:00';
public isPlay: boolean = false;
public isOpacity: boolean = false;
public flag: boolean = false;
public isLoading: boolean = false;
public progressVal: number = 0;
public controller: VideoController = new VideoController();
}
更多关于HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
2 回复
你看你的代码,共用一个控制器,swiper每次change的时候你都reset,那肯定是重置的
更多关于HarmonyOS 鸿蒙Next:父来控制进度条,swiper可左右滑动视频,滑动了进度条则重置为0重新渲染的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS中,若要实现父组件控制进度条,同时swiper组件可左右滑动视频,并在滑动进度条时重置为0并重新渲染的功能,你可以采取以下策略:
-
父组件控制进度条:
-
swiper组件滑动视频:
- 利用swiper组件的滑动事件监听功能,结合视频播放器控件(如VideoPlayer)实现视频的左右滑动。
- 确保swiper组件的滑动与视频播放器的当前播放位置同步。
-
进度条滑动重置与重新渲染:
- 在进度条组件上添加滑动事件监听器。
- 当检测到滑动事件时,将进度条的值重置为0,并触发重新渲染swiper组件及其包含的视频内容。
- 这可能需要重新加载视频或重置视频播放器的状态。
请注意,实现上述功能可能需要结合HarmonyOS的UI框架和组件库进行具体开发。如果问题依旧没法解决请联系官网客服,官网地址是: https://www.itying.com/category-93-b0.html