From 8d5f2a3c2077567771a65e21291de0cb0a8277ae Mon Sep 17 00:00:00 2001 From: ys152452 <362565210@qq.com> Date: Sat, 14 Sep 2024 19:19:09 +0800 Subject: [PATCH 1/4] feat(swipe): add rtl mode swipe add rtl mode --- packages/vant/src/swipe/Swipe.tsx | 87 ++++++++++++++++++-------- packages/vant/src/swipe/demo/index.vue | 11 ++++ packages/vant/src/swipe/index.less | 7 +++ packages/vant/src/utils/dom.ts | 8 +++ 4 files changed, 87 insertions(+), 26 deletions(-) diff --git a/packages/vant/src/swipe/Swipe.tsx b/packages/vant/src/swipe/Swipe.tsx index 370c87af2d9..3503d10ded6 100644 --- a/packages/vant/src/swipe/Swipe.tsx +++ b/packages/vant/src/swipe/Swipe.tsx @@ -25,6 +25,7 @@ import { preventDefault, createNamespace, makeNumericProp, + isRtl, } from '../utils'; // Composables @@ -98,7 +99,9 @@ export default defineComponent({ const minOffset = computed(() => { if (state.rect) { const base = props.vertical ? state.rect.height : state.rect.width; - return base - size.value * count.value; + return isRtl(root) + ? size.value * count.value - base + : base - size.value * count.value; } return 0; }); @@ -111,9 +114,9 @@ export default defineComponent({ const trackSize = computed(() => count.value * size.value); - const activeIndicator = computed( - () => (state.active + count.value) % count.value, - ); + const activeIndicator = computed(() => { + return (state.active + count.value) % count.value; + }); const isCorrectDirection = computed(() => { const expect = props.vertical ? 'vertical' : 'horizontal'; @@ -153,12 +156,14 @@ export default defineComponent({ const getTargetOffset = (targetActive: number, offset = 0) => { let currentPosition = targetActive * size.value; if (!props.loop) { - currentPosition = Math.min(currentPosition, -minOffset.value); + currentPosition = isRtl(root) + ? Math.min(currentPosition, minOffset.value) + : Math.min(currentPosition, -minOffset.value); } let targetOffset = offset - currentPosition; if (!props.loop) { - targetOffset = clamp(targetOffset, minOffset.value, 0); + targetOffset = clamp(targetOffset, 0, minOffset.value); } return targetOffset; @@ -180,19 +185,32 @@ export default defineComponent({ const { active } = state; const targetActive = getTargetActive(pace); const targetOffset = getTargetOffset(targetActive, offset); - // auto move first and last swipe in loop mode if (props.loop) { - if (children[0] && targetOffset !== minOffset.value) { - const outRightBound = targetOffset < minOffset.value; - children[0].setOffset(outRightBound ? trackSize.value : 0); - } + if (isRtl(root)) { + if (children[count.value - 1]) { + const outRightBound = targetOffset < size.value; + children[count.value - 1].setOffset( + outRightBound ? trackSize.value : 0, + ); + } - if (children[count.value - 1] && targetOffset !== 0) { - const outLeftBound = targetOffset > 0; - children[count.value - 1].setOffset( - outLeftBound ? -trackSize.value : 0, - ); + if (children[0]) { + const outLeftBound = targetOffset >= minOffset.value; + children[0].setOffset(outLeftBound ? minOffset.value : 0); + } + } else { + if (children[0] && targetOffset !== minOffset.value) { + const outRightBound = targetOffset < minOffset.value; + children[0].setOffset(outRightBound ? trackSize.value : 0); + } + + if (children[count.value - 1] && targetOffset !== 0) { + const outLeftBound = targetOffset > 0; + children[count.value - 1].setOffset( + outLeftBound ? -trackSize.value : 0, + ); + } } } @@ -327,9 +345,12 @@ export default defineComponent({ if (isCorrectDirection.value) { const isEdgeTouch = !props.loop && - ((state.active === 0 && delta.value > 0) || - (state.active === count.value - 1 && delta.value < 0)); - + ((!isRtl(root) && + ((state.active === 0 && delta.value > 0) || + (state.active === count.value - 1 && delta.value < 0))) || + (isRtl(root) && + ((state.active === count.value - 1 && delta.value > 0) || + (state.active === 0 && delta.value < 0)))); if (!isEdgeTouch) { preventDefault(event, props.stopPropagation); move({ offset: delta.value }); @@ -359,13 +380,22 @@ export default defineComponent({ : touch.offsetX.value; let pace = 0; - - if (props.loop) { - pace = offset > 0 ? (delta.value > 0 ? -1 : 1) : 0; + if (isRtl(root)) { + if (props.loop) { + pace = offset > 0 ? (delta.value > 0 ? 1 : -1) : 0; + } else { + pace = Math[delta.value > 0 ? 'ceil' : 'floor']( + delta.value / size.value, + ); + } } else { - pace = -Math[delta.value > 0 ? 'ceil' : 'floor']( - delta.value / size.value, - ); + if (props.loop) { + pace = offset > 0 ? (delta.value > 0 ? -1 : 1) : 0; + } else { + pace = -Math[delta.value > 0 ? 'ceil' : 'floor']( + delta.value / size.value, + ); + } } move({ @@ -430,7 +460,12 @@ export default defineComponent({ } if (props.showIndicators && count.value > 1) { return ( -
+
{Array(count.value).fill('').map(renderDot)}
); diff --git a/packages/vant/src/swipe/demo/index.vue b/packages/vant/src/swipe/demo/index.vue index 5b33fbd8e8d..932504ccdd0 100644 --- a/packages/vant/src/swipe/demo/index.vue +++ b/packages/vant/src/swipe/demo/index.vue @@ -11,6 +11,7 @@ const t = useTranslate({ title4: '纵向滚动', title5: '自定义滑块大小', title6: '自定义指示器', + title7: 'RTL 布局', message: '当前 Swipe 索引:', }, 'en-US': { @@ -19,6 +20,7 @@ const t = useTranslate({ title4: 'Vertical Scrolling', title5: 'Set SwipeItem Size', title6: 'Custom indicator', + title7: ' RTL Layout', message: 'Current Swipe index:', }, }); @@ -95,6 +97,15 @@ const onChange = (index: number) => showToast(t('message') + index); + + + + 1 + 2 + 3 + 4 + +