mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
feat(ImagePreview): add long-press event (#11252)
* feat(ImagePreview): add long-press event * chore: upd * chore: upd * chore: upd
This commit is contained in:
parent
839bcd8928
commit
093db7b37e
@ -77,7 +77,7 @@ export default defineComponent({
|
||||
|
||||
props: imagePreviewProps,
|
||||
|
||||
emits: ['scale', 'close', 'closed', 'change', 'update:show'],
|
||||
emits: ['scale', 'close', 'closed', 'change', 'longPress', 'update:show'],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
const swipeRef = ref<SwipeInstance>();
|
||||
@ -146,7 +146,7 @@ export default defineComponent({
|
||||
indicatorColor="white"
|
||||
onChange={setActive}
|
||||
>
|
||||
{props.images.map((image) => (
|
||||
{props.images.map((image, index) => (
|
||||
<ImagePreviewItem
|
||||
src={image}
|
||||
show={props.show}
|
||||
@ -157,6 +157,7 @@ export default defineComponent({
|
||||
rootHeight={state.rootHeight}
|
||||
onScale={emitScale}
|
||||
onClose={emitClose}
|
||||
onLongPress={() => emit('longPress', { index })}
|
||||
v-slots={{
|
||||
image: slots.image,
|
||||
}}
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
preventDefault,
|
||||
createNamespace,
|
||||
makeRequiredProp,
|
||||
LONG_PRESS_START_TIME,
|
||||
type ComponentInstance,
|
||||
} from '../utils';
|
||||
|
||||
@ -45,7 +46,7 @@ export default defineComponent({
|
||||
rootHeight: makeRequiredProp(Number),
|
||||
},
|
||||
|
||||
emits: ['scale', 'close'],
|
||||
emits: ['scale', 'close', 'longPress'],
|
||||
|
||||
setup(props, { emit, slots }) {
|
||||
const state = reactive({
|
||||
@ -200,20 +201,23 @@ export default defineComponent({
|
||||
const TAP_TIME = 250;
|
||||
const TAP_OFFSET = 5;
|
||||
|
||||
if (
|
||||
offsetX.value < TAP_OFFSET &&
|
||||
offsetY.value < TAP_OFFSET &&
|
||||
deltaTime < TAP_TIME
|
||||
) {
|
||||
if (doubleTapTimer) {
|
||||
clearTimeout(doubleTapTimer);
|
||||
doubleTapTimer = null;
|
||||
toggleScale();
|
||||
} else {
|
||||
doubleTapTimer = setTimeout(() => {
|
||||
emit('close');
|
||||
if (offsetX.value < TAP_OFFSET && offsetY.value < TAP_OFFSET) {
|
||||
// tap or double tap
|
||||
if (deltaTime < TAP_TIME) {
|
||||
if (doubleTapTimer) {
|
||||
clearTimeout(doubleTapTimer);
|
||||
doubleTapTimer = null;
|
||||
}, TAP_TIME);
|
||||
toggleScale();
|
||||
} else {
|
||||
doubleTapTimer = setTimeout(() => {
|
||||
emit('close');
|
||||
doubleTapTimer = null;
|
||||
}, TAP_TIME);
|
||||
}
|
||||
}
|
||||
// long press
|
||||
else if (deltaTime > LONG_PRESS_START_TIME) {
|
||||
emit('longPress');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -235,11 +235,11 @@ Vant exports following ImagePreview utility functions:
|
||||
|
||||
| Event | Description | Arguments |
|
||||
| --- | --- | --- |
|
||||
| close | Emitted when closing ImagePreview | _value: { index, url }_ |
|
||||
| close | Emitted when closing ImagePreview | _{ index: number, url: string }_ |
|
||||
| closed | Emitted when ImagePreview is closed | - |
|
||||
| change | Emitted when current image changed | _index: number_ |
|
||||
| scale | Emitted when scaling current image | _value: ImagePreviewScaleEventParams_ |
|
||||
| scale | Emitted when scaling current image | _value: ImagePreviewScaleEventParams_ |
|
||||
| scale | Emitted when scaling current image | _{ index: number, scale: number }_ |
|
||||
| long-press | Emitted when long press current image | _{ index: number }_ |
|
||||
|
||||
### Methods
|
||||
|
||||
|
@ -250,12 +250,13 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
|
||||
|
||||
通过组件调用 `ImagePreview` 时,支持以下事件:
|
||||
|
||||
| 事件 | 说明 | 回调参数 |
|
||||
| --- | --- | --- |
|
||||
| close | 关闭时触发 | { index: 索引, url: 图片链接 } |
|
||||
| closed | 关闭且且动画结束后触发 | - |
|
||||
| change | 切换当前图片时触发 | index: 当前图片的索引 |
|
||||
| scale | 缩放当前图片时触发 | { index: 当前图片的索引, scale: 当前缩放的值 } |
|
||||
| 事件 | 说明 | 回调参数 |
|
||||
| ---------- | ---------------------- | ---------------------------------- |
|
||||
| close | 关闭时触发 | _{ index: number, url: string }_ |
|
||||
| closed | 关闭且且动画结束后触发 | - |
|
||||
| change | 切换当前图片时触发 | _index: number_ |
|
||||
| scale | 缩放当前图片时触发 | _{ index: number, scale: number }_ |
|
||||
| long-press | 长按当前图片时触发 | _{ index: number }_ |
|
||||
|
||||
### 方法
|
||||
|
||||
|
@ -3,7 +3,9 @@ import {
|
||||
later,
|
||||
triggerDrag,
|
||||
mockGetBoundingClientRect,
|
||||
trigger,
|
||||
} from '../../../test';
|
||||
import { LONG_PRESS_START_TIME } from '../../utils';
|
||||
import ImagePreviewComponent from '../ImagePreview';
|
||||
import { images, triggerZoom } from './shared';
|
||||
|
||||
@ -287,3 +289,24 @@ test('should render image slot correctly 2', async () => {
|
||||
|
||||
expect(wrapper.html().includes('video')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should emit long-press event after long press', async () => {
|
||||
const onLongPress = jest.fn();
|
||||
const wrapper = mount(ImagePreviewComponent, {
|
||||
props: {
|
||||
images,
|
||||
show: true,
|
||||
onLongPress,
|
||||
},
|
||||
});
|
||||
|
||||
await later();
|
||||
const swipe = wrapper.find('.van-swipe-item');
|
||||
trigger(swipe, 'touchstart', 0, 0, { x: 0, y: 0 });
|
||||
await later(LONG_PRESS_START_TIME + 100);
|
||||
trigger(swipe, 'touchend', 0, 0, { touchList: [] });
|
||||
|
||||
expect(onLongPress).toHaveBeenLastCalledWith({
|
||||
index: 0,
|
||||
});
|
||||
});
|
||||
|
@ -24,6 +24,7 @@ import {
|
||||
callInterceptor,
|
||||
makeNumericProp,
|
||||
HAPTICS_FEEDBACK,
|
||||
LONG_PRESS_START_TIME,
|
||||
type Numeric,
|
||||
} from '../utils';
|
||||
|
||||
@ -33,7 +34,6 @@ import { useCustomFieldValue } from '@vant/use';
|
||||
const [name, bem] = createNamespace('stepper');
|
||||
|
||||
const LONG_PRESS_INTERVAL = 200;
|
||||
const LONG_PRESS_START_TIME = 600;
|
||||
|
||||
const isEqual = (value1?: Numeric, value2?: Numeric) =>
|
||||
String(value1) === String(value2);
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { nextTick } from 'vue';
|
||||
import { Stepper } from '..';
|
||||
import { mount, later } from '../../../test';
|
||||
import { LONG_PRESS_START_TIME } from '../../utils';
|
||||
|
||||
test('should disable buttons and input when using disabled prop', () => {
|
||||
const wrapper = mount(Stepper, {
|
||||
@ -126,9 +127,9 @@ test('should update value after long pressing', async () => {
|
||||
expect(wrapper.emitted('update:modelValue')![0]).toEqual([2]);
|
||||
|
||||
await plus.trigger('touchstart');
|
||||
await later(1000);
|
||||
await later(LONG_PRESS_START_TIME + 500);
|
||||
await plus.trigger('touchend');
|
||||
expect(wrapper.emitted('update:modelValue')).toEqual([[2], [3], [4]]);
|
||||
expect(wrapper.emitted('update:modelValue')).toEqual([[2], [3], [4], [5]]);
|
||||
});
|
||||
|
||||
test('should allow to disable long press', async () => {
|
||||
|
@ -12,3 +12,7 @@ export const BORDER_UNSET_TOP_BOTTOM = `${BORDER}-unset--top-bottom`;
|
||||
export const HAPTICS_FEEDBACK = 'van-haptics-feedback';
|
||||
|
||||
export const FORM_KEY: InjectionKey<FormProvide> = Symbol('van-form');
|
||||
|
||||
// Same as the default value of iOS long press time
|
||||
// https://developer.apple.com/documentation/uikit/uilongpressgesturerecognizer/1616423-minimumpressduration
|
||||
export const LONG_PRESS_START_TIME = 500;
|
||||
|
Loading…
x
Reference in New Issue
Block a user