HarmonyOS 点击图片放大缩小

请问下有没有图片大图浏览的组件,可双击点击放大缩小。

HarmonyOS
8h前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
Excelsior_abit

当前并无相关组件可用于查看大图,具体实现方式可参考图库查看大图、左右切换浏览图片源码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
          }),
      )
    )
  }
}
分享
微博
QQ
微信
回复
5h前
相关问题
HarmonyOS 如何实现放大缩小的动画?
377浏览 • 1回复 待解决
Swiper轮播图带放大缩小动效实践
1238浏览 • 1回复 待解决
HarmonyOS 点击图片按钮中间没反应
658浏览 • 1回复 待解决
HarmonyOS 自定义struct缩小异常
0浏览 • 1回复 待解决
如何实现图片点击跳转?
5546浏览 • 1回复 待解决
适老化模式字体放大咨询
281浏览 • 1回复 待解决