|
|
@@ -0,0 +1,288 @@
|
|
|
+import styles from "./styles.module.scss";
|
|
|
+import d_bg from "@assets/wheel/d.png";
|
|
|
+import bg_light from "@assets/wheel/bg_light.png";
|
|
|
+import light1 from "@assets/wheel/light1.png";
|
|
|
+import light2 from "@assets/wheel/light2.png";
|
|
|
+import spinBg from "@assets/wheel/spinBg.png";
|
|
|
+import pointer from "@assets/wheel/pointer.png"
|
|
|
+import styled from 'styled-components/macro';
|
|
|
+import {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/wheel/draw.png";
|
|
|
+import {useSelector} from "react-redux";
|
|
|
+import {getTurnplate} from "@features/turnplateSlice";
|
|
|
+import {formatTime} from "@utils/helpers";
|
|
|
+import SvgIcon from "@components/SvgIcon";
|
|
|
+import {ReactComponent as ShareIcon} from '@assets/singlesvg/share.svg';
|
|
|
+const i18n=global.i18n;
|
|
|
+const spinImgSrc=[
|
|
|
+ null,
|
|
|
+ spin_1,
|
|
|
+ spin_2,
|
|
|
+ null,
|
|
|
+ spin_4,
|
|
|
+ spin_5
|
|
|
+]
|
|
|
+const spinImg=[];
|
|
|
+const StyledCanvas=styled.canvas`
|
|
|
+ background-image:url('${spinBg}');
|
|
|
+`
|
|
|
+const turnObj={
|
|
|
+ timer:null,
|
|
|
+ cdTimer:null,
|
|
|
+ count:0
|
|
|
+};
|
|
|
+const WWheel=()=>{
|
|
|
+ let turnplate=useSelector(getTurnplate);
|
|
|
+ if(turnplate==null)turnplate={times:0};
|
|
|
+ const data=[
|
|
|
+ {id:0,type: 1,value: 0},
|
|
|
+ {id:1,type: 0,value: 1000},
|
|
|
+ {id:2,type: 0,value: 50},
|
|
|
+ {id:3,type: 5,value: 0},
|
|
|
+ {id:4,type: 1,value: 0},
|
|
|
+ {id:5,type: 4,value: 0},
|
|
|
+ {id:6,type: 2,value: 0},
|
|
|
+ {id:7,type: 0,value: 1},
|
|
|
+ ]
|
|
|
+ const drawRef=useRef(null);
|
|
|
+ const [imgLoaded,setImgLoaded]=useState(false);
|
|
|
+ const dataLen=8;
|
|
|
+ const startRotateDegree=3240;
|
|
|
+ const startRotateDegreeDynamic=3240;
|
|
|
+ const [drawStyle,setDrawStyle]=useState({});
|
|
|
+ const [countdown,setCountdown]=useState(turnplate?turnplate.countdown:0);
|
|
|
+ const loadImgs=()=>{
|
|
|
+ let totalCount=spinImgSrc.length;
|
|
|
+ let loadedCount=0;
|
|
|
+ let checkDone=()=>{
|
|
|
+ if (loadedCount===totalCount){
|
|
|
+ setImgLoaded(true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (let i = 0; i < totalCount; i++) {
|
|
|
+ let imgSrc=spinImgSrc[i];
|
|
|
+ if (imgSrc==null){
|
|
|
+ loadedCount++;
|
|
|
+ spinImg[i]=null;
|
|
|
+ checkDone();
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ let img=new Image;
|
|
|
+ img.src=imgSrc;
|
|
|
+ spinImg[i]=img;
|
|
|
+ img.onload=()=>{
|
|
|
+ loadedCount++;
|
|
|
+ checkDone();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const clearCDTimer=()=>{
|
|
|
+ if (turnObj.cdTimer!=null){
|
|
|
+ clearInterval(turnObj.cdTimer);
|
|
|
+ turnObj.cdTimer=null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const updateCD=()=>{
|
|
|
+ if (countdown<=0){
|
|
|
+ clearCDTimer();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ setCountdown(countdown-1);
|
|
|
+ }
|
|
|
+ const checkCountdown=()=>{
|
|
|
+ if (countdown>0){
|
|
|
+ clearCDTimer();
|
|
|
+ let left=countdown;
|
|
|
+ turnObj.cdTimer=setInterval(()=>{
|
|
|
+ left--;
|
|
|
+ if (left<=0){
|
|
|
+ clearCDTimer();
|
|
|
+ setCountdown(0);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ setCountdown(left);
|
|
|
+ },1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ const startSpin=()=>{
|
|
|
+ // drawAnimation();
|
|
|
+ startTurn();
|
|
|
+ }
|
|
|
+ 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>3){
|
|
|
+ // drawAnimation(turnCount*360+startRotateDegreeDynamic);
|
|
|
+ stopTurn(1);
|
|
|
+ }
|
|
|
+ },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);
|
|
|
+ drawAnimation(angle);
|
|
|
+ }
|
|
|
+ const drawAnimation=(angle=startRotateDegreeDynamic)=>{
|
|
|
+ clearTurnTimer();
|
|
|
+ let roteStyle={
|
|
|
+ transform:"rotate(".concat(angle, "deg)"),
|
|
|
+ transition:"transform 5.5s cubic-bezier(0.250, 0.460, 0.455, 0.995)",
|
|
|
+ };
|
|
|
+ setDrawStyle(roteStyle);
|
|
|
+ }
|
|
|
+ const drawWheel=()=>{
|
|
|
+ let draw=drawRef.current;
|
|
|
+ if (draw==null)return;
|
|
|
+ let colors=["#B90615","#FFD760"];
|
|
|
+ let color_len=colors.length;
|
|
|
+ let fontSizeNum=25;
|
|
|
+ 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(-2*l);
|
|
|
+ c.save();
|
|
|
+ for (let i = 0; i < dataLen; i++) {
|
|
|
+ let item=rdat[i];
|
|
|
+ if (item==null)continue;
|
|
|
+ let color=colors[i%color_len];
|
|
|
+ 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(.8);
|
|
|
+ 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();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ useEffect(()=>{
|
|
|
+ loadImgs();
|
|
|
+ return ()=>{
|
|
|
+ clearTurnTimer();
|
|
|
+ clearCDTimer();
|
|
|
+ }
|
|
|
+ },[]);
|
|
|
+ useEffect(()=>{
|
|
|
+ if (imgLoaded){
|
|
|
+ drawWheel();
|
|
|
+ }
|
|
|
+ },[imgLoaded])
|
|
|
+ useEffect(()=>{
|
|
|
+ checkCountdown();
|
|
|
+ },[turnplate.countdown])
|
|
|
+ const renderSpinInfo=()=>{
|
|
|
+ let times=turnplate?turnplate.times:0;
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <div className={styles.spin_con}>
|
|
|
+ <button className={styles.spin_btn} onClick={()=>{
|
|
|
+ startSpin();
|
|
|
+ }}>
|
|
|
+ <img src={draw} className={styles.spin_img}/>
|
|
|
+ <div className={styles.spin_content}>
|
|
|
+ <div className={styles.spin_num}>{times}</div>
|
|
|
+ </div>
|
|
|
+ </button>
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ const renderCountDown=()=>{
|
|
|
+ let d=Math.floor(countdown/86400);
|
|
|
+ let time=countdown-d*86400;
|
|
|
+ let stime=formatTime(time);
|
|
|
+ return (
|
|
|
+ <div className={styles.cd_con}>
|
|
|
+ <div>{i18n.t("turnplate.expires_in")}</div>
|
|
|
+ <div className={styles.text}>{d+"d"}</div>
|
|
|
+ <div className={styles.text}>{stime}</div>
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ const renderShareBar=()=>{
|
|
|
+ return (
|
|
|
+ <button className={styles.share_con}>
|
|
|
+ <div className={styles.share_bar}>
|
|
|
+ <div className={styles.text}>{i18n.t("turnplate.invite_tips")}</div>
|
|
|
+ <ShareIcon className={styles.icon}/>
|
|
|
+ </div>
|
|
|
+ </button>
|
|
|
+ )
|
|
|
+ }
|
|
|
+ return (
|
|
|
+ <div className={styles.container}>
|
|
|
+ <div className={styles.wheel}>
|
|
|
+ <img src={bg_light} className={styles.bg_light}/>
|
|
|
+ <img src={d_bg} className={styles.lamp}/>
|
|
|
+ <div className={styles.drawContent}>
|
|
|
+ <StyledCanvas ref={drawRef} className={styles.draw} style={drawStyle}/>
|
|
|
+ </div>
|
|
|
+ <img src={light1} className={`${styles.light} ${styles.light_ani_1}`}/>
|
|
|
+ <img src={light2} className={`${styles.light} ${styles.light_ani_2}`}/>
|
|
|
+ <img src={pointer} className={styles.pointer}/>
|
|
|
+ {
|
|
|
+ renderSpinInfo()
|
|
|
+ }
|
|
|
+ </div>
|
|
|
+ {renderCountDown()}
|
|
|
+ {renderShareBar()}
|
|
|
+ </div>
|
|
|
+ )
|
|
|
+}
|
|
|
+export default WWheel;
|