Skip to content

Commit

Permalink
feat(ImagePreview): add close-on-click-image prop (#12566)
Browse files Browse the repository at this point in the history
  • Loading branch information
inottn committed Jan 13, 2024
1 parent e6dd92e commit 5603aa2
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 6 deletions.
2 changes: 2 additions & 0 deletions packages/vant/src/image-preview/ImagePreview.tsx
Expand Up @@ -73,6 +73,7 @@ export const imagePreviewProps = {
startPosition: makeNumericProp(0),
showIndicators: Boolean,
closeOnPopstate: truthProp,
closeOnClickImage: truthProp,
closeOnClickOverlay: truthProp,
closeIconPosition: makeStringProp<PopupCloseIconPosition>('top-right'),
teleport: [String, Object] as PropType<TeleportProps['to']>,
Expand Down Expand Up @@ -185,6 +186,7 @@ export default defineComponent({
rootHeight={state.rootHeight}
disableZoom={state.disableZoom}
doubleScale={props.doubleScale}
closeOnClickImage={props.closeOnClickImage}
closeOnClickOverlay={props.closeOnClickOverlay}
onScale={emitScale}
onClose={emitClose}
Expand Down
7 changes: 6 additions & 1 deletion packages/vant/src/image-preview/ImagePreviewItem.tsx
Expand Up @@ -54,6 +54,7 @@ const imagePreviewItemProps = {
rootHeight: makeRequiredProp(Number),
disableZoom: Boolean,
doubleScale: Boolean,
closeOnClickImage: Boolean,
closeOnClickOverlay: Boolean,
};

Expand Down Expand Up @@ -251,8 +252,12 @@ export default defineComponent({
};

const checkClose = (event: TouchEvent) => {
const isClickOverlay = event.target === swipeItem.value?.$el;
const swipeItemEl: HTMLElement = swipeItem.value?.$el;
const imageEl = swipeItemEl.firstElementChild;
const isClickOverlay = event.target === swipeItemEl;
const isClickImage = imageEl?.contains(event.target as HTMLElement);

if (!props.closeOnClickImage && isClickImage) return;
if (!props.closeOnClickOverlay && isClickOverlay) return;

emit('close');
Expand Down
10 changes: 8 additions & 2 deletions packages/vant/src/image-preview/README.md
Expand Up @@ -150,10 +150,14 @@ export default {

### Use image slot

When using ImagePreview component, you can custom the image through the `image` slot, such as render a video content.
When using ImagePreview component, you can custom the image through the `image` slot, such as render a video content. In this example, you can also set `close-on-click-image` prop to `false`, so that the preview won't be accidentally closed when you click on the video.

```html
<van-image-preview v-model:show="show" :images="images">
<van-image-preview
v-model:show="show"
:images="images"
:close-on-click-image="false"
>
<template #image="{ src }">
<video style="width: 100%;" controls>
<source :src="src" />
Expand Down Expand Up @@ -206,6 +210,7 @@ Vant exports following ImagePreview utility functions:
| onScale | Emitted when scaling current image | _Function_ | - |
| closeOnPopstate | Whether to close when popstate | _boolean_ | `true` |
| doubleScale `v4.7.2` | Whether to enable double tap zoom gesture. When disabled, the image preview will be closed immediately upon clicking | _boolean_ | `true` |
| closeOnClickImage `v4.8.3` | Whether to close when image is clicked | _boolean_ | `true` |
| closeOnClickOverlay `v4.6.4` | Whether to close when overlay is clicked | _boolean_ | `true` |
| beforeClose | Callback function before close | _(action) => boolean \| Promise_ | - |
| className | Custom className | _string \| Array \| object_ | - |
Expand Down Expand Up @@ -233,6 +238,7 @@ Vant exports following ImagePreview utility functions:
| double-scale | Whether to enable double tap zoom gesture. When disabled, the image preview will be closed immediately upon clicking | _boolean_ | `true` |
| before-close | Callback function before close | _(action: number) => boolean \| Promise\<boolean\>_ | - |
| close-on-popstate | Whether to close when popstate | _boolean_ | `true` |
| close-on-click-image `v4.8.3` | Whether to close when image is clicked | _boolean_ | `true` |
| close-on-click-overlay `v4.6.4` | Whether to close when overlay is clicked | _boolean_ | `true` |
| class-name | Custom className (apply to Popup in image preview) | _string \| Array \| object_ | - |
| max-zoom | Max zoom | _number \| string_ | `3` |
Expand Down
10 changes: 8 additions & 2 deletions packages/vant/src/image-preview/README.zh-CN.md
Expand Up @@ -151,10 +151,14 @@ export default {

### 使用 image 插槽

当以组件调用的方式使用 ImagePreview 时,可以通过 `image` 插槽来插入自定义的内容,比如展示一个视频内容。
当以组件调用的方式使用 ImagePreview 时,可以通过 `image` 插槽来插入自定义的内容,比如展示一个视频内容。在这个例子中,你可以将 `close-on-click-image` 属性设置为 `false`,这样当你点击视频时就不会意外关闭预览了。

```html
<van-image-preview v-model:show="show" :images="images">
<van-image-preview
v-model:show="show"
:images="images"
:close-on-click-image="false"
>
<template #image="{ src }">
<video style="width: 100%;" controls>
<source :src="src" />
Expand Down Expand Up @@ -210,6 +214,7 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
| onScale | 缩放图片时的回调函数,回调参数为当前索引和当前缩放值组成的对象 | _Function_ | - |
| beforeClose | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
| closeOnPopstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
| closeOnClickImage `v4.8.3` | 是否在点击图片后关闭图片预览 | _boolean_ | `true` |
| closeOnClickOverlay `v4.6.4` | 是否在点击遮罩层后关闭图片预览 | _boolean_ | `true` |
| className | 自定义类名 (应用在图片预览的弹出层) | _string \| Array \| object_ | - |
| maxZoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
Expand Down Expand Up @@ -238,6 +243,7 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
| double-scale `v4.7.2` | 是否启用双击缩放手势,禁用后,点击时会立即关闭图片预览 | _boolean_ | `true` |
| before-close | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
| close-on-popstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
| close-on-click-image `v4.8.3` | 是否在点击图片后关闭图片预览 | _boolean_ | `true` |
| close-on-click-overlay `v4.6.4` | 是否在点击遮罩层后关闭图片预览 | _boolean_ | `true` |
| class-name | 自定义类名 | _string \| Array \| object_ | - |
| max-zoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
Expand Down
6 changes: 5 additions & 1 deletion packages/vant/src/image-preview/demo/index.vue
Expand Up @@ -134,7 +134,11 @@ const showFunctionCall = (options: Partial<ImagePreviewOptions> = {}) => {
:title="t('useImageSlot')"
@click="showComponentCallSlot"
/>
<van-image-preview v-model:show="showSlot" :images="imagesSlot">
<van-image-preview
v-model:show="showSlot"
:images="imagesSlot"
:close-on-click-image="false"
>
<template #image="{ src }">
<video style="width: 100%" controls>
<source :src="src" />
Expand Down
39 changes: 39 additions & 0 deletions packages/vant/src/image-preview/test/index.spec.ts
Expand Up @@ -181,6 +181,25 @@ test('before close prop', async () => {
expect(wrapper.emitted('close')![0]).toBeTruthy();
});

test('should close when image is clicked', async () => {
const wrapper = mount(ImagePreview, {
props: {
images,
show: true,
'onUpdate:show': (show) => {
wrapper.setProps({ show });
},
},
});

await later();
const image = wrapper.find('.van-image');

await triggerDrag(image, 0, 0);
await later(300);
expect(wrapper.emitted('close')).toBeTruthy();
});

test('should close when overlay is clicked', async () => {
const wrapper = mount(ImagePreview, {
props: {
Expand All @@ -199,6 +218,26 @@ test('should close when overlay is clicked', async () => {
expect(wrapper.emitted('close')).toBeTruthy();
});

test('should not close when image is clicked and closeOnClickImage is false', async () => {
const wrapper = mount(ImagePreview, {
props: {
images,
show: true,
closeOnClickImage: false,
'onUpdate:show': (show) => {
wrapper.setProps({ show });
},
},
});

await later();
const image = wrapper.find('.van-image');

triggerDrag(image, 0, 0);
await later(300);
expect(wrapper.emitted('close')).toBeFalsy();
});

test('should not close when overlay is clicked and closeOnClickOverlay is false', async () => {
const wrapper = mount(ImagePreview, {
props: {
Expand Down
1 change: 1 addition & 0 deletions packages/vant/src/image-preview/types.ts
Expand Up @@ -29,6 +29,7 @@ export type ImagePreviewOptions = {
showIndicators?: boolean;
closeOnPopstate?: boolean;
closeIconPosition?: PopupCloseIconPosition;
closeOnClickImage?: boolean;
closeOnClickOverlay?: boolean;
onClose?(): void;
onScale?(args: { scale: number; index: number }): void;
Expand Down

0 comments on commit 5603aa2

Please sign in to comment.