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,
|
props: imagePreviewProps,
|
||||||
|
|
||||||
emits: ['scale', 'close', 'closed', 'change', 'update:show'],
|
emits: ['scale', 'close', 'closed', 'change', 'longPress', 'update:show'],
|
||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const swipeRef = ref<SwipeInstance>();
|
const swipeRef = ref<SwipeInstance>();
|
||||||
@ -146,7 +146,7 @@ export default defineComponent({
|
|||||||
indicatorColor="white"
|
indicatorColor="white"
|
||||||
onChange={setActive}
|
onChange={setActive}
|
||||||
>
|
>
|
||||||
{props.images.map((image) => (
|
{props.images.map((image, index) => (
|
||||||
<ImagePreviewItem
|
<ImagePreviewItem
|
||||||
src={image}
|
src={image}
|
||||||
show={props.show}
|
show={props.show}
|
||||||
@ -157,6 +157,7 @@ export default defineComponent({
|
|||||||
rootHeight={state.rootHeight}
|
rootHeight={state.rootHeight}
|
||||||
onScale={emitScale}
|
onScale={emitScale}
|
||||||
onClose={emitClose}
|
onClose={emitClose}
|
||||||
|
onLongPress={() => emit('longPress', { index })}
|
||||||
v-slots={{
|
v-slots={{
|
||||||
image: slots.image,
|
image: slots.image,
|
||||||
}}
|
}}
|
||||||
|
@ -14,6 +14,7 @@ import {
|
|||||||
preventDefault,
|
preventDefault,
|
||||||
createNamespace,
|
createNamespace,
|
||||||
makeRequiredProp,
|
makeRequiredProp,
|
||||||
|
LONG_PRESS_START_TIME,
|
||||||
type ComponentInstance,
|
type ComponentInstance,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
@ -45,7 +46,7 @@ export default defineComponent({
|
|||||||
rootHeight: makeRequiredProp(Number),
|
rootHeight: makeRequiredProp(Number),
|
||||||
},
|
},
|
||||||
|
|
||||||
emits: ['scale', 'close'],
|
emits: ['scale', 'close', 'longPress'],
|
||||||
|
|
||||||
setup(props, { emit, slots }) {
|
setup(props, { emit, slots }) {
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
@ -200,20 +201,23 @@ export default defineComponent({
|
|||||||
const TAP_TIME = 250;
|
const TAP_TIME = 250;
|
||||||
const TAP_OFFSET = 5;
|
const TAP_OFFSET = 5;
|
||||||
|
|
||||||
if (
|
if (offsetX.value < TAP_OFFSET && offsetY.value < TAP_OFFSET) {
|
||||||
offsetX.value < TAP_OFFSET &&
|
// tap or double tap
|
||||||
offsetY.value < TAP_OFFSET &&
|
if (deltaTime < TAP_TIME) {
|
||||||
deltaTime < TAP_TIME
|
if (doubleTapTimer) {
|
||||||
) {
|
clearTimeout(doubleTapTimer);
|
||||||
if (doubleTapTimer) {
|
|
||||||
clearTimeout(doubleTapTimer);
|
|
||||||
doubleTapTimer = null;
|
|
||||||
toggleScale();
|
|
||||||
} else {
|
|
||||||
doubleTapTimer = setTimeout(() => {
|
|
||||||
emit('close');
|
|
||||||
doubleTapTimer = null;
|
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 |
|
| 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 | - |
|
| closed | Emitted when ImagePreview is closed | - |
|
||||||
| change | Emitted when current image changed | _index: number_ |
|
| change | Emitted when current image changed | _index: number_ |
|
||||||
| scale | Emitted when scaling current image | _value: ImagePreviewScaleEventParams_ |
|
| scale | Emitted when scaling current image | _{ index: number, scale: number }_ |
|
||||||
| scale | Emitted when scaling current image | _value: ImagePreviewScaleEventParams_ |
|
| long-press | Emitted when long press current image | _{ index: number }_ |
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
|
@ -250,12 +250,13 @@ Vant 中导出了以下 ImagePreview 相关的辅助函数:
|
|||||||
|
|
||||||
通过组件调用 `ImagePreview` 时,支持以下事件:
|
通过组件调用 `ImagePreview` 时,支持以下事件:
|
||||||
|
|
||||||
| 事件 | 说明 | 回调参数 |
|
| 事件 | 说明 | 回调参数 |
|
||||||
| --- | --- | --- |
|
| ---------- | ---------------------- | ---------------------------------- |
|
||||||
| close | 关闭时触发 | { index: 索引, url: 图片链接 } |
|
| close | 关闭时触发 | _{ index: number, url: string }_ |
|
||||||
| closed | 关闭且且动画结束后触发 | - |
|
| closed | 关闭且且动画结束后触发 | - |
|
||||||
| change | 切换当前图片时触发 | index: 当前图片的索引 |
|
| change | 切换当前图片时触发 | _index: number_ |
|
||||||
| scale | 缩放当前图片时触发 | { index: 当前图片的索引, scale: 当前缩放的值 } |
|
| scale | 缩放当前图片时触发 | _{ index: number, scale: number }_ |
|
||||||
|
| long-press | 长按当前图片时触发 | _{ index: number }_ |
|
||||||
|
|
||||||
### 方法
|
### 方法
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@ import {
|
|||||||
later,
|
later,
|
||||||
triggerDrag,
|
triggerDrag,
|
||||||
mockGetBoundingClientRect,
|
mockGetBoundingClientRect,
|
||||||
|
trigger,
|
||||||
} from '../../../test';
|
} from '../../../test';
|
||||||
|
import { LONG_PRESS_START_TIME } from '../../utils';
|
||||||
import ImagePreviewComponent from '../ImagePreview';
|
import ImagePreviewComponent from '../ImagePreview';
|
||||||
import { images, triggerZoom } from './shared';
|
import { images, triggerZoom } from './shared';
|
||||||
|
|
||||||
@ -287,3 +289,24 @@ test('should render image slot correctly 2', async () => {
|
|||||||
|
|
||||||
expect(wrapper.html().includes('video')).toBeTruthy();
|
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,
|
callInterceptor,
|
||||||
makeNumericProp,
|
makeNumericProp,
|
||||||
HAPTICS_FEEDBACK,
|
HAPTICS_FEEDBACK,
|
||||||
|
LONG_PRESS_START_TIME,
|
||||||
type Numeric,
|
type Numeric,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ import { useCustomFieldValue } from '@vant/use';
|
|||||||
const [name, bem] = createNamespace('stepper');
|
const [name, bem] = createNamespace('stepper');
|
||||||
|
|
||||||
const LONG_PRESS_INTERVAL = 200;
|
const LONG_PRESS_INTERVAL = 200;
|
||||||
const LONG_PRESS_START_TIME = 600;
|
|
||||||
|
|
||||||
const isEqual = (value1?: Numeric, value2?: Numeric) =>
|
const isEqual = (value1?: Numeric, value2?: Numeric) =>
|
||||||
String(value1) === String(value2);
|
String(value1) === String(value2);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
import { Stepper } from '..';
|
import { Stepper } from '..';
|
||||||
import { mount, later } from '../../../test';
|
import { mount, later } from '../../../test';
|
||||||
|
import { LONG_PRESS_START_TIME } from '../../utils';
|
||||||
|
|
||||||
test('should disable buttons and input when using disabled prop', () => {
|
test('should disable buttons and input when using disabled prop', () => {
|
||||||
const wrapper = mount(Stepper, {
|
const wrapper = mount(Stepper, {
|
||||||
@ -126,9 +127,9 @@ test('should update value after long pressing', async () => {
|
|||||||
expect(wrapper.emitted('update:modelValue')![0]).toEqual([2]);
|
expect(wrapper.emitted('update:modelValue')![0]).toEqual([2]);
|
||||||
|
|
||||||
await plus.trigger('touchstart');
|
await plus.trigger('touchstart');
|
||||||
await later(1000);
|
await later(LONG_PRESS_START_TIME + 500);
|
||||||
await plus.trigger('touchend');
|
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 () => {
|
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 HAPTICS_FEEDBACK = 'van-haptics-feedback';
|
||||||
|
|
||||||
export const FORM_KEY: InjectionKey<FormProvide> = Symbol('van-form');
|
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