HarmonyOS 鸿蒙Next 如何在Swiper里实现视频播放器双指缩放并拖动?
HarmonyOS 鸿蒙Next 如何在Swiper里实现视频播放器双指缩放并拖动?
手势响应链如下:
捏合 + Pan的响应链是:PinchGesture onActionStartPanGesture onActionStartPanGesture onActionUpdatePanGesture onActionUpdatePanGesture onActionUpdatePanGesture onActionUpdatePanGesture onActionEnd
诉求:可以正常收到pinchGesture的onActionUpdate回调
// src/main/ets/preview/Component/GalleryImage.ets
import display from '[@ohos](/user/ohos).display';
import {
FingerDirection,
HorizontalBoundary,
ImageMeta,
OnCompleteMsg,
TouchPos,
VerticalBoundary
} from '../interface';
[@Component](/user/Component)
export struct GalleryImage {
[@Consume](/user/Consume)('pageInfos') pageInfos: NavPathStack;
private MAX_SCALE = 3;
private MIN_SCALE = 0.7;
private DOUBLE_CLICK_SCALE = 1.5;
[@Prop](/user/Prop) url: string = '';
[@Prop](/user/Prop) index: number = 0;
[@Prop](/user/Prop) showMenu: boolean = false;
[@Link](/user/Link) isScaling: boolean;
[@State](/user/State) downLoadEnable: boolean = false;
[@State](/user/State) alt_name: string | Resource = $r('app.media.gallery_image_alt')
[@State](/user/State) showLoading: boolean = false;
[@State](/user/State) rotateAngle: number = 0;
[@State](/user/State) isImageError: boolean = false;
[@State](/user/State) touchFlag: number = 1;
[@State](/user/State) temp: number = 0;
[@State](/user/State) tempY: number = 0;
private imageMeta: ImageMeta = {
IMAGE_NAME: '',
SUFFIX: '',
IMAGE_WIDTH: 0,
IMAGE_HEIGHT: 0,
PAN_DIRECTION: PanDirection.All,
MAX_SCALE_VALUE: this.MAX_SCALE
};
[@State](/user/State) scaleValue: number = 1;
[@State](/user/State) pinchValue: number = 1;
[@State](/user/State) pinchX: number | string = '50%';
[@State](/user/State) pinchY: number | string = '50%';
private panOption: PanGestureOptions = new PanGestureOptions({
direction: this.imageMeta.PAN_DIRECTION,
fingers: 1,
distance: 2
});
[@State](/user/State) offsetX: number = 0;
[@State](/user/State) offsetY: number = 0;
private positionX: number = 0;
private positionY: number = 0;
private touchPos: TouchPos = {
x: 0,
y: 0
};
[@State](/user/State) fingerDirection: FingerDirection = FingerDirection.UNKNOWN;
[@State](/user/State) xBoundary: HorizontalBoundary = HorizontalBoundary.MIDDLE;
[@State](/user/State) yBoundary: VerticalBoundary = VerticalBoundary.MIDDLE;
[@State](/user/State) leftBoundary: number = 0;
[@State](/user/State) rightBoundary: number = 0;
[@State](/user/State) topBoundary: number = 0;
[@State](/user/State) bottomBoundary: number = 0;
aboutToAppear(): void {
}
aboutToDisappear(): void {
}
build() {
Column() {
Video({ src: this.url, previewUri: $r('app.media.gallery_video_unmute_icon') })
.width('100%')
.height('100%')
.objectFit(ImageFit.Contain)
.autoPlay(true)
.loop(true)
.controls(false)
.scale({
x: this.scaleValue,
y: this.scaleValue,
z: 1,
centerX: this.pinchX,
centerY: this.pinchY
})
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.onImageGesture()
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
// 重置
reset() {
animateTo({
duration: 400,
}, () => {
this.scaleValue = 1;
this.pinchX = '50%';
this.pinchY = '50%';
this.pinchValue = this.scaleValue;
this.offsetX = 0;
this.offsetY = 0;
this.positionX = 0;
this.positionY = 0;
this.xBoundary = 0;
this.yBoundary = 0;
})
}
[@Styles](/user/Styles)
onImageGesture(){
.gesture(
GestureGroup(GestureMode.Parallel,
// 两指或以上的捏合手势
PinchGesture({ fingers: 2, distance: 0.1 })
.onActionUpdate((event: GestureEvent) => {
this.onPinchGestureActionUpdate(event);
})
.onActionEnd(() => {
this.onPinchGestureActionEnd();
}),
// 拖动手势
PanGesture(this.panOption)
.onActionUpdate((event?: GestureEvent) => {
this.onPanGestureActionUpdate(event);
})
.onActionEnd(() => {
this.onPanGestureActionEnd();
}),
// 滑动手势
SwipeGesture({ direction: SwipeDirection.Vertical })
.onAction((event?: GestureEvent) => {
console.log("SwipeGesture onAction --");
}),
)
)
}
// 当捏合手势触发时,获取缩放比例,修改组件的缩放比例
onPinchGestureActionUpdate(event: GestureEvent) {
const SCALE_VALUE = this.pinchValue * event.scale;
if (SCALE_VALUE <= this.imageMeta.MAX_SCALE_VALUE && SCALE_VALUE >= this.MIN_SCALE) {
this.scaleValue = SCALE_VALUE;
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
}
}
getPinchY(pinchCenterY: number | string) {
let pinchY = pinchCenterY;
if (this.scaleValue > 1) {
if (this.imageMeta.IMAGE_WIDTH >= this.imageMeta.IMAGE_HEIGHT) {
const SCREEN_HEIGHT = px2vp(display.getDefaultDisplaySync().height);
const MIN_PINCH_Y = SCREEN_HEIGHT / 2 - this.imageMeta.IMAGE_HEIGHT / 2;
const MAX_PINCH_Y = SCREEN_HEIGHT / 2 + this.imageMeta.IMAGE_HEIGHT / 2;
const MIDDLE_PINCH_Y = SCREEN_HEIGHT / 2;
if (pinchY < MIN_PINCH_Y) {
pinchY = MIN_PINCH_Y;
}
if (pinchY > MAX_PINCH_Y) {
pinchY = MAX_PINCH_Y;
}
if (pinchY < MIDDLE_PINCH_Y && typeof this.pinchY === 'number') {
this.offsetY = (Number(pinchY) - MIDDLE_PINCH_Y) * (this.scaleValue - 1);
}
if (pinchY > MIDDLE_PINCH_Y && typeof this.pinchY === 'number') {
this.offsetY = (Number(pinchY) - MIDDLE_PINCH_Y) * (this.scaleValue - 1);
}
}
}
return pinchY;
}
// 当捏合手势结束时,计算当前的isScaling,如果缩放比例小于1,置为原效果
onPinchGestureActionEnd() {
this.pinchValue = this.scaleValue;
if (this.pinchValue < 1 && this.panOption.getDirection() === PanDirection.None) {
console.log('pinch --reset ')
this.reset();
this.panOption.setDirection(PanDirection.All);
}
}
// 当拖动手势触发时,获取偏移位置,并计算是否已到边界,不可拖出边界
onPanGestureActionUpdate(event: GestureEvent) {
if (this.scaleValue >= 1) {
this.panOption.setDirection(PanDirection.None);
return;
}
if (!event) {
return;
}
this.panOption.setDirection(PanDirection.All);
console.log('onPanGestureActionUpdate -- ')
if (this.imageMeta.PAN_DIRECTION === PanDirection.All || this.imageMeta.PAN_DIRECTION === PanDirection.Vertical ||
this.imageMeta.PAN_DIRECTION === PanDirection.Horizontal) {
const NEWOFFSET_X = this.positionX + event.offsetX;
this.offsetX = NEWOFFSET_X;
console.log('x this.offsetX=' + this.offsetX)
const NEWOFFSET_Y = this.positionY + event.offsetY;
this.offsetY = NEWOFFSET_Y;
console.log('y this.offsetY=' + this.offsetY)
}
}
// 当拖动手势结束时,保存当前偏移位置
onPanGestureActionEnd() {
if (this.scaleValue < 1) {
console.log('pan --reset ')
this.reset();
}
}
}
在HarmonyOS鸿蒙Next系统中,若想在Swiper组件内实现视频播放器的双指缩放及拖动功能,通常需要对视频播放器控件进行自定义处理,并集成手势识别逻辑。以下是实现该功能的基本思路:
-
视频播放器控件:首先,确保你使用的视频播放器控件支持缩放功能。如果内置控件不支持,可以考虑使用第三方库或自行实现。
-
手势识别:使用HarmonyOS提供的手势识别API(如GestureDetector)来监听双指缩放及拖动手势。通过重写相关回调方法,获取手势的缩放比例和拖动距离。
-
缩放与拖动逻辑:在获取到手势信息后,根据缩放比例调整视频播放器的尺寸,同时根据拖动距离更新播放器的位置。这可能需要涉及到对播放器布局参数的动态修改。
-
Swiper组件处理:确保Swiper组件能够正确传递手势事件到内部的视频播放器控件。这可能需要调整Swiper的触摸事件拦截策略。
-
测试与优化:在实现基本功能后,进行充分的测试,确保缩放与拖动操作流畅且无误。根据测试结果进行必要的优化。
如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html