Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 93 additions & 48 deletions packages/vantui/src/swiper/swiper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,37 +78,6 @@ const Swiper = (
containerSize,
...rest
} = propSwiper
const isVertical = direction === 'vertical'
const timer = useRef<any>(null)
const containerRef = useRef<any>(null)
const innerRef = useRef<any>(null)
const [refRandomId] = useState(Math.random().toString(36).slice(-8))
const [moving, setmoving] = useState(false)
// eslint-disable-next-line prefer-const
let [active, setActive_] = useState(
typeof initPage === 'number' ? initPage : 0,
)
const setActive = (a) => {
active = a
setActive_(a)
}
const [W, setW] = useState(getValidNumber(width))
const [H, setH] = useState(getValidNumber(height))
const [showToDo, setShowToDo] = useState(false)
const [touch] = useState({
startX: 0,
startY: 0,
deltaX: 0,
deltaY: 0,
offsetX: 0,
offsetY: 0,
stateDirection: '',
delta: 0,
})

const size = useMemo(() => {
return isVertical ? H : W
}, [H, W, isVertical])

const { childs, childCount, pageCount, resetChilds } = useMemo(() => {
let childCount = 0
Expand All @@ -124,7 +93,9 @@ const Swiper = (

const childLast = children?.[childCount - 1]
const pageCount = childCount === 2 ? 2 : childCount
if (childCount === 2) {
// 2 items loop, duplicate to 4 items: [2, 1, 2, 1]
// Indices: 0(2), 1(1), 2(2), 3(1)
if (childCount === 2 && loop) {
if (childFirst) {
resetChilds.push(childFirst)
}
Expand All @@ -143,7 +114,44 @@ const Swiper = (
pageCount,
resetChilds,
}
}, [children])
}, [children, loop])

const isVertical = direction === 'vertical'
const timer = useRef<any>(null)
const containerRef = useRef<any>(null)
const innerRef = useRef<any>(null)
const [refRandomId] = useState(Math.random().toString(36).slice(-8))
const [moving, setmoving] = useState(false)
// eslint-disable-next-line prefer-const
let [active, setActive_] = useState(() => {
let init = typeof initPage === 'number' ? initPage : 0
if (resetChilds.length === 4 && pageCount === 2) {
init += 1
}
return init
})

const setActive = (a) => {
active = a
setActive_(a)
}
const [W, setW] = useState(getValidNumber(width))
const [H, setH] = useState(getValidNumber(height))
const [showToDo, setShowToDo] = useState(false)
const [touch] = useState({
startX: 0,
startY: 0,
deltaX: 0,
deltaY: 0,
offsetX: 0,
offsetY: 0,
stateDirection: '',
delta: 0,
})

const size = useMemo(() => {
return isVertical ? H : W
}, [H, W, isVertical])

// 重置 全部位移信息
const touchReset = useCallback(() => {
Expand Down Expand Up @@ -269,19 +277,42 @@ const Swiper = (
let _duration = duration
let timeout: any = 0
// 第一张和最后一样的特殊情况
if (active === 0 && activeNew === childCount - 1) {
_duration = 0
timeout = duration || 0 + 16.66
setInnertStyle(active, duration, size)
} else if (active === childCount - 1 && activeNew === 0) {
_duration = 0
timeout = duration || 0 + 16.66
setInnertStyle(active, duration, -childCount * size)
const is2ItemLoop = resetChilds.length === 4 && pageCount === 2
let needReset = false
if (is2ItemLoop) {
if (active === 2 && activeNew === 3) {
needReset = true
timeout = duration
setInnertStyle(activeNew, duration)
} else if (active === 1 && activeNew === 0) {
needReset = true
timeout = duration
setInnertStyle(activeNew, duration)
}
}

if (!needReset) {
if (active === 0 && activeNew === childCount - 1) {
_duration = 0
timeout = duration || 0 + 16.66
setInnertStyle(active, duration, size)
} else if (active === childCount - 1 && activeNew === 0) {
_duration = 0
timeout = duration || 0 + 16.66
setInnertStyle(active, duration, -childCount * size)
}
}
setTimeout(() => {
setmoving(false)
setActive(activeNew)
setInnertStyle(activeNew, _duration)
let finalActive = activeNew
// For 2 items loop, we expanded to 4 items [2, 1, 2, 1]
// Indices 1 and 2 are the stable ones. 0 and 3 are clones.
if (resetChilds.length === 4 && pageCount === 2) {
if (activeNew === 0) finalActive = 2
if (activeNew === 3) finalActive = 1
}
setActive(finalActive)
setInnertStyle(finalActive, activeNew !== finalActive ? 0 : _duration)
callback?.()
}, timeout)
}
Expand Down Expand Up @@ -343,14 +374,28 @@ const Swiper = (
)

useImperativeHandle(ref, () => ({
to: (n) => moveTo(n),
to: (n) => {
let target = n
if (resetChilds.length === 4 && pageCount === 2) {
target = n + 1
}
moveTo(target)
},
prev: () => moveTo(active - 1 < 0 ? childCount - 1 : active - 1),
next: () => moveTo(active + 1 > childCount - 1 ? 0 : active + 1),
}))

const getCurrentPage = useCallback(() => {
let reportIndex = (active + pageCount) % pageCount
if (resetChilds.length === 4 && pageCount === 2) {
reportIndex = (active - 1 + pageCount) % pageCount
}
return reportIndex
}, [active, pageCount, resetChilds.length])

useEffect(() => {
onChange?.((active + pageCount) % pageCount)
}, [active, pageCount, onChange])
onChange?.(getCurrentPage())
}, [getCurrentPage, onChange])

useDidShow(() => {
setShowToDo(true)
Expand Down Expand Up @@ -456,15 +501,15 @@ const Swiper = (
return (
<Text
style={
(active + pageCount) % pageCount === index
getCurrentPage() === index
? {
backgroundColor: paginationColor,
}
: undefined
}
className={classNames({
['van-swiper__pagination-item']: true,
active: (active + pageCount) % pageCount === index,
active: getCurrentPage() === index,
})}
key={index}
/>
Expand Down
Loading