123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- 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<SwiperMethods, SwiperProps>(
- ({ 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 (
- <View
- className="sights"
- onTouchStart={handleTouchStart}
- onTouchEnd={handleTouchEnd}
- >
- {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 && (
- <RoundItem
- key={id}
- id={realId}
- angle={(360 / 12) * idx}
- bigR={Big_R}
- minR={MIN_R}
- isActive={isActive}
- isNear={nearIds.includes(id)}
- onClick={handleDetail.bind(undefined, realId)}
- onActLoaded={() => {
- setTimeout(() => {
- moving.current = false;
- setIsRunning(true);
- }, 500);
- }}
- />
- )
- );
- })}
- </View>
- );
- }
- );
|