From 2ce44f82ed270aae54f4c7b1e37adf4c2302ec10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E6=B3=89=E6=B2=B3?= Date: Mon, 10 Oct 2022 17:43:30 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9F=B3=E9=A2=91=E6=92=AD=E6=94=BE=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/ets/Components/VideoGestureView.ets | 169 ++++++++++++++++++ entry/main/ets/Components/VideoView.ets | 59 ++++++ 2 files changed, 228 insertions(+) create mode 100644 entry/main/ets/Components/VideoGestureView.ets create mode 100644 entry/main/ets/Components/VideoView.ets diff --git a/entry/main/ets/Components/VideoGestureView.ets b/entry/main/ets/Components/VideoGestureView.ets new file mode 100644 index 0000000..d85a053 --- /dev/null +++ b/entry/main/ets/Components/VideoGestureView.ets @@ -0,0 +1,169 @@ + + +import MediaPlayService from '../model/media/MediaPlayService'; +import { MediaPlayerState, VideoPlayerGestureType } from '../model/media/MediaConstants'; +import DateTimeUtils from '../util/DateTimeUtils' + +@Component +export default struct VideoGestureView { + private service: MediaPlayService + private startFocusX: number + private startFocusY: number + private gestureValue: number + private gestureType: VideoPlayerGestureType = VideoPlayerGestureType.IDLE + @State controlHint: string = '' + @State controlTypeSrc: Resource = undefined + @State isShow: boolean = false + private onStateUpdate: (isShow: boolean) => void + + aboutToAppear() { + if (this.service != null) { + this.service.addStatusChangedListener((state, extra) => { + switch (state) { + case MediaPlayerState.STOP: + case MediaPlayerState.IDLE: + case MediaPlayerState.ERROR: + case MediaPlayerState.FINISH: + this.setViewShow(false) + break; + } + }) + } + } + + private setViewShow(isShow: boolean) { + if (isShow != this.isShow) { + this.isShow = isShow + this.onStateUpdate(isShow) + } + } + + private getFocusPoint(event: TouchEvent) { + let sumX = 0; + let sumY = 0; + let count = event.touches.length; + for (let i = 0;i < event.touches.length; i++) { + sumX += event.touches[i].x + sumY += event.touches[i].y + } + return { x: sumX / count, y: sumY / count }; + } + + // 手指移动 + onFingerMove(focusX, focusY) { + let changedValue + let offsetX = focusX - this.startFocusX + let offsetY = focusY - this.startFocusY + switch (this.gestureType) { + case VideoPlayerGestureType.IDLE: + // 根据按下的位置,设置当前模式 + if (Math.abs(offsetX) == Math.abs(offsetY)) { + break + } else if (Math.abs(offsetX) > Math.abs(offsetY)) { + this.gestureType = VideoPlayerGestureType.PROGRESS_CONTROL + } else if (this.startFocusX > px2vp(globalThis.display.width) / 2) { + this.gestureType = VideoPlayerGestureType.VOLUME_CONTROL + } else { + this.gestureType = VideoPlayerGestureType.BRIGHT_CONTROL + } + this.setViewShow(true) + break; + case VideoPlayerGestureType.PROGRESS_CONTROL: + // 当前为进度控制模式,计算位移量 + changedValue = this.service.getCurrentTime() + offsetX / px2vp(globalThis.display.width) * this.service.getDuration() + this.gestureValue = (changedValue <= 0 ? 0 : (changedValue >= this.service.getDuration() ? this.service.getDuration() : changedValue)) + this.controlHint = DateTimeUtils.ms2CountdownTime(Math.round(this.gestureValue / 1000) * 1000) + '/' + DateTimeUtils.ms2CountdownTime(this.service.getDuration()) + this.controlTypeSrc = (offsetX >= 0 ? $r('app.media.ic_forward') : $r('app.media.ic_backward')) + break; + case VideoPlayerGestureType.VOLUME_CONTROL: + // 当前为音量控制模式,计算位移量 + changedValue = this.service.getVolume() - offsetY / px2vp(globalThis.display.height) + this.gestureValue = (changedValue <= 0 ? 0 : (changedValue >= 1 ? 1 : changedValue)) + this.controlHint = Math.round(this.gestureValue * 100) + '%' + this.controlTypeSrc = $r('app.media.ic_horns') + break; + case VideoPlayerGestureType.BRIGHT_CONTROL: + // 当前为亮度控制模式,计算位移量 + changedValue = this.service.getBrightness() - offsetY / px2vp(globalThis.display.height) + this.gestureValue = (changedValue <= 0 ? 0 : (changedValue >= 1 ? 1 : changedValue)) + this.controlHint = Math.round(this.gestureValue * 100) + '%' + this.controlTypeSrc = $r('app.media.ic_bright') + break; + } + } + + // 手指松开 + onFingerUp() { + switch (this.gestureType) { + case VideoPlayerGestureType.PROGRESS_CONTROL: + // 设置播放进度 + this.service.seek(this.gestureValue) + break; + case VideoPlayerGestureType.VOLUME_CONTROL: + // 设置音量 + this.service.setVolume(this.gestureValue) + break; + case VideoPlayerGestureType.BRIGHT_CONTROL: + // 设置亮度 + this.service.setBrightness(this.gestureValue) + break; + } + // 重置当前模式 + this.gestureType = VideoPlayerGestureType.IDLE + this.setViewShow(false) + } + + build() { + Stack({ alignContent: Alignment.Center }) { + if (this.isShow) { + Column() { + Image(this.controlTypeSrc) + .width(40) + .height(40) + .objectFit(ImageFit.Fill) + Text(this.controlHint).margin({ top: 15 }).fontColor('#ffffff') + } + .width(120) + .height(120) + .padding({ left: 10, right: 10, top: 20, bottom: 20 }) + .justifyContent(FlexAlign.Center) + .alignItems(HorizontalAlign.Center) + .backgroundColor('#88000000') + .borderRadius(10) + } + } + .width('100%') + .height('100%') + .backgroundColor('#00000000') + .onTouch((event) => { + if (this.service != null + && (this.service.getPlayerState() == MediaPlayerState.PLAY + || this.service.getPlayerState() == MediaPlayerState.PAUSE) + ) { + let focusPoint = this.getFocusPoint(event) + // 手指按下 + if (event.type === TouchType.Down) { + this.startFocusX = focusPoint.x + this.startFocusY = focusPoint.y + } else if (event.type === TouchType.Move) {// 手指移动 + this.onFingerMove(focusPoint.x, focusPoint.y) + } else if (event.type === TouchType.Up) { + this.onFingerUp() + } + } + }) + .gesture( + TapGesture({ count: 2 }) + .onAction(() => { + if (this.service != null) { + if (this.service.getPlayerState() == MediaPlayerState.PLAY) { + this.service.pause() + } else { + this.service.resume() + } + } + }) + ) + } +} + diff --git a/entry/main/ets/Components/VideoView.ets b/entry/main/ets/Components/VideoView.ets new file mode 100644 index 0000000..cafab94 --- /dev/null +++ b/entry/main/ets/Components/VideoView.ets @@ -0,0 +1,59 @@ + +import MediaPlayService from '../model/media/MediaPlayService' +import { MediaPlayerState } from '../model/media/MediaConstants' +import prompt from '@system.prompt'; + +@Component +export default struct VideoView { + private service: MediaPlayService + private playerAreaController = new XComponentController() + private isContentFull: boolean = false + @State ratio: number = 0 + private onCreated: (id) => void + + aboutToAppear() { + if (this.service != null) { + this.service.addStatusChangedListener((state, extra) => { + switch (state) { + case MediaPlayerState.SIZE_CHANGED: + if (!this.isContentFull) { + this.ratio = extra.width / extra.height + this.playerAreaController.setXComponentSurfaceSize({ + surfaceWidth: extra.width, + surfaceHeight: extra.height + }) + } + break; + case MediaPlayerState.ERROR: + if (extra.code == -331350011 || extra.code == -331350014 || extra.code == -331350007) { + prompt.showDialog({ message: '播放错误,请检查播放源,如果是在线视频,请检查网络是否连接。错误码:' + extra.code }) + } + break; + } + }) + } + } + + build() { + Stack() { + + + XComponent({ + id: '', + type: 'surface', + libraryname: '', + controller: this.playerAreaController + }) + .onLoad(() => { + let renderId = this.playerAreaController.getXComponentSurfaceId() + if (this.service != null) { + this.service.addSurface(renderId) + } + this.onCreated(renderId) + }) + .aspectRatio(this.ratio) + }.backgroundColor('#ffffff') + .width('100%') + .height('100%') + } +} \ No newline at end of file -- Gitee