"use client"; import { getGiveReceiveApi, SlotParams, SlotType } from "@/api/slots"; import { debounce, flatPoint } from "@/utils/methods"; import { SlotMachine } from "@lucky-canvas/react"; import { Mask, Toast } from "antd-mobile"; import clsx from "clsx"; import { useTranslations } from "next-intl"; import { FC, forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react"; import animation from "../animations.module.scss"; interface Props { onAfterHandler: () => void; } const getRandomRedColor = () => { const r = 255; const g = 255; const b = 255; return `rgba(${r},${g},${b},${Math.random().toFixed(1)})`; }; const defaultConfig = { rowSpacing: "0.4861rem", direction: -1, }; const prizes = [ { imgs: [ { width: "80%", height: "100%", src: "/slots/0.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/1.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/2.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/3.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/4.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/5.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/6.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/7.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/8.png", }, ], }, { imgs: [ { width: "80%", height: "100%", src: "/slots/9.png", }, ], }, ]; const slots = [ { order: [9, 7, 6, 8, 2, 5, 4, 3, 1, 0], speed: 30 }, { order: [9, 6, 5, 3, 8, 7, 4, 0, 1, 2], speed: 26 }, { order: [9, 2, 4, 7, 3, 1, 8, 5, 0, 6], speed: 22 }, { order: [9, 3, 8, 5, 0, 1, 2, 4, 6, 7], speed: 18 }, ]; const numberPadding = (n: number, index = 4): number[] => { const s = `${n}`.padStart(index, "0"); return s.split("").map((v, i) => Number(v)); }; const ColorWill = () => { const rows = 9; // 总行数 const cols = 22; // 总列数 const [blocks, setBlocks] = useState( Array.from({ length: rows }, () => Array.from({ length: cols }, () => getRandomRedColor())) ); useEffect(() => {}, []); return ( <>
{/**/} {blocks.map((row, rowIndex) => (
{row.map((n: string, index: number) => { return (
); })}
))}
); }; interface SlotsClientProps { slotSource: SlotType; onRotateAfter?: () => void; } const SlotsClient: FC = (props) => { const { slotSource, onRotateAfter } = props; const slotsRef = useRef(null); const t = useTranslations(); const rotating = useRef(false); const buttonRef = useRef(null); // const ratio = `${slotSource?.rollover.reduce( // (pre, next) => (pre > next.weight ? pre : next.weight), // 0 // )}` // .split("") // .map((n) => Number(n)) || [9, 9]; const [ratio, setRatio] = useState([9, 9]); const params = { activity_id: slotSource?.id, start_time: slotSource?.times[0].start_time, end_time: slotSource?.times[0].end_time, }; useEffect(() => { // getSlots(); }, []); // 开始旋转 const handler = debounce(() => { // 按下动画 if (params && !params.activity_id && !params.start_time) return; if (rotating.current) return; // slotsRef.current?.play(); // setTimeout(() => { // slotsRef.current?.stop(numberPadding(Math.floor(Math.random() * 9999))); // }, 2500); // return; // 图片按下修改高度 let height = buttonRef.current!.clientHeight; buttonRef.current!.style.transition = "height 0.3s"; buttonRef.current!.style.height = `${height * 0.8}px`; rotating.current = true; setTimeout(() => { buttonRef.current!.style.height = `${height}px`; }, 200); slotsRef.current?.play(); // 数据获取 getGiveReceiveApi(params as SlotParams) .then((res) => { setTimeout(() => { const rollover = flatPoint(res.data.rollover / 100); slotsRef.current?.stop(numberPadding(res.data.amount)); setRatio(numberPadding(rollover > 100 ? 99 : rollover, 2)); }, 2500); }) .catch((error) => { slotsRef.current.init(); rotating.current = false; Toast.show(t(`code.${error.data.code}`)); }); }, 300); // 结束旋转 const endHandler = (prize: any) => { // rotating.current = false; onRotateAfter && onRotateAfter(); }; return ( <>
{""} {/*light*/}
{""}
{/*header*/}
{ratio.map((n, index) => ( {""} ))}
{/*slots*/}
); }; export type SlotModalRefProps = { onClose: () => void; onOpen: (value: SlotType) => void; }; const SlotsModal = forwardRef(function SlotsModal(props, ref) { const [visible, setVisible] = useState(false); const { onAfterHandler } = props; const [willStatus, setWillStatus] = useState(false); const [slotSource, setSlotSource] = useState(null); useImperativeHandle(ref, () => { return { onClose: () => setVisible(false), onOpen: (source: SlotType) => { setVisible(true); setSlotSource(source); }, }; }); const globalCls = "absolute z-[8] transition transform duration-1000 ease-in "; const light1 = clsx(globalCls, willStatus ? `${animation.expandAnimation} ` : "hidden", {}); const light2 = clsx(globalCls, willStatus ? `${animation.expandAnimation} ` : "hidden", {}); const light3 = clsx( " object-contain absolute z-[8] ", willStatus ? ` ${animation.scaleLxAnimation}` : "hidden" ); const light4 = clsx( " object-contain absolute z-[8] ", willStatus ? `${animation.scaleRxAnimation}` : "hidden" ); const will = clsx("", willStatus ? "opacity-1" : "opacity-0"); const handler = () => { setWillStatus(true); onAfterHandler(); }; return ( <>
setVisible(false)} >
{/*body*/}
{slotSource && }
); }); export default memo(SlotsModal);