Skip to content

Instantly share code, notes, and snippets.

@ZowieTao
Created May 31, 2023 15:32
Show Gist options
  • Save ZowieTao/8372a7a61d8d2c70ab4dc3061732d0d2 to your computer and use it in GitHub Desktop.
Save ZowieTao/8372a7a61d8d2c70ab4dc3061732d0d2 to your computer and use it in GitHub Desktop.
const Swiper = () => {
const [currentIndex, setCurrentIndex] = useState(0)
// eslint-disable-next-line no-unused-vars
const [_, forceUpdate] = useState<boolean>(true)
const slides = useMemo(() => {
const content0 = (
<div className="flex w-full border rounded-xl aspect-[7/4] overflow-hidden">
<div className="w-[232px]">side0</div>
<div className="flex-1">content0</div>
</div>
)
const content1 = (
<div className="flex w-full border rounded-xl aspect-[7/4] overflow-hidden">
<div className="w-[232px]">side1</div>
<div className="flex-1">content1</div>
</div>
)
const content2 = (
<div className="flex w-full border rounded-xl aspect-[7/4] overflow-hidden">
<div className="w-[232px]">side2</div>
<div className="flex-1">content2</div>
</div>
)
const content3 = (
<div className="flex w-full border rounded-xl aspect-[7/4] overflow-hidden">
<div className="w-[232px]">side3</div>
<div className="flex-1">content3</div>
</div>
)
const content4 = (
<div className="flex w-full border rounded-xl aspect-[7/4] overflow-hidden">
<div className="w-[232px]">side4</div>
<div className="flex-1">content4</div>
</div>
)
return [content0, content1, content2, content3, content4]
}, [])
const slidesLen = useMemo(() => {
return slides.length
}, [slides.length])
const content0Ref = useRef(slides[currentIndex])
const content1Ref = useRef(slides[(currentIndex + 1) % slidesLen])
const content2Ref = useRef(slides[(currentIndex + 2) % slidesLen])
const handlePrev = useCallback(() => {
setCurrentIndex((prevIndex) => {
return prevIndex - 1
})
setTimeout(() => {
const windowSize = 3
const _currentCursor = currentIndex - 1
const _idx =
_currentCursor < 0
? windowSize - (Math.abs(_currentCursor) % windowSize)
: _currentCursor % windowSize
if (_idx === 0) {
content0Ref.current = slides[mod(_currentCursor, slidesLen)]
} else if (_idx === 1) {
content1Ref.current = slides[mod(_currentCursor, slidesLen)]
} else {
content2Ref.current = slides[mod(_currentCursor, slidesLen)]
}
forceUpdate((pre) => {
return !pre
})
})
}, [currentIndex, slides, slidesLen])
const mod = (n: number, m: number) => {
return n < 0 ? m - (Math.abs(n) % m) : n % m
}
const handleNext = useCallback(() => {
setCurrentIndex((prevIndex) => {
return prevIndex + 1
})
setTimeout(() => {
const windowSize = 3
const _idx =
currentIndex < 0
? windowSize - (Math.abs(currentIndex) % windowSize)
: currentIndex % windowSize
const offset = currentIndex + windowSize
if (_idx === 0) {
content0Ref.current = slides[mod(offset, slidesLen) % slidesLen]
} else if (_idx === 1) {
content1Ref.current = slides[mod(offset, slidesLen) % slidesLen]
} else {
content2Ref.current = slides[mod(offset, slidesLen) % slidesLen]
}
forceUpdate((pre) => {
return !pre
})
}, 100)
}, [currentIndex, slides, slidesLen])
// const style1 = "flex pt-12 pl-16",
// style2 = "absolute flex w-full h-full pb-12 pr-16",
// style3 = "hidden"
// const [front, cycleFront] = useCycle(style1, style2, style3)
// const [back, cycleBack] = useCycle(style2, style3, style1)
// const [hidden, cycleHidden] = useCycle(style3, style1, style2)
return (
<div className="relative w-full">
<div className="w-full max-w-6xl mx-auto border border-red-800 relative">
{/* font item: flex pt-12 pl-16 */}
<motion.div className="flex pt-12 pl-16">
{content0Ref.current}
</motion.div>
{/* back item: absolute flex w-full h-full pb-12 pr-16 */}
<motion.div className="absolute flex top-0 w-full h-full pb-12 pr-16">
{content1Ref.current}
</motion.div>
{/* hidden and prepare: hidden*/}
<motion.div className="absolute -top-12 -left-12">
{content2Ref.current}
</motion.div>
</div>
<div className="absolute top-1/2 left-0 w-full flex justify-between">
<button
className="px-4 py-2 bg-gray-500 text-white"
onClick={handlePrev}
>
&lt;
</button>
<button
className="px-4 py-2 bg-gray-500 text-white"
onClick={handleNext}
>
&gt;
</button>
</div>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment