HarmonyOS 是否有大图预览效果的方案?

需要实现大图预览的效果,双击放大、拖动到边缘切换下一张图片。

阅读 578
1 个回答

1、使用组合手势GestureGroup,同时绑定捏合手势PinchGesture和滑动手势PanGesture,设置组合手势识别模式为并行识别模式Parallel,并行识别组合手势中注册的手势将同时进行识别,直到所有手势识别结束。并行识别手势组合中的手势进行识别时互不影响。

2、在对图片进行双指捏合时,优先触发绑定的PinchGesture手势,对图片进行缩放操作。当滑动拖拽图片时,识别绑定的PanGesture手势,对图片进行拖拽移动。

核心代码如下:

1、绑定组合手势GestureGroup,设置为并行识别模式,添加捏合手势PinchGesture和滑动手势PanGesture。

@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();
        })
    )
  )
}

2、在捏合手势的onActionUpdate和onActionEnd回调中修改scale参数,进行图片缩放处理。

// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例
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 = this.getPinchY(event.pinchCenterY);
    if (this.scaleValue > 1) {
      this.offsetX = 0;
    }
  }
}

getPinchY(pinchCenterY: number | string) {
  let pinchY = pinchCenterY;
  if (this.scaleValue > 1) {
    // 当为横图时,在留白处放大,图片位置不居中,手动计算pinchY,并移动Y轴中心点,即offsetY
    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.scaleEnable();
  } else {
    this.scaleUnEnable();
    if (this.pinchValue < 1) {
      this.reset();
    }
  }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进