HarmonyOS 关于图片浏览大图

有大图实现方式么(可以缩小,放大,放大后能左右移动视图区域,根据手指定点进行放大)

HarmonyOS
1天前
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
zxjiu

浏览大图可以参考下面的demo:

//page页面:
import router from '@ohos.router'
@Entry
@Component
struct SharedTransitionExample {
  @State active: boolean = false
  @State imageNames: Resource[] = [$r('app.media.ic_product01'), $r('app.media.ic_product02'), $r('app.media.ic_product03')]
  @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%)
  }
}
//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
        }
      })
  }
}
@Component
struct ImageComponent {
  private image: Resource = $r('app.media.startIcon')
  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
微信
回复
1天前
相关问题
HarmonyOS 图片浏览页面示例
15浏览 • 1回复 待解决
如何实现图片预览效果
2159浏览 • 1回复 待解决
HarmonyOS http下载失败
75浏览 • 1回复 待解决
HarmonyOS app预览手势问题
31浏览 • 1回复 待解决
HarmonyOS 关于柱状,环形的绘制
34浏览 • 1回复 待解决
HarmonyOS 图片问题
306浏览 • 1回复 待解决
关于mysql存文本字段的问题
4155浏览 • 1回复 待解决
HarmonyOS 图片两倍? 三倍
4浏览 • 1回复 待解决
HarmonyOS 图片浏览和裁剪的视图组件
82浏览 • 1回复 待解决
HarmonyOS 关于怎么还原设计问题?
288浏览 • 1回复 待解决
HarmonyOS 图片文件夹获取封面coverUri
304浏览 • 1回复 待解决
HarmonyOS 关于图片裁切问题
39浏览 • 1回复 待解决
HarmonyOS 整数如何处理
512浏览 • 1回复 待解决