在HarmonyOS NEXT开发中点击图片放大缩小?

在HarmonyOS NEXT开发中点击图片放大缩小?请问下有没有图片大图浏览的组件,可双击点击放大缩小。

阅读 1k
1 个回答

当前并无相关组件可用于查看大图,具体实现方式可参考图库查看大图、左右切换浏览图片源码https://gitee.com/openharmony/applications_photos/tree/master,或者参考如下代码:
1.Page页面:

// xxx.ets 
import router from '@ohos.router' 
 
@Entry 
@Component 
struct SharedTransitionExample { 
  @State active: boolean = false 
  @State imageNames: Resource[] = [$r('app.media.image1'), $r('app.media.image2'), $r('app.media.image3')] 
  @StorageLink('currentIndex') currentIndex: number = 0 
 
  build() { 
    Row() { 
      ForEach(this.imageNames, (res: Resource, index: number) => { 
        Column() { 
          Image(res) 
            .width('100%') 
            .height('100%') 
            .objectFit(ImageFit.Contain) // 在组件上绑定缩放比例,可以通过修改缩放比例来实现组件的缩小或者放大 
        } 
        .width(100) 
        .height(100) 
        .clip(true) 
        .sharedTransition('sharedImage' + res.id, { 
          duration: 200, 
          curve: Curve.Linear, 
          zIndex: this.currentIndex === index ? 10 : -10 
        }) 
        .onClick(() => { 
          this.currentIndex = index 
          router.pushUrl({ url: 'pages/Index', params: { 
            data: this.imageNames, 
          } }) 
        }) 
      }) 
 
    }.width('100%') 
    .height('100%') 
  } 
 
  pageTransition() { 
    PageTransitionEnter({ duration: 0, curve: Curve.Linear }) 
      .onEnter((type?: RouteType, progress?: number) => { 
 
      }) // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0% -- 100%) 
    PageTransitionExit({ duration: 0, curve: Curve.Ease }) 
      .onExit((type?: RouteType, progress?: number) => { 
 
      }) // 退场过程中会逐帧触发onExit回调,入参为动效的归一化进度(0% -- 100%) 
  } 
} 
//2.Index页面 
import window from '@ohos.window'; 
import router from '@ohos.router'; 
 
interface Data { 
  data: Resource[]; 
} 
 
enum Direction { 
  None, 
  Left, 
  Right, 
} 
 
@Entry 
@Component 
struct Index { 
  private swiperController: SwiperController = new SwiperController(); 
  @State imageNames: Resource[] = [] 
  @StorageLink('currentIndex') currentIndex: number = 0 
  @State screenWidth: number = 0; 
  @State op: number = 0 
 
  aboutToAppear() { 
    const data = (router.getParams() as Data) 
    this.imageNames = data.data 
    window.getLastWindow(getContext(this)).then(currentWindow => { 
 
      let property = currentWindow.getWindowProperties(); 
      this.screenWidth = property.windowRect.width; 
    }) 
  } 
 
  build() { 
    Stack({ alignContent: Alignment.Center }) { 
      Swiper(this.swiperController) { 
        ForEach(this.imageNames, (name: Resource, index: number) => { 
          Column() { 
            ImageComponent({ 
              image: name, 
              viewWidth: this.screenWidth, 
              isCurrent: this.currentIndex === index, 
              onNeedGoNext: (dire: Direction) => { 
                if (dire === Direction.Right) { 
                  this.swiperController.showNext() 
                } else if (dire === Direction.Left) { 
                  this.swiperController.showPrevious() 
                } 
              } 
            }).zIndex(index == this.currentIndex ? 2 : 1) 
          }.width('100%') 
          .height('100%') 
          .justifyContent(FlexAlign.Center) 
        }) 
      } 
      .index(this.currentIndex) 
      .indicator(false) 
      .disableSwipe(true) 
      .itemSpace(10) 
      .onChange((index: number) => { 
        this.currentIndex = index 
      }) 
    }.width('100%').height('100%') 
    .backgroundColor(`rgba(0,0,0,${this.op})`) 
  } 
 
