import { ITouchEvent, View } from "@tarojs/components"; import { RoundItem } from "../RoundItem"; import Taro from "@tarojs/taro"; import { forwardRef, useImperativeHandle, useMemo, useRef, useState, } from "react"; import { useInterval } from "../../../../hooks/useInterval"; import "./index.scss"; import { SORT_MAP_ID } from "../../constants"; export interface SwiperProps { curSwiperItem: number; handleDetail(id: number): void; setCurSwiperItem(num: number): void; } export interface SwiperMethods { toNext(): void; toPrev(): void; setIsRunning(v: boolean): void; } const SIGHT_COUNT = 26; const Big_R = (500 * Taro.getSystemInfoSync().windowWidth) / 750; const MIN_R = (150 * Taro.getSystemInfoSync().windowWidth) / 750; const getItemStack = () => { const stack: number[] = []; for (let i = 0; i <= 13; i++) { stack.push(i); } return stack; }; export const Swiper = forwardRef( ({ curSwiperItem, setCurSwiperItem, handleDetail }, ref) => { const [itemStack, setItemStack] = useState(getItemStack()); const touchStartX = useRef(0); const moving = useRef(false); const [isRunning, setIsRunning] = useState(false); const getNextItem = (curIndex: number, length: number) => { return (curIndex + 1) % length; }; const getPreviousItem = (curIndex: number, length: number) => { return (curIndex - 1 + length) % length; }; const getIndicesRelative = (curIndex: number, length: number) => { const nextIndex = getNextItem(curIndex, length); const nextThreeIndices = [nextIndex]; for (let i = 1; i < 1; i++) { nextThreeIndices.push(getNextItem(nextThreeIndices[i - 1], length)); } const previousIndex = getPreviousItem(curIndex, length); const previousThreeIndices = [previousIndex]; for (let i = 1; i <= 2; i++) { previousThreeIndices.push( getPreviousItem(previousThreeIndices[i - 1], length) ); } return [nextThreeIndices, previousThreeIndices]; }; const handleTouchStart = (e: ITouchEvent) => { setIsRunning(false); touchStartX.current = e.changedTouches[0].clientX; }; const handleTouchEnd = (e: ITouchEvent) => { const touchEndX = e.changedTouches[0].clientX; const deltaX = touchEndX - touchStartX.current; if (deltaX > 50) { toPrev(); } else if (deltaX < -50) { toNext(); } }; const toggleHandler = (fn: Function) => { if (moving.current) return; setIsRunning(false); moving.current = true; fn(); }; const toNext = () => { toggleHandler(() => { const temp = [...itemStack]; const swiperItem = getNextItem(curSwiperItem, SIGHT_COUNT); temp.shift(); temp.push(getNextItem(curSwiperItem + 3, SIGHT_COUNT)); setItemStack(temp); setCurSwiperItem(swiperItem); }); }; const toPrev = () => { toggleHandler(() => { const temp = [...itemStack]; const swiperItem = getPreviousItem(curSwiperItem, SIGHT_COUNT); temp.pop(); temp.unshift(getPreviousItem(itemStack[0], SIGHT_COUNT)); setItemStack(temp); setCurSwiperItem(swiperItem); }); }; const [nexts, prevs] = useMemo( () => getIndicesRelative(curSwiperItem, SIGHT_COUNT), [curSwiperItem] ); const activeId = getPreviousItem(curSwiperItem, SIGHT_COUNT); const nearIds = [ getPreviousItem(activeId, SIGHT_COUNT), getNextItem(activeId, SIGHT_COUNT), ]; useImperativeHandle(ref, () => { return { toNext, toPrev, setIsRunning, }; }); useInterval(toNext, isRunning ? 5000 : null); return ( {itemStack.map((id, idx) => { const realId = SORT_MAP_ID[id + 1 > 25 ? 0 : id + 1]; const show = [...nexts, ...prevs].includes(id) || id === curSwiperItem; const isActive = activeId === id; return ( show && ( { setTimeout(() => { moving.current = false; setIsRunning(true); }, 500); }} /> ) ); })} ); } );