From c9a65c4f08fd62fc985517e99d2d615c360b0cec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=B5=B7=E8=B7=83?= Date: Thu, 18 Jan 2024 14:58:22 +0800 Subject: [PATCH 1/2] feat: picker supports setting the sliding direction --- packages/vant/src/composables/use-touch.ts | 2 +- packages/vant/src/picker/Picker.tsx | 3 + packages/vant/src/picker/PickerColumn.tsx | 28 +++- packages/vant/src/picker/README.md | 1 + packages/vant/src/picker/README.zh-CN.md | 1 + .../src/picker/demo/WithPopupHorizontal.vue | 121 ++++++++++++++++++ packages/vant/src/picker/demo/index.vue | 3 + 7 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 packages/vant/src/picker/demo/WithPopupHorizontal.vue diff --git a/packages/vant/src/composables/use-touch.ts b/packages/vant/src/composables/use-touch.ts index 817924f4c6b..40fcb35b3a7 100644 --- a/packages/vant/src/composables/use-touch.ts +++ b/packages/vant/src/composables/use-touch.ts @@ -1,7 +1,7 @@ import { ref } from 'vue'; import { TAP_OFFSET } from '../utils'; -type Direction = '' | 'vertical' | 'horizontal'; +export type Direction = '' | 'vertical' | 'horizontal'; function getDirection(x: number, y: number) { if (x > y) { diff --git a/packages/vant/src/picker/Picker.tsx b/packages/vant/src/picker/Picker.tsx index 6332ba14629..ab9cae0775b 100644 --- a/packages/vant/src/picker/Picker.tsx +++ b/packages/vant/src/picker/Picker.tsx @@ -55,6 +55,7 @@ import type { PickerToolbarPosition, } from './types'; import { PICKER_GROUP_KEY } from '../picker-group/PickerGroup'; +import { type Direction } from '../composables/use-touch'; export const pickerSharedProps = extend( { @@ -65,6 +66,7 @@ export const pickerSharedProps = extend( showToolbar: truthProp, swipeDuration: makeNumericProp(1000), visibleOptionNum: makeNumericProp(6), + direction: makeStringProp('vertical'), }, pickerToolbarProps, ); @@ -209,6 +211,7 @@ export default defineComponent({ optionHeight={optionHeight.value} swipeDuration={props.swipeDuration} visibleOptionNum={props.visibleOptionNum} + direction={props.direction} onChange={(value: Numeric) => onChange(value, columnIndex)} onClickOption={(option: PickerOption) => onClickOption(option, columnIndex) diff --git a/packages/vant/src/picker/PickerColumn.tsx b/packages/vant/src/picker/PickerColumn.tsx index 7b07594b66e..37ada956741 100644 --- a/packages/vant/src/picker/PickerColumn.tsx +++ b/packages/vant/src/picker/PickerColumn.tsx @@ -15,13 +15,14 @@ import { preventDefault, createNamespace, makeRequiredProp, + makeStringProp, type Numeric, } from '../utils'; import { getElementTranslateY, findIndexOfEnabledOption } from './utils'; // Composables -import { useEventListener, useParent } from '@vant/use'; -import { useTouch } from '../composables/use-touch'; +import { useEventListener, useParent, useRect } from '@vant/use'; +import { useTouch, type Direction } from '../composables/use-touch'; import { useExpose } from '../composables/use-expose'; // Types @@ -55,6 +56,7 @@ export default defineComponent({ optionHeight: makeRequiredProp(Number), swipeDuration: makeRequiredProp(numericProp), visibleOptionNum: makeRequiredProp(numericProp), + direction: makeStringProp('vertical'), }, emits: ['change', 'clickOption', 'scrollInto'], @@ -65,6 +67,7 @@ export default defineComponent({ let touchStartTime: number; let momentumOffset: number; let transitionEndTrigger: null | (() => void); + let horSign = 0; // 水平滑动的方向符号 const root = ref(); const wrapper = ref(); @@ -159,6 +162,17 @@ export default defineComponent({ touchStartTime = Date.now(); momentumOffset = startOffset; transitionEndTrigger = null; + + if (props.direction === 'horizontal') { + // 根据第一个和最后一个item的位置来判断旋转方向 + const liNodeList = wrapper.value!.children; + horSign = liNodeList.length + ? Math.sign( + useRect(liNodeList[liNodeList.length - 1]).x - + useRect(liNodeList[0]).x, + ) + : 0; + } }; const onTouchMove = (event: TouchEvent) => { @@ -168,13 +182,19 @@ export default defineComponent({ touch.move(event); - if (touch.isVertical()) { + if ( + (props.direction === 'vertical' && touch.isVertical()) || + (props.direction === 'horizontal' && touch.isHorizontal()) + ) { moving = true; preventDefault(event, true); } const newOffset = clamp( - startOffset + touch.deltaY.value, + startOffset + + (props.direction === 'horizontal' + ? touch.deltaX.value * horSign + : touch.deltaY.value), -(count() * props.optionHeight), props.optionHeight, ); diff --git a/packages/vant/src/picker/README.md b/packages/vant/src/picker/README.md index ff37887b828..ac640509a30 100644 --- a/packages/vant/src/picker/README.md +++ b/packages/vant/src/picker/README.md @@ -352,6 +352,7 @@ export default { | option-height | Option height, supports `px` `vw` `vh` `rem` unit, default `px` | _number \| string_ | `44` | | visible-option-num | Count of visible columns | _number \| string_ | `6` | | swipe-duration | Duration of the momentum animation, unit `ms` | _number \| string_ | `1000` | +| direction | Sliding direction, adapts to the sliding of options after the element is rotated, cat be set to `horizontal` | _string_ | `vertical` | ### Events diff --git a/packages/vant/src/picker/README.zh-CN.md b/packages/vant/src/picker/README.zh-CN.md index ffbb3ce5d4a..9a8bb7e7fe4 100644 --- a/packages/vant/src/picker/README.zh-CN.md +++ b/packages/vant/src/picker/README.zh-CN.md @@ -373,6 +373,7 @@ export default { | option-height | 选项高度,支持 `px` `vw` `vh` `rem` 单位,默认 `px` | _number \| string_ | `44` | | visible-option-num | 可见的选项个数 | _number \| string_ | `6` | | swipe-duration | 快速滑动时惯性滚动的时长,单位 `ms` | _number \| string_ | `1000` | +| direction | 滑动方向,适配元素旋转以后选项的滑动,可选值为 `horizontal` | _string_ | `vertical` | ### Events diff --git a/packages/vant/src/picker/demo/WithPopupHorizontal.vue b/packages/vant/src/picker/demo/WithPopupHorizontal.vue new file mode 100644 index 00000000000..1223a53bb71 --- /dev/null +++ b/packages/vant/src/picker/demo/WithPopupHorizontal.vue @@ -0,0 +1,121 @@ + + + + + diff --git a/packages/vant/src/picker/demo/index.vue b/packages/vant/src/picker/demo/index.vue index c6353ceb9dc..96fc26f27b5 100644 --- a/packages/vant/src/picker/demo/index.vue +++ b/packages/vant/src/picker/demo/index.vue @@ -1,6 +1,7 @@