  pageTransition() { 
PageTransitionEnter({ duration: 200, curve: Curve.Linear }) 
.onEnter((type?: RouteType, progress?: number) => { 
if (progress) { 
this.op = progress 
} 
 
}) // 进场过程中会逐帧触发onEnter回调,入参为动效的归一化进度(0% -- 100 
@Component 
struct ImageComponent { 
private image: Resource = $r('app.media.icon') 
private preGeometryScale: number = 1 
@State geometryScale: number = 1 
private preOffsetX: number = 0 
private preOffsetY: number = 0 
@State geometryOffsetX: number = 0 
@State geometryOffsetY: number = 0 
@State imageWidth: number = 0 
@State imageHeight: number = 0 
@Prop viewWidth: number = 0 
@Prop isCurrent: boolean = false 
private dire: Direction = Direction.None 
private goNext: boolean = true 
private pinching: boolean = false 
private onNeedGoNext: (dire: Direction) => void = () => { 
} 
 
  reset(): Promise<void> | undefined { 
    this.preGeometryScale = 1 
    this.preOffsetX = 0 
    this.preOffsetY = 0 
    this.dire = Direction.None 
    this.goNext = true 
    if (this.geometryScale === 1) return 
    return new Promise<void>(res => { 
      animateTo({ duration: 200, onFinish: res }, () => { 
        this.geometryScale = 1 
        this.geometryOffsetX = 0 
        this.geometryOffsetY = 0 
      }) 
    }) 
  } 
 
  build() { 
    Column() { 
      Image(this.image) 
        .onComplete((e) => { 
          this.imageWidth = (e?.width || 0) 
          this.imageHeight = (e?.height || 0) 
        }) 
        .objectFit(ImageFit.Cover) 
        .width(this.imageWidth + 'px') 
        .height(this.imageHeight + 'px') 
        .scale({ 
          x: this.geometryScale, 
          y: this.geometryScale 
        }) 
        .offset({ 
          x: this.geometryOffsetX, 
          y: this.geometryOffsetY 
        }) 
        .focusable(true) 
        .objectFit(ImageFit.Cover) 
        .autoResize(false) 
        .sharedTransition('sharedImage' + this.image.id, { 
          duration: 200, 
          curve: Curve.Linear, 
          zIndex: this.isCurrent ? 10 : -10 
        }) 
    } 
    .clip(true) 
    .width('100%') 
    .height('100%') 
    .justifyContent(FlexAlign.Center) 
    .hitTestBehavior(HitTestMode.Default) 
    .parallelGesture( // 在组件上绑定二指触发的捏合手势 
      GestureGroup(GestureMode.Parallel, 
        PinchGesture({ fingers: 2 }) 
          .onActionStart((event: GestureEvent) => { 
            this.pinching = true 
            this.goNext = false 
          })// 当捏合手势触发时,可以通过回调函数获取缩放比例,从而修改组件的缩放比例 
          .onActionUpdate((event: GestureEvent) => { 
            const s = this.preGeometryScale * event.scale; 
            this.geometryScale = Math.max(0.6, Math.min(2, s)) 
          }) 
          .onActionEnd(async () => { 
            this.preGeometryScale = this.geometryScale 
            if (this.preGeometryScale < 1) { 
              await this.reset() 
            } 
            this.pinching = false 
          }), 
        PanGesture() 
          .onActionStart((event?: GestureEvent) => { 
          }) 
          .onActionUpdate((event?: GestureEvent) => { 
            let offsetX = this.preOffsetX + (event?.offsetX || 0) 
            let offsetY = this.preOffsetY + (event?.offsetY || 0) 
            if (((this.imageWidth * this.geometryScale - this.viewWidth) / 2 - Math.abs(vp2px(offsetX))) <= 0) { 
              if (!this.pinching) { 
                this.dire = offsetX < 0 ? Direction.Right : Direction.Left 
              } 
              return; 
            } 
            this.goNext = false 
            this.geometryOffsetX = offsetX 
            this.geometryOffsetY = offsetY 
          }) 
          .onActionEnd((event?: GestureEvent) => { 
            if ((this.dire !== Direction.None)) { 
              if (this.goNext) { 
                this.onNeedGoNext(this.dire) 
                this.reset() 
              } 
              this.goNext = true 
            } 
            this.preOffsetX = this.geometryOffsetX 
            this.preOffsetY = this.geometryOffsetY 
          }), 
      ) 
    ) 
  } 
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题