|
@@ -6,18 +6,9 @@ import { getToken } from "@/utils/Cookies";
|
|
|
import { Mask } from "antd-mobile";
|
|
|
import clsx from "clsx";
|
|
|
import { useTranslations } from "next-intl";
|
|
|
-import Image from "next/image";
|
|
|
-import {
|
|
|
- forwardRef,
|
|
|
- Fragment,
|
|
|
- memo,
|
|
|
- useEffect,
|
|
|
- useImperativeHandle,
|
|
|
- useRef,
|
|
|
- useState,
|
|
|
-} from "react";
|
|
|
+import { FC, forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
|
+import animation from "./animations.module.scss";
|
|
|
import styles from "./redpacked.module.scss";
|
|
|
-
|
|
|
const randomX = (len: number) => {
|
|
|
return Math.floor(Math.random() * len);
|
|
|
};
|
|
@@ -46,289 +37,6 @@ function getRandom(min: number, max: number) {
|
|
|
type DescProps = {
|
|
|
onClose: () => void;
|
|
|
};
|
|
|
-const Desc = (props: DescProps) => {
|
|
|
- const { onClose } = props;
|
|
|
- const [activeTab, setActiveTab] = useState(0);
|
|
|
- const tabs = [{ text: "Vezes de evento participado" }, { text: "Consulta de registo levado" }];
|
|
|
- return (
|
|
|
- <div className={"absolute top-[30%] w-[100%]"}>
|
|
|
- <div className={"absolute -top-[1.3rem] left-1/2 w-[3.3rem] -translate-x-1/2"}>
|
|
|
- <img src="/9f/red-header.png" alt="" />
|
|
|
- <div
|
|
|
- className={
|
|
|
- "h-[0.2rem] w-[0.2rem] " + " absolute bottom-[20px] right-[30px]" + " "
|
|
|
- }
|
|
|
- onClick={onClose}
|
|
|
- >
|
|
|
- <Image src={"/9f/close.png"} alt={"close"} width={25} height={25} />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- className={"mx-auto w-[2.9rem] bg-[#ff9417] px-[0.16rem] pb-[0.12rem] pt-[0.44rem]"}
|
|
|
- >
|
|
|
- <img src="/9f/red-title.png" alt="" className={"mx-auto w-[90%]"} />
|
|
|
- <div className={"mt-[0.0694rem] rounded-[3px] bg-primary-color"}>
|
|
|
- <div className={"flex h-[0.54rem] justify-between text-center text-[0.15rem]"}>
|
|
|
- {tabs.map((item, index) => {
|
|
|
- return (
|
|
|
- <Fragment key={index}>
|
|
|
- <span
|
|
|
- onClick={() => setActiveTab(index)}
|
|
|
- className={`flex h-[100%] items-center ${index === activeTab ? "bg-[#8b3500] text-[#5f2600]" : ""}`}
|
|
|
- >
|
|
|
- {item.text}
|
|
|
- </span>
|
|
|
- </Fragment>
|
|
|
- );
|
|
|
- })}
|
|
|
- </div>
|
|
|
- {/* 动态内容 */}
|
|
|
- <div className={"h-[3rem] overflow-y-scroll p-[0.1rem]"}>
|
|
|
- <div
|
|
|
- className={
|
|
|
- "flex items-center rounded-[0.1rem] bg-[#d45300] p-[10px] font-bold"
|
|
|
- }
|
|
|
- >
|
|
|
- <Image
|
|
|
- className={"h-[0.43rem] w-[0.7rem]"}
|
|
|
- width={80}
|
|
|
- height={40}
|
|
|
- src="/9f/wallet.png"
|
|
|
- alt=""
|
|
|
- />
|
|
|
- <div className={"text-center"}>
|
|
|
- <h2> Tempo regressivo </h2>
|
|
|
- <p className={"text-[#fe0]"}>Começa amanhã às 11:00</p>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {!activeTab ? (
|
|
|
- <>
|
|
|
- <Image
|
|
|
- src={"/9f/6xtime.png"}
|
|
|
- className={"mt-[0.1rem] h-[0.7rem] w-[100%] rounded-[0.1rem]"}
|
|
|
- width={600}
|
|
|
- height={100}
|
|
|
- alt={"time"}
|
|
|
- ></Image>
|
|
|
-
|
|
|
- <Image
|
|
|
- src={"/9f/3xtime.png"}
|
|
|
- className={"mt-[0.1rem] h-[0.55rem] w-[100%] rounded-[0.1rem]"}
|
|
|
- width={600}
|
|
|
- height={80}
|
|
|
- alt={"time"}
|
|
|
- ></Image>
|
|
|
- </>
|
|
|
- ) : (
|
|
|
- <>
|
|
|
- <div
|
|
|
- className={"mt-[0.1rem] rounded-[0.1rem] bg-[#d45300] p-[10px]"}
|
|
|
- >
|
|
|
- <p className={"text-[#fe0]"}>Registro persoal</p>
|
|
|
- <div
|
|
|
- className={
|
|
|
- "grid grid-cols-3 text-center" +
|
|
|
- " items-center text-[0.1rem]"
|
|
|
- }
|
|
|
- >
|
|
|
- <span>Nome do jogo</span>
|
|
|
- <span>Coleta cumulativa</span>
|
|
|
- <span>Participação total</span>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div
|
|
|
- className={
|
|
|
- "grid grid-cols-3 text-center" +
|
|
|
- " items-center text-[0.12rem] font-bold"
|
|
|
- }
|
|
|
- >
|
|
|
- <span>55****26</span>
|
|
|
- <span>R$ 100.00</span>
|
|
|
- <span>1</span>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- <div
|
|
|
- className={"mt-[0.1rem] rounded-[0.1rem] bg-[#d45300] p-[10px]"}
|
|
|
- >
|
|
|
- <p className={"text-[#fe0]"}>Lista dos vencedores</p>
|
|
|
- <div
|
|
|
- className={
|
|
|
- "grid grid-cols-3 text-center" +
|
|
|
- " items-center text-[0.1rem]"
|
|
|
- }
|
|
|
- >
|
|
|
- <span>ID do papel</span>
|
|
|
- <span>Valor obtido</span>
|
|
|
- <span>Hora obtida</span>
|
|
|
- </div>
|
|
|
- <div className={`h-[1rem] overflow-hidden`}>
|
|
|
- {mockData.map((item, index) => {
|
|
|
- return (
|
|
|
- <div
|
|
|
- key={index}
|
|
|
- className={`grid grid-cols-3 items-center text-center text-[0.12rem] font-bold ${styles.scrollAnimation}`}
|
|
|
- >
|
|
|
- <span>{item.phone}</span>
|
|
|
- <span>R$ {item.num}</span>
|
|
|
- <span>{item.time}</span>
|
|
|
- </div>
|
|
|
- );
|
|
|
- })}
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </>
|
|
|
- )}
|
|
|
-
|
|
|
- <ul className={"mt-[0.1rem] text-[0.1rem]"}>
|
|
|
- <li>
|
|
|
- ·Cada sessão de chuva de dinheiro é distribuída gratuitamente por
|
|
|
- R$100.000.
|
|
|
- </li>
|
|
|
- <li>
|
|
|
- ·Valor máximo de queda em dinheiro: Cada sessão de chuva de dinheiro
|
|
|
- é distribuída gratuitamente.
|
|
|
- </li>
|
|
|
- <li>·Membros recarregados podem reivindicar gratuitamente.</li>
|
|
|
- <li>
|
|
|
- ·O dinheiro recebido pode ser utilizado para jogar ou sacar
|
|
|
- diretamente.
|
|
|
- </li>
|
|
|
- <li>
|
|
|
- ·Quanto for maior o nível de associação VIP, será maior o valor
|
|
|
- recebido.
|
|
|
- </li>
|
|
|
- </ul>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- );
|
|
|
-};
|
|
|
-
|
|
|
-// 红包掉落动画像下雨
|
|
|
-const FallAnimation1 = (props: any) => {
|
|
|
- const { onClose } = props;
|
|
|
- const fallContentRef = useRef<HTMLDivElement>(null);
|
|
|
- const isActive = useRef(true);
|
|
|
-
|
|
|
- const getRandom = (min: number, max: number) => {
|
|
|
- return Math.random() * (max - min) + min;
|
|
|
- };
|
|
|
-
|
|
|
- const createMoneyElement = (xPos: number) => {
|
|
|
- if (!fallContentRef.current || !isActive.current) return;
|
|
|
-
|
|
|
- const money = document.createElement('div');
|
|
|
-
|
|
|
- // 基础样式
|
|
|
- money.style.cssText = `
|
|
|
- position: fixed;
|
|
|
- left: ${xPos}px;
|
|
|
- top: -100px;
|
|
|
- width: 60px;
|
|
|
- height: 60px;
|
|
|
- pointer-events: none;
|
|
|
- `;
|
|
|
-
|
|
|
- // 创建图片
|
|
|
- const img = document.createElement('img');
|
|
|
- img.src = `/9f/money${Math.floor(Math.random() * 3) + 1}.png`;
|
|
|
- img.style.cssText = `
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- object-fit: contain;
|
|
|
- `;
|
|
|
-
|
|
|
- money.appendChild(img);
|
|
|
- fallContentRef.current.appendChild(money);
|
|
|
-
|
|
|
- // 使用 requestAnimationFrame 确保元素已添加到 DOM 后再添加动画
|
|
|
- requestAnimationFrame(() => {
|
|
|
- const scale = getRandom(0.4, 1);
|
|
|
- const duration = getRandom(8, 12);
|
|
|
- const delay = getRandom(0, 5);
|
|
|
-
|
|
|
- money.style.cssText += `
|
|
|
- transform: scale(${scale});
|
|
|
- z-index: ${Math.floor(scale * 100)};
|
|
|
- animation: ${styles.fall} ${duration}s linear infinite,
|
|
|
- ${styles.sway} ${duration/2}s ease-in-out infinite alternate;
|
|
|
- animation-delay: ${delay}s;
|
|
|
- `;
|
|
|
- });
|
|
|
-
|
|
|
- // 当动画完成一次循环后,重新设置位置
|
|
|
- setInterval(() => {
|
|
|
- if (isActive.current) {
|
|
|
- money.style.left = `${getRandom(0, window.innerWidth)}px`;
|
|
|
- }
|
|
|
- }, 12000);
|
|
|
- };
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- console.log('FallAnimation1 mounted'); // 调试日志
|
|
|
-
|
|
|
- if (!fallContentRef.current) return;
|
|
|
-
|
|
|
- // 设置容器样式
|
|
|
- fallContentRef.current.style.cssText = `
|
|
|
- position: fixed;
|
|
|
- top: 0;
|
|
|
- left: 0;
|
|
|
- width: 100%;
|
|
|
- height: 100vh;
|
|
|
- z-index: 1000;
|
|
|
- pointer-events: none;
|
|
|
- overflow: hidden;
|
|
|
- background: transparent;
|
|
|
- `;
|
|
|
-
|
|
|
- // 分批创建元素
|
|
|
- const totalElements = 300;
|
|
|
- const batchSize = 20;
|
|
|
- let created = 0;
|
|
|
-
|
|
|
- const createBatch = () => {
|
|
|
- if (!isActive.current) return;
|
|
|
-
|
|
|
- for (let i = 0; i < batchSize && created < totalElements; i++) {
|
|
|
- const xPos = getRandom(0, window.innerWidth);
|
|
|
- createMoneyElement(xPos);
|
|
|
- created++;
|
|
|
- }
|
|
|
-
|
|
|
- if (created < totalElements) {
|
|
|
- setTimeout(createBatch, 200);
|
|
|
- }
|
|
|
- };
|
|
|
-
|
|
|
- createBatch();
|
|
|
-
|
|
|
- return () => {
|
|
|
- console.log('FallAnimation1 unmounting'); // 调试日志
|
|
|
- isActive.current = false;
|
|
|
- };
|
|
|
- }, []);
|
|
|
-
|
|
|
- return (
|
|
|
- <div
|
|
|
- ref={fallContentRef}
|
|
|
- style={{
|
|
|
- position: 'fixed',
|
|
|
- top: 0,
|
|
|
- left: 0,
|
|
|
- width: '100%',
|
|
|
- height: '100vh',
|
|
|
- zIndex: 1000,
|
|
|
- }}
|
|
|
- onClick={(e) => {
|
|
|
- e.stopPropagation();
|
|
|
- onClose?.();
|
|
|
- }}
|
|
|
- />
|
|
|
- );
|
|
|
-};
|
|
|
|
|
|
const HbyInfoDetail = (props: any) => {
|
|
|
const { iconImg, onCloseHby } = props;
|
|
@@ -344,43 +52,8 @@ const HbyInfoDetail = (props: any) => {
|
|
|
<div
|
|
|
className={`absolute left-1/2 top-[50%] w-[90%] -translate-x-1/2 -translate-y-1/2 ${styles.promoRules}`}
|
|
|
>
|
|
|
- {/* <Image src={"/hby/close.png"} alt={"close"} width={25} height={25} onClick={onCloseHby} className={styles.closeIcon}/> */}
|
|
|
<div onClick={onCloseHby} className={styles.closeIcon}></div>
|
|
|
- <Image src={iconImg} onClick={handler} alt={"detail"} width={672} height={1044} />
|
|
|
- {/* <div className={`h-[0.15rem] text-[#ffd800] text-[0.20rem] text-center ${styles.promoTitle}`}>Dinheiro como chuva</div>
|
|
|
- <div className={styles.titleWrap}>
|
|
|
- <span>R$200.00</span>
|
|
|
- <span> por vez, </span>
|
|
|
- <span>Máx queda </span>
|
|
|
- <span>R$7.777</span>
|
|
|
- </div>
|
|
|
- <div className={styles.tips}>
|
|
|
- <img src="/hby/tip-icon.png" alt="tips" className={styles.tipsIcon}/>
|
|
|
- <div className={styles.tipsTime}>Começa às 23:00</div>
|
|
|
- </div>
|
|
|
- <div className={styles.times1}>
|
|
|
- <img src="/hby/time1.png"/>
|
|
|
- </div>
|
|
|
- <div className={styles.times2}>
|
|
|
- <img src="/hby/time2.png"/>
|
|
|
- </div>
|
|
|
- <ul className={styles.rulelist}>
|
|
|
- <li className={styles.ruleItem}>
|
|
|
- Cada sessão de chuva de dinheiro é distribuída gratuitamente com <span>R$200.000</span>
|
|
|
- </li>
|
|
|
- <li className={styles.ruleItem}>
|
|
|
- Valor máximo de queda em dinheiro:Cada sessäo de chuva de dinheiro é distribuida gratuitamente com
|
|
|
- </li>
|
|
|
- <li className={styles.ruleItem}>
|
|
|
- Membros recarregados podem reivindicar gratuitamente
|
|
|
- </li>
|
|
|
- <li className={styles.ruleItem}>
|
|
|
- O dinheiro recebido pode ser utilizado para jogar ou sacado diretamente
|
|
|
- </li>
|
|
|
- <li className={styles.ruleItem}>
|
|
|
- Quanto maior o nivel de associacäo VP, maior o valor recebido
|
|
|
- </li>
|
|
|
- </ul> */}
|
|
|
+ <img src={iconImg} onClick={handler} alt={"detail"} width={672} height={1044} />
|
|
|
</div>
|
|
|
);
|
|
|
};
|
|
@@ -432,7 +105,7 @@ const HbyInfo2 = (props: any) => {
|
|
|
className={hbyInfoClass}
|
|
|
style={{ background: `url(${iconImg})`, backgroundSize: "100% 100%" }}
|
|
|
>
|
|
|
- <Image
|
|
|
+ <img
|
|
|
src={"/hby/close.png"}
|
|
|
alt={"close"}
|
|
|
width={30}
|
|
@@ -450,6 +123,75 @@ const HbyInfo2 = (props: any) => {
|
|
|
);
|
|
|
};
|
|
|
|
|
|
+/**
|
|
|
+ * @description 动画背景 - 下雨动效
|
|
|
+ */
|
|
|
+
|
|
|
+const FallAnimation = (props: any) => {
|
|
|
+ const { onClose } = props;
|
|
|
+ const fallContentRef = useRef<HTMLDivElement>(null);
|
|
|
+
|
|
|
+ const totalPackets = 200;
|
|
|
+ const timer = useRef<NodeJS.Timer>(null);
|
|
|
+ const total = useRef(0);
|
|
|
+ const createPacket = (xPoint: number) => {
|
|
|
+ const packetWrapperEl = document.createElement("div");
|
|
|
+ packetWrapperEl.classList.add(styles.packetWrapper);
|
|
|
+ packetWrapperEl.style.left = xPoint + "px";
|
|
|
+ packetWrapperEl.style.width = `77px`;
|
|
|
+ packetWrapperEl.style.height = `44px`;
|
|
|
+ packetWrapperEl.style.transform = `scale(${getRandom(0.4, 1.2)}) `;
|
|
|
+
|
|
|
+ const packetEl = document.createElement("img");
|
|
|
+ packetEl.classList.add(styles.packet);
|
|
|
+
|
|
|
+ packetEl.style.width = `${getRandom(44, 77)}`;
|
|
|
+ packetEl.style.height = `${getRandom(44, 77)}`;
|
|
|
+
|
|
|
+ packetEl.src = `/9f/money${Math.floor(Math.random() * 3) + 1}.png`;
|
|
|
+
|
|
|
+ setInterval(() => {
|
|
|
+ packetEl.style.transform = `rotate(${getRandom(0, 180)}deg) translateX(${Math.random() > 0.5 ? getRandom(0, 180) : -getRandom(0, 180)}px) `;
|
|
|
+ }, 1000);
|
|
|
+
|
|
|
+ packetWrapperEl.appendChild(packetEl);
|
|
|
+ fallContentRef.current?.appendChild(packetWrapperEl);
|
|
|
+ };
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ // @ts-ignore
|
|
|
+ timer.current = setInterval(() => {
|
|
|
+ if (total.current >= totalPackets - 1) {
|
|
|
+ clearInterval(Number(timer.current));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ total.current += 1;
|
|
|
+ createPacket(Math.random() * fallContentRef.current?.clientWidth! || 500);
|
|
|
+ }, 200);
|
|
|
+ return () => {
|
|
|
+ clearInterval(Number(timer.current));
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
+ return <div ref={fallContentRef} className={"h-dvh overflow-hidden"} onClick={onClose}></div>;
|
|
|
+};
|
|
|
+const FallAnimation1 = ({ onClose }: { onClose: () => void }) => {
|
|
|
+ const fallContentRef = useRef<HTMLDivElement | null>(null);
|
|
|
+ return (
|
|
|
+ <div
|
|
|
+ ref={fallContentRef}
|
|
|
+ className={"h-[100dvh] h-[100vh] overflow-hidden"}
|
|
|
+ onClick={onClose}
|
|
|
+ >
|
|
|
+ {Array(300)
|
|
|
+ .fill(0)
|
|
|
+ .map((n, index) => (
|
|
|
+ <div key={index} className={animation.snow}>
|
|
|
+ <img src={`/9f/money${Math.floor(Math.random() * 3) + 1}.png`} alt="" />
|
|
|
+ </div>
|
|
|
+ ))}
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
type Props = {
|
|
|
onAfterHandler?: () => void;
|
|
|
};
|
|
@@ -461,15 +203,125 @@ export type RedPacketModalProps = {
|
|
|
/**
|
|
|
* @description 红包的三种状态
|
|
|
* is_start 可领取 展示红包领取组件
|
|
|
- * is_receive 已领取 展示领取情组件
|
|
|
- * is_end 可展示 展示���明页
|
|
|
+ * is_receive 已领取 展示领取详情组件
|
|
|
+ * is_end 可展示 展示说明页
|
|
|
*/
|
|
|
enum Status {
|
|
|
is_start,
|
|
|
is_receive,
|
|
|
is_end,
|
|
|
}
|
|
|
+interface Snowflake {
|
|
|
+ x: number; // 水平位置
|
|
|
+ y: number; // 垂直位置
|
|
|
+ scale: number; // 缩放比例
|
|
|
+ speedX: number; // 水平移动速度
|
|
|
+ speedY: number; // 垂直下落速度
|
|
|
+ rotate: number; // 当前旋转角度
|
|
|
+ rotateSpeed: number; // 旋转速度
|
|
|
+ image: HTMLImageElement; // 图片路径
|
|
|
+}
|
|
|
|
|
|
+interface SnowfallProps {
|
|
|
+ images: string[]; // 图片数组
|
|
|
+ snowflakeCount?: number; // 雪花数量
|
|
|
+ onClose: () => void;
|
|
|
+}
|
|
|
+
|
|
|
+const Snowfall: FC<SnowfallProps> = ({ images, snowflakeCount = 200, onClose = () => {} }) => {
|
|
|
+ // canvas
|
|
|
+ const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
|
|
+ // 预加载图片
|
|
|
+ const imageElements = useRef<HTMLImageElement[]>([]);
|
|
|
+ // 父元素
|
|
|
+ const containerRef = useRef<HTMLDivElement | null>(null);
|
|
|
+
|
|
|
+ const createSnowflakes = (count: number, width: number, height: number): Snowflake[] => {
|
|
|
+ return Array.from({ length: count }, () => ({
|
|
|
+ x: Math.random() * width,
|
|
|
+ y: Math.random() * height - height,
|
|
|
+ scale: Math.random() * (1.2 - 0.3) + 0.3,
|
|
|
+ speedX: Math.random() * 1.5 - 0.75,
|
|
|
+ speedY: Math.random() * 3 + 1,
|
|
|
+ rotate: Math.random() * 180,
|
|
|
+ rotateSpeed: Math.random() * 2 - 1,
|
|
|
+ image: imageElements.current[Math.floor(Math.random() * imageElements.current.length)],
|
|
|
+ }));
|
|
|
+ };
|
|
|
+ useEffect(() => {
|
|
|
+ // Preload images
|
|
|
+ imageElements.current = images.map((src) => {
|
|
|
+ const img = new Image();
|
|
|
+ img.src = src;
|
|
|
+ return img;
|
|
|
+ });
|
|
|
+
|
|
|
+ const canvas = canvasRef.current;
|
|
|
+ if (!canvas) return;
|
|
|
+
|
|
|
+ const ctx = canvas.getContext("2d");
|
|
|
+ if (!ctx) return;
|
|
|
+
|
|
|
+ const width = (canvas.width = containerRef.current?.clientWidth || 0);
|
|
|
+ const height = (canvas.height = containerRef.current?.clientHeight || 0);
|
|
|
+
|
|
|
+ let snowflakes: Snowflake[] = createSnowflakes(snowflakeCount, width, height);
|
|
|
+
|
|
|
+ const animate = () => {
|
|
|
+ ctx.clearRect(0, 0, width, height);
|
|
|
+ snowflakes.forEach((flake) => {
|
|
|
+ flake.y += flake.speedY;
|
|
|
+ flake.x += flake.speedX;
|
|
|
+ flake.rotate += flake.rotateSpeed;
|
|
|
+
|
|
|
+ if (flake.y > height) {
|
|
|
+ flake.y = -44;
|
|
|
+ flake.x = Math.random() * width;
|
|
|
+ flake.rotate = Math.random() * 360;
|
|
|
+ }
|
|
|
+ if (flake.x < 0 || flake.x > width) {
|
|
|
+ flake.speedX *= -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ ctx.save();
|
|
|
+ ctx.globalAlpha = 1;
|
|
|
+ ctx.translate(flake.x + (77 * flake.scale) / 2, flake.y + (44 * flake.scale) / 2);
|
|
|
+ ctx.rotate((flake.rotate * Math.PI) / 180);
|
|
|
+ ctx.drawImage(
|
|
|
+ flake.image,
|
|
|
+ (-77 * flake.scale) / 2,
|
|
|
+ (-44 * flake.scale) / 2,
|
|
|
+ 77 * flake.scale,
|
|
|
+ 44 * flake.scale
|
|
|
+ );
|
|
|
+ ctx.restore();
|
|
|
+ });
|
|
|
+
|
|
|
+ requestAnimationFrame(animate);
|
|
|
+ };
|
|
|
+
|
|
|
+ animate();
|
|
|
+
|
|
|
+ const handleResize = () => {
|
|
|
+ canvas.width = containerRef.current?.clientWidth || 0;
|
|
|
+ console.dir(containerRef.current);
|
|
|
+ canvas.height = containerRef.current?.clientHeight || 0;
|
|
|
+ snowflakes = createSnowflakes(snowflakeCount, canvas.width, canvas.height);
|
|
|
+ };
|
|
|
+
|
|
|
+ window.addEventListener("resize", handleResize);
|
|
|
+
|
|
|
+ return () => {
|
|
|
+ window.removeEventListener("resize", handleResize);
|
|
|
+ };
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className={"absolute h-[100%] w-[100%]"} ref={containerRef} onClick={onClose}>
|
|
|
+ <canvas ref={canvasRef} style={{ display: "block" }} />;
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+};
|
|
|
const RedPacketModal = forwardRef<RedPacketModalProps, Props>(function RedPacketModal(props, ref) {
|
|
|
const { onAfterHandler } = props;
|
|
|
const [visible, setVisible] = useState(false);
|
|
@@ -502,7 +354,7 @@ const RedPacketModal = forwardRef<RedPacketModalProps, Props>(function RedPacket
|
|
|
const getRedPacketInfo = async () => {
|
|
|
try {
|
|
|
let actList = packets.current;
|
|
|
- // 是否开始但是没领过的红包
|
|
|
+ // 是否有已开始但是没领过的红包
|
|
|
let packetsFilter = actList
|
|
|
.filter((aItem: any) => {
|
|
|
return aItem.can_receive && aItem.is_start && !aItem.is_receive;
|
|
@@ -559,9 +411,13 @@ const RedPacketModal = forwardRef<RedPacketModalProps, Props>(function RedPacket
|
|
|
}, []);
|
|
|
return (
|
|
|
<Mask visible={visible} destroyOnClose={true} getContainer={element.current}>
|
|
|
- <FallAnimation1 onClose={() => setVisible(false)} />
|
|
|
{/*<FallAnimation1 onClose={() => setVisible(false)} />*/}
|
|
|
|
|
|
+ <Snowfall
|
|
|
+ images={["/9f/money1.png", "/9f/money2.png", "/9f/money3.png"]}
|
|
|
+ onClose={() => setVisible(false)}
|
|
|
+ />
|
|
|
+
|
|
|
{status === Status.is_start ? (
|
|
|
<HbyInfo
|
|
|
onCloseHby={() => setVisible(false)}
|