| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550 |
- import styles from "./styles.module.scss";
- // import d_bg from "@assets/holidaysGift/d.png";
- import img_close from "@assets/holidaysGift/close.png";
- // import img_theme from "@assets/holidaysGift/theme.png";
- import icon_cash from "@assets/holidaysGift/cash.png";
- import icon_gift from "@assets/holidaysGift/gift.png";
- // import spinBg from "@assets/holidaysGift/spinBg.png";
- import styled from 'styled-components/macro';
- import React, { useEffect, useRef, useState } from "react";
- import spin_1 from "@assets/wheel/spin-1.png";
- import spin_2 from "@assets/wheel/spin-2.png";
- import spin_4 from "@assets/wheel/spin-4.png";
- import spin_5 from "@assets/wheel/spin-5.png";
- // import draw from "@assets/holidaysGift/draw.png";
- // import light1 from "@assets/holidaysGift/light1.png";
- import light2 from "@assets/holidaysGift/light2.png";
- import { useDispatch, useSelector } from "react-redux";
- import { getIsHelp, getTurnplate, updateCollect, updateTimes } from "@features/turnplateSlice";
- import { formatCash, formatTime, localStorageGet, localStorageSet } from "@utils/helpers";
- import { getHolidaysGiftInfo, isLogined, updateHolidaysGiftSpinTimes } from "@features/mainSlice";
- import { useNavigate } from "react-router";
- import CountUp from "react-countup";
- import { Fade, Grow, Modal } from "@mui/material";
- import usePaymentActions from "@hooks/usePaymentActions";
- import { reqGameInfo, reqHolidaysGiftSpin } from "@features/api";
- import HOLIDAYS from "@constants/holidays";
- const i18n = global.i18n;
- const spinImgSrc = [
- null,
- spin_1,
- spin_2,
- null,
- spin_4,
- spin_5
- ];
- const spinImg = [];
- const turnObj = {
- timer: null,
- cdTimer: null,
- count: 0,
- result: null,
- resTimer: null,
- flashTimer: null,
- resetTimer: null,
- ishelp: false
- };
- const CURRENT_HOLIDAY = HOLIDAYS.Christmas;
- const getThemeImg = (imgName) => {
- const img = require(`@assets/holidaysGift/${CURRENT_HOLIDAY.name}/${imgName}.png`);
- return img;
- };
- const StyledCanvas = styled.canvas`
- background-image:url('${getThemeImg("spinBg")}');
- `;
- const WHolidaysGift = () => {
- const info = useSelector(getHolidaysGiftInfo);
- // console.error("holidays info", info);
- let { slots, user, recharge_rules, status } = info;
- const data = slots?.map((item, index) => {
- return { id: index + 1, type: 0, value: item };
- });
- const [spinTimes, setSpinTimes] = useState(user?.left_times);
- useEffect(() => {
- if (user?.left_times !== undefined) {
- setSpinTimes(user.left_times);
- }
- }, [user]);
- const [open, setOpen] = useState(false);
- const drawRef = useRef(null);
- const dataLen = 16;
- const startRotateDegreeDynamic = 3240;
- const [drawStyle, setDrawStyle] = useState({});
- const navigate = useNavigate();
- const dispatch = useDispatch();
- const stopduring = 5.5;
- const resetduring = 2;
- const [collect, setCollect] = useState(0);
- const [isLock, setIsLock] = useState(false);
- const statusRef = useRef(status);
- useEffect(() => {
- statusRef.current = status;
- }, [status]);
- const show = () => {
- if (statusRef.current === 0) return global.openNextPopup();;
- setOpen(true);
- };
- const hide = () => {
- setOpen(false);
- };
- const onClose = () => {
- hide();
- global.openNextPopup();
- };
- useEffect(() => {
- const holidaysGift = {
- show,
- hide
- };
- global.holidaysGift = holidaysGift;
- }, []);
- const onCheckClose = () => {
- onClose();
- };
- const clearCDTimer = () => {
- if (turnObj.cdTimer != null) {
- clearInterval(turnObj.cdTimer);
- turnObj.cdTimer = null;
- }
- };
- const onTurnResult = (res) => {
- // console.error("onTurnResult", res);
- // return;
- if (res.code !== 200) {
- resetWheel(0);
- return;
- }
- let { reward, slot_index, left_times } = res.data;
- let type = 0;
- let curr_amount = 0;
- let collect_amount = 0;
- let change = 0;
- let id = data[slot_index]?.id;
- turnObj.result = {
- type: type,
- reward: id,
- amount: collect_amount,
- change: change
- };
- console.error("turnObj.result", turnObj.result);
- dispatch(updateHolidaysGiftSpinTimes({ left_times }));
- };
- const startSpin = async () => {
- if (isLock) return;
- if (spinTimes <= 0 || isNaN(spinTimes)) return;
- // if (spinTimes === 1) isLastSpin = true;
- startTurn();
- setSpinTimes(spinTimes - 1);
- setIsLock(true);
- let res = await dispatch(reqHolidaysGiftSpin()).unwrap();
- onTurnResult(res);
- };
- const clearTurnTimer = () => {
- if (turnObj.timer != null) {
- clearInterval(turnObj.timer);
- turnObj.timer = null;
- }
- };
- const startTurn = () => {
- clearTurnTimer();
- turnObj.count = 0;
- let turnCount = turnObj.count;
- let during = 0.333;
- let roteStyle = {
- transform: `rotate(360deg)`,
- transition: `transform ${during * 2}s cubic-bezier(0.42, 0.00, 1.00, 1.00)`,
- };
- setDrawStyle(roteStyle);
- let timer = setInterval(() => {
- turnCount++;
- turnObj.count++;
- roteStyle = {
- transform: `rotate(${turnCount * 360}deg)`,
- transition: `transform ${during}s cubic-bezier(1.00, 1.00, 0.00, 0.00)`,
- };
- setDrawStyle(roteStyle);
- if (turnCount > 2) {
- if (turnObj.result) {
- stopTurn(turnObj.result.reward);
- }
- }
- }, during * 1000);
- turnObj.timer = timer;
- };
- const stopTurn = (reward) => {
- let index = 0;
- for (let i = 0; i < dataLen; i++) {
- let item = data[i];
- if (item && item.id === reward) {
- index = i;
- break;
- }
- }
- let per = 360 / dataLen;
- let angle = turnObj.count * 360 + startRotateDegreeDynamic - (per * (index + 1)) + 11;
- drawAnimation(angle);
- // console.error("stopTurn ", turnplate);
- };
- const drawAnimation = (angle = startRotateDegreeDynamic, fix) => {
- clearTurnTimer();
- let roteStyle = {
- transform: "rotate(".concat(angle, "deg)"),
- transition: `transform ${stopduring}s cubic-bezier(0.250, 0.460, 0.455, 0.995)`,
- };
- setDrawStyle(roteStyle);
- playRes(angle);
- };
- const flashDraw = () => {
- let show = false;
- turnObj.flashTimer = setInterval(() => {
- show = !show;
- let result = show ? turnObj.result : null;
- drawWheel(result);
- }, 260);
- };
- const playRes = (angle = 0) => {
- clearResTimer();
- let during = (stopduring + 0.5) * 1000;
- turnObj.resTimer = setTimeout(() => {
- flashDraw();
- startReset(angle);
- }, during);
- };
- // const
- const clearResTimer = () => {
- if (turnObj.resTimer) {
- clearTimeout(turnObj.resTimer);
- turnObj.resTimer = null;
- }
- if (turnObj.flashTimer) {
- clearInterval(turnObj.flashTimer);
- turnObj.flashTimer = null;
- }
- };
- const startReset = (angle = 0) => {
- turnObj.resetTimer = setTimeout(() => {
- resetWheel(angle);
- // console.error("startReset ");
- spinOver();
- }, resetduring * 1000);
- };
- const resetWheel = (angle = 0) => {
- clearTurnTimer();
- turnObj.result = null;
- turnObj.count = 0;
- turnObj.ishelp = false;
- if (angle == null) angle = 0;
- else angle = angle % 360;
- let roteStyle = {
- transform: "rotate(" + angle + "deg)",
- transition: ``,
- };
- setDrawStyle(roteStyle);
- drawWheel(null);
- setCollect(0);
- setIsLock(false);
- clearResTimer();
- };
- const clearResetTimer = () => {
- if (turnObj.resetTimer) {
- clearTimeout(turnObj.resetTimer);
- turnObj.resetTimer = null;
- }
- };
- const drawWheel2 = (result) => {
- let draw = drawRef.current;
- if (draw == null) return;
- let colors = ["#FFFFFF", "#8960DD"];
- let color_len = colors.length;
- let fontSizeNum = 14;
- if (data != null) {
- let s = draw;
- let rdat = data.slice(0, dataLen);
- let c = draw.getContext("2d");
- let dcwidth = draw.clientWidth;
- let dcheight = draw.clientHeight;
- let devicePixelRatioNum = window.devicePixelRatio < 1 ? 1 : window.devicePixelRatio;
- s.width = dcwidth * devicePixelRatioNum;
- s.height = dcheight * devicePixelRatioNum;
- c.clearRect(0, 0, s.width, s.height);
- let l = 2 * Math.PI / dataLen;
- let g = -s.width / 2 + s.width / 2 / 2.5;
- c.translate(s.width / 2, s.width / 2);
- c.rotate(-3 * l);
- c.save();
- for (let i = 0; i < dataLen; i++) {
- let item = rdat[i];
- if (item == null) continue;
- let color = colors[i % color_len];
- if (result) {
- if (result.reward === item.id) {
- c.beginPath();
- c.moveTo(0, 0);
- c.arc(0, 0, s.width / 2 - 6, -l, 0);
- c.strokeStyle = "#fff";
- c.fillStyle = "#fff";
- c.lineWidth = 10;
- c.lineTo(0, -5);
- c.stroke();
- c.closePath();
- }
- }
- c.rotate(l);
- c.save();
- c.beginPath();
- c.fillStyle = color;
- c.textBaseline = "middle";
- c.textAlign = "center";
- c.font = "".concat(devicePixelRatioNum * fontSizeNum, "px SWISSC-BT");
- c.translate(s.width / 5.2, -s.width / dataLen);
- c.rotate(1);
- c.translate(-s.width / 5.2, s.width / dataLen);
- if (item.type === 0) {
- c.fillText(item.value, s.width / 7.2, g + devicePixelRatioNum * fontSizeNum * .36, 3 * s.width / dataLen);
- }
- else {
- let img = spinImg[item.type];
- if (img) c.drawImage(img, s.width / 23, g - 11 * devicePixelRatioNum, s.width / 5, s.width / 4.37);
- }
- c.restore();
- }
- }
- };
- const drawWheel = (result) => {
- let draw = drawRef.current;
- if (draw == null) return;
- let colors = CURRENT_HOLIDAY.gift.color;
- let color_len = colors.length;
- let fontSizeNum = 18;
- if (data != null) {
- let s = draw;
- let rdat = data.slice(0, dataLen);
- let c = draw.getContext("2d");
- let dcwidth = draw.clientWidth;
- let dcheight = draw.clientHeight;
- let devicePixelRatioNum = window.devicePixelRatio < 1 ? 1 : window.devicePixelRatio;
- s.width = dcwidth * devicePixelRatioNum;
- s.height = dcheight * devicePixelRatioNum;
- c.clearRect(0, 0, s.width, s.height);
- let l = 2 * Math.PI / dataLen;
- let g = -s.width / 2 + s.width / 2 / 2.5;
- c.translate(s.width / 2, s.width / 2);
- c.rotate(-1 * l);
- c.save();
- for (let i = 0; i < dataLen; i++) {
- let item = rdat[i];
- if (item == null) continue;
- let color = colors[i % color_len];
- if (result) {
- if (result.reward === item.id) {
- c.beginPath();
- c.moveTo(0, 0);
- c.arc(0, 0, s.width / 2 - 6, -3 * l, -2 * l);
- c.strokeStyle = "#fff";
- c.fillStyle = "#fff";
- c.lineWidth = 3.3 * devicePixelRatioNum;
- c.lineTo(0, -5);
- c.stroke();
- c.closePath();
- }
- }
- c.rotate(l);
- c.save();
- c.beginPath();
- c.fillStyle = color;
- c.textBaseline = "middle";
- c.textAlign = "center";
- c.font = "".concat(devicePixelRatioNum * fontSizeNum, "px Roboto");
- c.translate(s.width / 5.2, -s.width / dataLen);
- c.rotate(1);
- c.translate(-s.width / 5.2, s.width / dataLen);
- if (item.type === 0) {
- c.rotate(4);
- c.fillText("$" + item.value, 50 * devicePixelRatioNum, -0.0);
- }
- else {
- let img = spinImg[item.type];
- if (img) c.drawImage(img, s.width / 23, g - 11 * devicePixelRatioNum, s.width / 5, s.width / 4.37);
- }
- c.restore();
- }
- }
- };
- useEffect(() => {
- return () => {
- clearTurnTimer();
- clearCDTimer();
- clearResTimer();
- turnObj.result = null;
- clearResetTimer();
- };
- }, []);
- // 检测 Modal 内容是否已渲染
- const [contentMounted, setContentMounted] = useState(false);
- useEffect(() => {
- if (open) {
- // 等待下一帧确保 DOM 已渲染
- requestAnimationFrame(() => {
- requestAnimationFrame(() => {
- setContentMounted(true);
- });
- });
- } else {
- setContentMounted(false);
- }
- }, [open]);
- useEffect(() => {
- if (contentMounted && drawRef.current) {
- drawWheel();
- }
- }, [contentMounted]);
- // let isLastSpin = false;
- const spinOver = () => {
- dispatch(reqGameInfo());
- global.showDropCoins();
- };
- const renderSpinInfo = () => {
- return (
- <>
- <div className={styles.spin_con}>
- <button className={styles.spin_btn} onClick={() => {
- startSpin();
- }}>
- {spinTimes > 0 && !isLock ? <img src={light2} className={`${styles.light2} ${styles.scale}`} /> : <></>}
- <img src={getThemeImg("draw")} className={styles.spin_img} />
- {spinTimes > 0 && !isLock ? <img src={getThemeImg("light1")} className={`${styles.light1} ${styles.blink}`} /> : <></>}
- <div className={styles.spin_content}>
- {
- collect > 0 ? (
- <CountUp
- start={0}
- end={Number(formatCash(collect))}
- duration={1}
- separator=" "
- decimals={2}
- prefix={"+"}
- >
- {({ countUpRef, start }) => {
- return (
- <div ref={(ref) => {
- countUpRef.current = ref;
- if (countUpRef.collect !== collect) {
- countUpRef.collect = collect;
- start();
- }
- }} className={styles.collect_num} />
- );
- }}
- </CountUp>
- ) : (
- <div className={styles.spin_num}>{spinTimes}</div>
- )
- }
- </div>
- </button>
- </div>
- </>
- );
- };
- const { startPayingOrder } = usePaymentActions();
- const handleBuyClick = (rule) => {
- setOpen(false);
- let payload = {
- price: rule.amount,
- goodsName: "",
- payType: "",
- GiftsID: rule.gear.gift_id,
- gear: rule.gear.gear
- };
- startPayingOrder(payload);
- localStorageSet("payHolidaysGift", true);
- };
- if (!!!status) return <></>;
- return (
- <>
- <Modal open={open} onClose={onCheckClose} closeAfterTransition>
- <Fade in={open} timeout={500}>
- <div className={`${styles.container} ${styles[CURRENT_HOLIDAY.name]}`}>
- {/* <Grow in={open} timeout={500}> */}
- <div className={styles.wheel}>
- <div className={`${styles.wheelBox}`}>
- <img src={getThemeImg("bg")} className={styles.bg} />
- <div className={styles.drawContent}>
- <StyledCanvas ref={drawRef} className={styles.draw} style={drawStyle} />
- </div>
- {
- CURRENT_HOLIDAY.gift.decorate ? <img src={getThemeImg("decorate")} className={styles.decorate} /> : <></>
- }
- {renderSpinInfo()}
- </div>
- <img src={getThemeImg("theme")} alt="" className={styles.themeImg} />
- <div className={styles.msgPanel}>
- <div className={styles.title}>
- Complete The Recharge And Draw A Prize To GetUp To 100% Extra Reward
- </div>
- {
- recharge_rules?.map((rule, index) => {
- return (
- <div className={styles.item} key={index}>
- <div className={styles.itemBox}>
- <img src={icon_cash} alt="" className={styles.icon_cash} />
- <span className={styles.price}>${rule?.amount}</span>
- </div>
- <span className={styles.plus}>+</span>
- <div className={styles.itemBox}>
- <img src={icon_gift} alt="" className={styles.icon_gift} />
- <span className={styles.spinTimes}>SPIN+{rule?.times}</span>
- </div>
- <div className={styles.buy} onClick={() => handleBuyClick(rule)} >${rule?.gear?.money}</div>
- </div>
- );
- })
- }
- </div>
- </div>
- {/* </Grow> */}
- <img src={img_close} alt="" className={styles.close} onClick={onCheckClose} />
- </div>
- </Fade >
- </Modal >
- </>
- );
- };
- export default WHolidaysGift;
|