From c50be595d44068c69e9c7b0129e81c9efab1e7be Mon Sep 17 00:00:00 2001 From: inottn Date: Sun, 5 Nov 2023 20:31:34 +0800 Subject: [PATCH] feat(ImagePreview): expose resetScale method (#12426) --- .../vant/src/image-preview/ImagePreview.tsx | 18 ++++++++-- .../src/image-preview/ImagePreviewItem.tsx | 34 ++++++++++++------- packages/vant/src/image-preview/README.md | 3 +- .../vant/src/image-preview/README.zh-CN.md | 3 +- .../vant/src/image-preview/test/index.spec.ts | 21 ++++++++++++ packages/vant/src/image-preview/types.ts | 11 ++++++ 6 files changed, 74 insertions(+), 16 deletions(-) diff --git a/packages/vant/src/image-preview/ImagePreview.tsx b/packages/vant/src/image-preview/ImagePreview.tsx index 0aa0a7d86..ae15d7996 100644 --- a/packages/vant/src/image-preview/ImagePreview.tsx +++ b/packages/vant/src/image-preview/ImagePreview.tsx @@ -38,7 +38,10 @@ import { Popup, PopupCloseIconPosition } from '../popup'; import ImagePreviewItem from './ImagePreviewItem'; // Types -import { ImagePreviewScaleEventParams } from './types'; +import { + ImagePreviewScaleEventParams, + ImagePreviewItemInstance, +} from './types'; const [name, bem] = createNamespace('image-preview'); @@ -86,6 +89,7 @@ export default defineComponent({ setup(props, { emit, slots }) { const swipeRef = ref(); + const activedPreviewItemRef = ref(); const state = reactive({ active: 0, @@ -167,6 +171,11 @@ export default defineComponent({ v-slots={{ image: slots.image, }} + ref={(item) => { + if (index === state.active) { + activedPreviewItemRef.value = item as ImagePreviewItemInstance; + } + }} src={image} show={props.show} active={state.active} @@ -206,7 +215,12 @@ export default defineComponent({ const swipeTo = (index: number, options?: SwipeToOptions) => swipeRef.value?.swipeTo(index, options); - useExpose({ swipeTo }); + useExpose({ + resetScale: () => { + activedPreviewItemRef.value?.resetScale(); + }, + swipeTo, + }); onMounted(resize); diff --git a/packages/vant/src/image-preview/ImagePreviewItem.tsx b/packages/vant/src/image-preview/ImagePreviewItem.tsx index 8ef778164..3f2f14df3 100644 --- a/packages/vant/src/image-preview/ImagePreviewItem.tsx +++ b/packages/vant/src/image-preview/ImagePreviewItem.tsx @@ -5,6 +5,7 @@ import { reactive, defineComponent, type CSSProperties, + type ExtractPropTypes, } from 'vue'; // Utils @@ -20,6 +21,7 @@ import { } from '../utils'; // Composables +import { useExpose } from '../composables/use-expose'; import { useTouch } from '../composables/use-touch'; import { raf, useEventListener, useRect } from '@vant/use'; @@ -43,19 +45,25 @@ const bem = createNamespace('image-preview')[1]; const longImageRatio = 2.6; +const imagePreviewItemProps = { + src: String, + show: Boolean, + active: Number, + minZoom: makeRequiredProp(numericProp), + maxZoom: makeRequiredProp(numericProp), + rootWidth: makeRequiredProp(Number), + rootHeight: makeRequiredProp(Number), + disableZoom: Boolean, + doubleScale: Boolean, + closeOnClickOverlay: Boolean, +}; + +export type ImagePreviewItemProps = ExtractPropTypes< + typeof imagePreviewItemProps +>; + export default defineComponent({ - props: { - src: String, - show: Boolean, - active: Number, - minZoom: makeRequiredProp(numericProp), - maxZoom: makeRequiredProp(numericProp), - rootWidth: makeRequiredProp(Number), - rootHeight: makeRequiredProp(Number), - disableZoom: Boolean, - doubleScale: Boolean, - closeOnClickOverlay: Boolean, - }, + props: imagePreviewItemProps, emits: ['scale', 'close', 'longPress'], @@ -375,6 +383,8 @@ export default defineComponent({ target: computed(() => swipeItem.value?.$el), }); + useExpose({ resetScale }); + return () => { const imageSlots = { loading: () => , diff --git a/packages/vant/src/image-preview/README.md b/packages/vant/src/image-preview/README.md index af263544c..e4c3a420e 100644 --- a/packages/vant/src/image-preview/README.md +++ b/packages/vant/src/image-preview/README.md @@ -261,7 +261,8 @@ Use [ref](https://vuejs.org/v2/api/#ref) to get ImagePreview instance and call i | Name | Description | Attribute | Return value | | --- | --- | --- | --- | -| swipeTo `2.9.0` | Swipe to target index | _index: number, options?: SwipeToOptions_ | - | +| resetScale `4.7.4` | Reset the current image's zoom ratio | - | - | +| swipeTo | Swipe to target index | _index: number, options?: SwipeToOptions_ | - | ### Types diff --git a/packages/vant/src/image-preview/README.zh-CN.md b/packages/vant/src/image-preview/README.zh-CN.md index 901e817c1..056ccc6a2 100644 --- a/packages/vant/src/image-preview/README.zh-CN.md +++ b/packages/vant/src/image-preview/README.zh-CN.md @@ -268,7 +268,8 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数: | 方法名 | 说明 | 参数 | 返回值 | | --- | --- | --- | --- | -| swipeTo `2.9.0` | 切换到指定位置 | _index: number, options?: SwipeToOptions_ | - | +| resetScale `4.7.4` | 重置当前图片的缩放比 | - | - | +| swipeTo | 切换到指定位置 | _index: number, options?: SwipeToOptions_ | - | ### 类型定义 diff --git a/packages/vant/src/image-preview/test/index.spec.ts b/packages/vant/src/image-preview/test/index.spec.ts index 04669e0f5..c6aa42bab 100644 --- a/packages/vant/src/image-preview/test/index.spec.ts +++ b/packages/vant/src/image-preview/test/index.spec.ts @@ -8,6 +8,7 @@ import { import { LONG_PRESS_START_TIME } from '../../utils'; import ImagePreview from '../ImagePreview'; import { images, triggerZoom } from './shared'; +import type { ImagePreviewInstance } from '../types'; test('should swipe to current index after calling the swipeTo method', async () => { const wrapper = mount(ImagePreview, { @@ -365,3 +366,23 @@ test('should emit long-press event after long press', async () => { index: 0, }); }); + +test('should reset scale after calling the resetScale method', async () => { + const wrapper = mount(ImagePreview, { + props: { + show: true, + images, + }, + }); + + await later(); + const image = wrapper.find('.van-image'); + + triggerZoom(image, 300, 300); + await later(); + expect(image.style.transform).toBeTruthy(); + + (wrapper.vm as ImagePreviewInstance).resetScale(); + await later(); + expect(image.style.transform).toBeFalsy(); +}); diff --git a/packages/vant/src/image-preview/types.ts b/packages/vant/src/image-preview/types.ts index 23495cedf..8d8c9e374 100644 --- a/packages/vant/src/image-preview/types.ts +++ b/packages/vant/src/image-preview/types.ts @@ -7,6 +7,7 @@ import type { Interceptor } from '../utils'; import type { SwipeToOptions } from '../swipe'; import type { PopupCloseIconPosition } from '../popup'; import type { ImagePreviewProps } from './ImagePreview'; +import type { ImagePreviewItemProps } from './ImagePreviewItem'; export type ImagePreviewOptions = { loop?: boolean; @@ -39,7 +40,17 @@ export type ImagePreviewScaleEventParams = { index: number; }; +type ImagePreviewItemExpose = { + resetScale: () => void; +}; + +export type ImagePreviewItemInstance = ComponentPublicInstance< + ImagePreviewItemProps, + ImagePreviewItemExpose +>; + export type ImagePreviewExpose = { + resetScale: () => void; swipeTo: (index: number, options?: SwipeToOptions) => void; };