mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(ImagePreview): add closeOnClickOverlay option (#12153)
This commit is contained in:
parent
afeef70429
commit
d988df7ba5
@ -69,6 +69,7 @@ export const imagePreviewProps = {
|
|||||||
startPosition: makeNumericProp(0),
|
startPosition: makeNumericProp(0),
|
||||||
showIndicators: Boolean,
|
showIndicators: Boolean,
|
||||||
closeOnPopstate: truthProp,
|
closeOnPopstate: truthProp,
|
||||||
|
closeOnClickOverlay: truthProp,
|
||||||
closeIconPosition: makeStringProp<PopupCloseIconPosition>('top-right'),
|
closeIconPosition: makeStringProp<PopupCloseIconPosition>('top-right'),
|
||||||
teleport: [String, Object] as PropType<TeleportProps['to']>,
|
teleport: [String, Object] as PropType<TeleportProps['to']>,
|
||||||
};
|
};
|
||||||
@ -173,6 +174,7 @@ export default defineComponent({
|
|||||||
rootWidth={state.rootWidth}
|
rootWidth={state.rootWidth}
|
||||||
rootHeight={state.rootHeight}
|
rootHeight={state.rootHeight}
|
||||||
disableZoom={state.disableZoom}
|
disableZoom={state.disableZoom}
|
||||||
|
closeOnClickOverlay={props.closeOnClickOverlay}
|
||||||
onScale={emitScale}
|
onScale={emitScale}
|
||||||
onClose={emitClose}
|
onClose={emitClose}
|
||||||
onLongPress={() => emit('longPress', { index })}
|
onLongPress={() => emit('longPress', { index })}
|
||||||
|
@ -53,6 +53,7 @@ export default defineComponent({
|
|||||||
rootWidth: makeRequiredProp(Number),
|
rootWidth: makeRequiredProp(Number),
|
||||||
rootHeight: makeRequiredProp(Number),
|
rootHeight: makeRequiredProp(Number),
|
||||||
disableZoom: Boolean,
|
disableZoom: Boolean,
|
||||||
|
closeOnClickOverlay: Boolean,
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['scale', 'close', 'longPress'],
|
emits: ['scale', 'close', 'longPress'],
|
||||||
@ -241,7 +242,7 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkTap = () => {
|
const checkTap = (event: TouchEvent) => {
|
||||||
if (fingerNum > 1) {
|
if (fingerNum > 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -260,6 +261,12 @@ export default defineComponent({
|
|||||||
doubleTapTimer = null;
|
doubleTapTimer = null;
|
||||||
toggleScale();
|
toggleScale();
|
||||||
} else {
|
} else {
|
||||||
|
if (
|
||||||
|
!props.closeOnClickOverlay &&
|
||||||
|
event.target === swipeItem.value?.$el
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
doubleTapTimer = setTimeout(() => {
|
doubleTapTimer = setTimeout(() => {
|
||||||
emit('close');
|
emit('close');
|
||||||
doubleTapTimer = null;
|
doubleTapTimer = null;
|
||||||
@ -314,7 +321,7 @@ export default defineComponent({
|
|||||||
// eliminate tap delay on safari
|
// eliminate tap delay on safari
|
||||||
preventDefault(event, stopPropagation);
|
preventDefault(event, stopPropagation);
|
||||||
|
|
||||||
checkTap();
|
checkTap(event);
|
||||||
touch.reset();
|
touch.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ Vant exports following ImagePreview utility functions:
|
|||||||
| onChange | Emitted when current image changed | _Function_ | - |
|
| onChange | Emitted when current image changed | _Function_ | - |
|
||||||
| onScale | Emitted when scaling current image | _Function_ | - |
|
| onScale | Emitted when scaling current image | _Function_ | - |
|
||||||
| closeOnPopstate | Whether to close when popstate | _boolean_ | `true` |
|
| closeOnPopstate | Whether to close when popstate | _boolean_ | `true` |
|
||||||
|
| closeOnClickOverlay `v4.6.4` | Whether to close when overlay is clicked | _boolean_ | `true` |
|
||||||
| beforeClose | Callback function before close | _(action) => boolean \| Promise_ | - |
|
| beforeClose | Callback function before close | _(action) => boolean \| Promise_ | - |
|
||||||
| className | Custom className | _string \| Array \| object_ | - |
|
| className | Custom className | _string \| Array \| object_ | - |
|
||||||
| maxZoom | Max zoom | _number \| string_ | `3` |
|
| maxZoom | Max zoom | _number \| string_ | `3` |
|
||||||
@ -220,6 +221,7 @@ Vant exports following ImagePreview utility functions:
|
|||||||
| loop | Whether to enable loop | _boolean_ | `true` |
|
| loop | Whether to enable loop | _boolean_ | `true` |
|
||||||
| before-close | Callback function before close | _(action: number) => boolean \| Promise\<boolean\>_ | - |
|
| before-close | Callback function before close | _(action: number) => boolean \| Promise\<boolean\>_ | - |
|
||||||
| close-on-popstate | Whether to close when popstate | _boolean_ | `true` |
|
| close-on-popstate | Whether to close when popstate | _boolean_ | `true` |
|
||||||
|
| close-on-click-overlay `v4.6.4` | Whether to close when overlay is clicked | _boolean_ | `true` |
|
||||||
| class-name | Custom className | _string \| Array \| object_ | - |
|
| class-name | Custom className | _string \| Array \| object_ | - |
|
||||||
| max-zoom | Max zoom | _number \| string_ | `3` |
|
| max-zoom | Max zoom | _number \| string_ | `3` |
|
||||||
| min-zoom | Min zoom | _number \| string_ | `1/3` |
|
| min-zoom | Min zoom | _number \| string_ | `1/3` |
|
||||||
|
@ -209,6 +209,7 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
|
|||||||
| onScale | 缩放图片时的回调函数,回调参数为当前索引和当前缩放值组成的对象 | _Function_ | - |
|
| onScale | 缩放图片时的回调函数,回调参数为当前索引和当前缩放值组成的对象 | _Function_ | - |
|
||||||
| beforeClose | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
|
| beforeClose | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
|
||||||
| closeOnPopstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
|
| closeOnPopstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
|
||||||
|
| closeOnClickOverlay `v4.6.4` | 是否在点击遮罩层后关闭图片预览 | _boolean_ | `true` |
|
||||||
| className | 自定义类名 | _string \| Array \| object_ | - |
|
| className | 自定义类名 | _string \| Array \| object_ | - |
|
||||||
| maxZoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
|
| maxZoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
|
||||||
| minZoom | 手势缩放时,最小缩放比例 | _number \| string_ | `1/3` |
|
| minZoom | 手势缩放时,最小缩放比例 | _number \| string_ | `1/3` |
|
||||||
@ -235,6 +236,7 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
|
|||||||
| loop | 是否开启循环播放 | _boolean_ | `true` |
|
| loop | 是否开启循环播放 | _boolean_ | `true` |
|
||||||
| before-close | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
|
| before-close | 关闭前的回调函数,返回 `false` 可阻止关闭,支持返回 Promise | _(active: number) => boolean \| Promise\<boolean\>_ | - |
|
||||||
| close-on-popstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
|
| close-on-popstate | 是否在页面回退时自动关闭 | _boolean_ | `true` |
|
||||||
|
| close-on-click-overlay `v4.6.4` | 是否在点击遮罩层后关闭图片预览 | _boolean_ | `true` |
|
||||||
| class-name | 自定义类名 | _string \| Array \| object_ | - |
|
| class-name | 自定义类名 | _string \| Array \| object_ | - |
|
||||||
| max-zoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
|
| max-zoom | 手势缩放时,最大缩放比例 | _number \| string_ | `3` |
|
||||||
| min-zoom | 手势缩放时,最小缩放比例 | _number \| string_ | `1/3` |
|
| min-zoom | 手势缩放时,最小缩放比例 | _number \| string_ | `1/3` |
|
||||||
|
@ -26,6 +26,7 @@ const defaultConfig: ImagePreviewOptions = {
|
|||||||
swipeDuration: 300,
|
swipeDuration: 300,
|
||||||
showIndicators: false,
|
showIndicators: false,
|
||||||
closeOnPopstate: true,
|
closeOnPopstate: true,
|
||||||
|
closeOnClickOverlay: true,
|
||||||
closeIconPosition: 'top-right',
|
closeIconPosition: 'top-right',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,11 +6,11 @@ import {
|
|||||||
trigger,
|
trigger,
|
||||||
} from '../../../test';
|
} from '../../../test';
|
||||||
import { LONG_PRESS_START_TIME } from '../../utils';
|
import { LONG_PRESS_START_TIME } from '../../utils';
|
||||||
import ImagePreviewComponent from '../ImagePreview';
|
import ImagePreview from '../ImagePreview';
|
||||||
import { images, triggerZoom } from './shared';
|
import { images, triggerZoom } from './shared';
|
||||||
|
|
||||||
test('should swipe to current index after calling the swipeTo method', async () => {
|
test('should swipe to current index after calling the swipeTo method', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
images,
|
images,
|
||||||
@ -26,7 +26,7 @@ test('should swipe to current index after calling the swipeTo method', async ()
|
|||||||
|
|
||||||
test('should allow to use the teleport prop', () => {
|
test('should allow to use the teleport prop', () => {
|
||||||
const root = document.createElement('div');
|
const root = document.createElement('div');
|
||||||
mount(ImagePreviewComponent, {
|
mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
teleport: root,
|
teleport: root,
|
||||||
@ -37,7 +37,7 @@ test('should allow to use the teleport prop', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render cover slot correctly', () => {
|
test('should render cover slot correctly', () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
@ -50,7 +50,7 @@ test('should render cover slot correctly', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render index slot correctly', () => {
|
test('should render index slot correctly', () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
@ -63,7 +63,7 @@ test('should render index slot correctly', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render close icon when using closeable prop', () => {
|
test('should render close icon when using closeable prop', () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
images,
|
images,
|
||||||
@ -76,7 +76,7 @@ test('should render close icon when using closeable prop', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should change close icon when using close-icon prop', () => {
|
test('should change close icon when using close-icon prop', () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
closeable: true,
|
closeable: true,
|
||||||
@ -90,7 +90,7 @@ test('should change close icon when using close-icon prop', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should change close icon position when using close-icon-position prop', () => {
|
test('should change close icon position when using close-icon-position prop', () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
closeable: true,
|
closeable: true,
|
||||||
@ -104,7 +104,7 @@ test('should change close icon position when using close-icon-position prop', ()
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should hide index when show-index prop is false', async () => {
|
test('should hide index when show-index prop is false', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
@ -116,7 +116,7 @@ test('should hide index when show-index prop is false', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should hide ImagePreview after popstate', async () => {
|
test('should hide ImagePreview after popstate', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
@ -128,7 +128,7 @@ test('should hide ImagePreview after popstate', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should not hide ImagePreview after popstate when close-on-popstate is false', async () => {
|
test('should not hide ImagePreview after popstate when close-on-popstate is false', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
@ -141,7 +141,7 @@ test('should not hide ImagePreview after popstate when close-on-popstate is fals
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('render image', async () => {
|
test('render image', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: { images, show: true },
|
props: { images, show: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ test('render image', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('before close prop', async () => {
|
test('before close prop', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
@ -180,9 +180,46 @@ test('before close prop', async () => {
|
|||||||
expect(wrapper.emitted('close')![0]).toBeTruthy();
|
expect(wrapper.emitted('close')![0]).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should close when overlay is clicked', async () => {
|
||||||
|
const wrapper = mount(ImagePreview, {
|
||||||
|
props: {
|
||||||
|
images,
|
||||||
|
show: true,
|
||||||
|
'onUpdate:show': (show) => {
|
||||||
|
wrapper.setProps({ show });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const swipe = wrapper.find('.van-swipe-item');
|
||||||
|
|
||||||
|
await triggerDrag(swipe, 0, 0);
|
||||||
|
await later(300);
|
||||||
|
expect(wrapper.emitted('close')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not close when overlay is clicked and closeOnClickOverlay is false', async () => {
|
||||||
|
const wrapper = mount(ImagePreview, {
|
||||||
|
props: {
|
||||||
|
images,
|
||||||
|
show: true,
|
||||||
|
closeOnClickOverlay: false,
|
||||||
|
'onUpdate:show': (show) => {
|
||||||
|
wrapper.setProps({ show });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const swipe = wrapper.find('.van-swipe-item');
|
||||||
|
|
||||||
|
triggerDrag(swipe, 0, 0);
|
||||||
|
await later(300);
|
||||||
|
expect(wrapper.emitted('close')).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
test('double click', async () => {
|
test('double click', async () => {
|
||||||
const onScale = jest.fn();
|
const onScale = jest.fn();
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
@ -211,7 +248,7 @@ test('double click', async () => {
|
|||||||
test('zoom in and drag image to move', async () => {
|
test('zoom in and drag image to move', async () => {
|
||||||
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
||||||
|
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: { images, show: true },
|
props: { images, show: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -240,7 +277,7 @@ test('zoom out', async () => {
|
|||||||
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
const restore = mockGetBoundingClientRect({ width: 100, height: 100 });
|
||||||
|
|
||||||
const onScale = jest.fn();
|
const onScale = jest.fn();
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
@ -258,7 +295,7 @@ test('zoom out', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render image slot correctly', async () => {
|
test('should render image slot correctly', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
images,
|
images,
|
||||||
@ -274,7 +311,7 @@ test('should render image slot correctly', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('should render image slot correctly 2', async () => {
|
test('should render image slot correctly 2', async () => {
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
show: true,
|
show: true,
|
||||||
images,
|
images,
|
||||||
@ -292,7 +329,7 @@ test('should render image slot correctly 2', async () => {
|
|||||||
|
|
||||||
test('should emit long-press event after long press', async () => {
|
test('should emit long-press event after long press', async () => {
|
||||||
const onLongPress = jest.fn();
|
const onLongPress = jest.fn();
|
||||||
const wrapper = mount(ImagePreviewComponent, {
|
const wrapper = mount(ImagePreview, {
|
||||||
props: {
|
props: {
|
||||||
images,
|
images,
|
||||||
show: true,
|
show: true,
|
||||||
|
@ -27,6 +27,7 @@ export type ImagePreviewOptions = {
|
|||||||
showIndicators?: boolean;
|
showIndicators?: boolean;
|
||||||
closeOnPopstate?: boolean;
|
closeOnPopstate?: boolean;
|
||||||
closeIconPosition?: PopupCloseIconPosition;
|
closeIconPosition?: PopupCloseIconPosition;
|
||||||
|
closeOnClickOverlay?: boolean;
|
||||||
onClose?(): void;
|
onClose?(): void;
|
||||||
onScale?(args: { scale: number; index: number }): void;
|
onScale?(args: { scale: number; index: number }): void;
|
||||||
onChange?(index: number): void;
|
onChange?(index: number): void;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user