移动端微信h5
<template>
<div class="container" id="container">
<div class="regBag"></div>
<div class="moneyBox">
<transition
v-for="(item,index) in showImgList"
:key="index"
appear
name="animate__animated animate__bounce"
enter-active-class="animate__bounceOutUp"
leave-active-class="animate__bounceOutDown"
>
<div class="money" key="img" style="z-index: 0;width: 104%;"></div>
</transition>
<div class="money" style="z-index: -50;"></div>
<div class="money" style="z-index: -49;"></div>
<div class="money" style="z-index: -48;"></div>
<div class="money" style="z-index: -47;"></div>
<div class="money" style="z-index: -46;"></div>
<div class="money" style="z-index: -45;"></div>
<div class="money" style="z-index: -44;"></div>
<div class="money" style="z-index: -43;"></div>
<div class="money" style="z-index: -42;"></div>
</div>
<div class="wait_tips" v-if="!startType" id="wait_tips" style="opacity: 1; transform: scale(1, 1);">
<img src="@/assets/images/ready.png" v-if="readySrc == 0">
<img src="@/assets/images/3.png" v-else-if="readySrc == 1">
<img src="@/assets/images/2.png" v-else-if="readySrc == 2">
<img src="@/assets/images/1.png" v-else-if="readySrc == 3">
<img src="@/assets/images/go.png" v-else-if="readySrc == 4">
</div>
<div class="mask"></div>
<div class="gold"></div>
<div class="time">
<div class="timeTxt">倒计时</div>
<span id="time">{{ timeCount }}</span>
</div>
<div class="totalScore">
积分:<span>{{ count }}</span>
</div>
<div class="opt">
<div class="back_ico" id="backBtn" @click.stop="toBackIndex()"></div>
<div class="rank_ico" id="rankBtn" v-if="rankBtnShow" @click.stop="openRankList()"></div>
</div>
<div class="playTips" id="playTips" :class="{touchend:touchState}" v-if="newVal === 4">
<div class="arrow"></div>
<div class="hand"></div>
</div>
<div class="rank_mask" id="rank_list" v-if="rankShow">
<div style="height: 3em;"></div>
<div class="close" id="closeBtn" @click.stop="closeRankList()"></div>
<div class="rank_box"></div>
<div class="rank_list_box">
<div class="rank_dec"></div>
<div class="rank_list_ranking">
<div class="rank_list_rankingBs">
<div class="my_rank">
<p class="my_rankTop"><span class="my-rank-title">您当前排名为</span> <span class="rank_myTop" id="myTop">{{ curRank }}</span> 名</p>
</div>
<div class="rank" id="rankBox" style="height: 232px;">
<div class="rank-row" :class="{'rank-active': index === curRank - 1}" v-for="(item, index) in rankList" :key="index">
<span>{{ index + 1 }}</span>
<img :src="item.headimgurl" alt="">
<span class="rank-name">{{ item.nickName }}</span>
<span class="rank-score">{{ item.scores }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import wx from 'weixin-js-sdk';
import { getSign, getRedirectUrl, getOpenId, getUserInfo, getRankList } from "@/api/login.ts"
const showImgList = ref([])
const touchInfo = reactive({
startX: 0,
startY: 0
})
const touchState = ref(false)
const rankShow = ref(false)
const rankBtnShow = ref(false)
const count = ref(0)
const timeCount = ref(30)
const gameTimer = ref(null)
const codeStr:any = new URLSearchParams(window.location.search).get('code')
const openId = ref('')
const rankList = ref([])
const startType = ref(false)
const readySrc = ref(0)
const curRank = ref(0)
const getRankListData = () => {
getRankList().then((res: any) => {
if (res.code === 200) {
rankList.value = res.data
curRank.value = rankList.value.findIndex((item: any) => item.openId === openId.value) + 1
}
})
}
watch(timeCount, (newVal) => {
if (newVal <= 0) {
getRankListData()
clearInterval(gameTimer.value);
gameTimer.value = null
rankShow.value = true
readySrc.value = 0
startType.value = false
rankBtnShow.value = true
}
})
watch(readySrc, (newVal) => {
if (newVal === 4) {
setTimeout(() => {
startType.value = true
timeCount.value = 30
gameTimer.value = setInterval(function () {
timeCount.value -= 1
}, 1000);
}, 1000);
}
})
let websocket = null
// const wsUrl = 'ws://8.140.57.214:890/websocket'
const wsUrl = 'wss://h5.xqiot.top/game-socket/websocket'
const getAngle = (angx, angy) => (Math.atan2(angy, angx) * 180) / Math.PI;
const getDirection = (startx, starty, endx, endy) => {
const angx = endx - startx;
const angy = endy - starty;
let result = 0;
//如果滑动距离太短
if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
console.log('==>点击了一下');
return result;
}
const angle = getAngle(angx, angy);
if (angle < 0 && -90 < angle) {
result = 1
console.log('往【右上】滑动1');
} else if (angle < -90 && -180 < angle) {
result = 2
console.log('往【左上】滑动2');
} else if (angle < 90 && 0 < angle) {
result = 3
console.log('往【右下】滑动0');
} else {
result = 4
console.log('往【左下】滑动0');
}
return result;
};
//排行榜关闭
const closeRankList = () => {
rankShow.value = false
}
//打开排行榜
const openRankList = () => {
getRankListData()
rankShow.value = true
}
const getCode = () => {
getRedirectUrl().then((res: any) => {
if (res.code === 200) {
window.location.href = res.data
}
})
}
const getSignInfo = () => {
const params = {
url:encodeURIComponent(location.href.split('#')[0])
}
getSign(params).then((res: { data: any;code:number }) => {
if(res.code === 200) {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: 'xxx', // 必填,公众号的唯一标识
timestamp: res.data.timestamp, // 必填,生成签名的时间戳
nonceStr: res.data.nonceStr, // 必填,生成签名的随机串
signature: res.data.cardSign, // 必填,签名
jsApiList: ['closeWindow']
});
getCode()
}
});
}
const toBackIndex = () => {
window.location.href = 'https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=xxx==#wechat_redirect'
}
//获取随机数
const randomNum = (length = 32) => {//默认32位
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
let num = '';
for(let i = 0;i < length;i++) {
num += arr[parseInt(Math.random() * arr.length)];
}
return num;
}
const getUserData = () => {
getUserInfo({wxCode:codeStr}).then((res:any) => {
if(res.code === 200) {
websocket = new WebSocket(wsUrl, openId.value)
const msgPayload = JSON.stringify({nickname: res.data.nickname, headimgurl: res.data.headimgurl})
websocket.onopen = function () {
websocket.send(JSON.stringify({msgId:randomNum(32), messageType:3, msgPayload, openId:openId.value }))
}
websocket.onmessage = function (event) {
const eventInfo = JSON.parse(event.data)
if (eventInfo.messageType === 5) {
for (let index = 0; index < 5; index++) {
setTimeout(() => {
readySrc.value = index
}, index * 1000);
}
}
}
}
})
}
onBeforeMount(() => {
if(!codeStr) {
getSignInfo()
}else{
getOpenId({wxCode:codeStr}).then((res:any) => {
if(res.code === 200) {
openId.value = res.data.openid
websocket = new WebSocket(wsUrl, openId.value);
if(res.data.subscribe === 0) {
toBackIndex()
}else{
getUserData()
}
}
})
}
})
onMounted(() => {
//手指接触屏幕
document.getElementById('container').addEventListener(
'touchstart',
function (e) {
touchInfo.startX = `${e.touches[0].pageX}`;
touchInfo.startY = `${e.touches[0].pageY}`;
e.stopPropagation();
},
false
);
document.getElementById('container').addEventListener(
'touchend',
function (e) {
const endX = e.changedTouches[0].pageX;
const endY = e.changedTouches[0].pageY;
const direction = getDirection(touchInfo.startX, touchInfo.startY, endX, endY);
if(direction !== 0 && readySrc.value === 4) {
if(touchState.value) {
showImgList.value.push(direction)
count.value += 100
websocket.send(JSON.stringify({ msgId: randomNum(32), messageType: 7, msgPayload: 100, openId: openId.value }))
}
touchState.value = true;
}
e.stopPropagation();
},
false
);
});
</script>
<style lang='scss' scoped>
@-webkit-keyframes handSwipe {
0% {
top: 70vh;
opacity: 1;
}
70% {
top: 200px;
opacity: 1;
}
100% {
top: 200px;
opacity: 0;
}
}
@-moz-keyframes handSwipe {
0% {
top: 70vh;
opacity: 1;
}
70% {
top: 200px;
opacity: 1;
}
100% {
top: 200px;
opacity: 0;
}
}
@keyframes handSwipe {
0% {
top: 70vh;
opacity: 1;
}
70% {
top: 200px;
opacity: 1;
}
100% {
top: 200px;
opacity: 0;
}
}
.container {
width: 100%;
height: 100vh;
background: url("@/assets/images/bg.jpg");
background-size: 100% 100%;
position: relative;
overflow: hidden;
bottom: 0;
top: 0;
left: 0;
.regBag{
background: url('@/assets/images/red_bag.png') no-repeat center bottom;
width: 86%;
height: 100%;
position: absolute;
bottom: -20px;
background-size: 100% auto;
left: 7%;
}
.moneyBox{
width: 60%;
height: 100%;
position: relative;
margin: 0 auto;
.money{
background: url('@/assets/images/money.png') no-repeat center bottom;
width: 100%;
height: 100%;
position: absolute;
top: 0;
background-size: 100% auto;
pointer-events: none;
}
}
.wait_tips {
position: absolute;
top: 50%;
margin-top: -50px;
color: #fdbe22;
font-size: 2.5rem;
width: 100%;
font-weight: bold;
background: rgba(17, 17, 17, 0.6);
padding: 20px 0;
text-align: center;
z-index: 998;
}
.mask{
width: 86%;
height: 135px;
position: absolute;
bottom: -20px;
left: 7%;
background: url("@/assets/images/mask.png") no-repeat center 0;
background-size: 100% auto;
z-index: 501;
pointer-events: none;
}
.gold{
width: 100%;
height: 60px;
position: absolute;
bottom: 0;
background: url("@/assets/images/gold.png") no-repeat center 0;
background-size: 100% auto;
z-index: 502;
pointer-events: none;
}
.time{
position: absolute;
top: 15px;
right: 20px;
font-weight: bold;
font-size: 1.875rem;
color: #fff;
div{
display: inline-block;
position: relative;
top: -5px;
}
span{
font-size: 3rem;
color: #fdbe23;
font-weight: bold;
padding: 0 5px;
}
}
.playTips{
position: absolute;
background-color: rgba(0, 0, 0, .5);
z-index: 999;
top: 0;
width: 100%;
height: 100%;
.arrow{
width: 40%;
height: 100%;
background: url('@/assets/images/arrow.png') no-repeat center;
background-size: contain;
margin: 0 auto;
}
.hand{
width: 120px;
height: 120px;
background: url('@/assets/images/hand.png') no-repeat center;
background-size: contain;
position: absolute;
top: 90vh;
left: 50%;
-webkit-animation: handSwipe 1.8s ease infinite;
-moz-animation: handSwipe 1.8s ease infinite;
animation: handSwipe 1.8s ease infinite;
}
}
.touchend{
display: none;
}
.totalScore{
position: absolute;
z-index: 10;
top: 14%;
width: 100%;
text-align: center;
color: #ffff4d;
font-size: 2rem;
}
/*排行榜公共样式*/
.rank_mask {
position: absolute;
background-color: rgba(0, 0, 0, .5);
top: 0;
width: 100%;
height: 100%;
z-index: 1000;
.close {
width: 32px;
height: 32px;
background: url('@/assets/images/rank_close.png') no-repeat center;
position: absolute;
top: 30px;
right: 20px;
background-size: contain;
z-index: 10;
}
.rank_dec {
width: 100%;
height: 178px;
background: url('@/assets/images/rank_list_dec.png') no-repeat center;
background-size: contain;
position: absolute;
top: -89px;
left: 0;
}
.rank_list_box {
background: url('@/assets/images/rank_list_boxBs.png') no-repeat;
background-size: 100% 100%;
width: 89%;
margin: 0 auto;
position: relative;
border-bottom-left-radius: 2em;
border-bottom-right-radius: 2em;
margin-top: 7%;
padding: 0 11px 18px;
.rank_list_ranking {
padding-top: 70px;
width: 100%;
margin: 10px auto 0;
.rank_list_rankingBs {
background: url('@/assets/images/rankBs.png') no-repeat;
background-size: 100% 100%;
padding-bottom: 14px;
.my_rank {
padding-top: 18px;
padding-bottom: 10px;
.my_rankTop {
margin: 0 auto;
background-image: -webkit-linear-gradient(bottom, #c58726, #843a06, #211e14);
-webkit-background-clip: text;
-webkit-text-fill-color: #d8a8a800;
.rank_myTop {
color: #9a5612;
text-shadow: -2px -2px 0 #fff033;
font-size: 2rem;
}
}
}
.rank{
height: 300px;
overflow-y: auto;
padding: 5px 18px;
.rank-active{
margin-top: 10px!important;
margin-bottom: 10px!important;
span{
font-size: 1.25rem!important;
}
}
.rank-row {
margin-top: 5px;
margin-left: 5px;
color: #bb5b15;
font-weight: bold;
img {
width: 28px;
height: 28px;
vertical-align: middle;
border-radius: 50%;
position: relative;
top: 0;
margin-left: 4px;
}
span {
display: inline-block;
}
.rank-score {
padding-left: 3px;
width: 58px;
text-align: right;
padding-right: 3px;
border-left: 2px solid #ce7e61;
color: #c56a09;
font-weight: bold;
}
.rank-name {
width: 115px;
text-align: left;
padding-left: 7px;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
position: relative;
top: 3px;
}
}
}
.my_rank,.my_money{
font-size: 1.4rem;
font-weight: bold;
text-align: center;
height: 43px;
background-size: 87%;
}
}
}
}
}
.opt {
position: absolute;
top: 15px;
left: 15px;
z-index: 1001;
font-size: 1.4rem;
.back_ico {
width: 50px;
background: url("@/assets/images/back_ico.png") no-repeat center;
background-size: contain;
display: inline-block;
padding-top: 41px;
font-weight: bold;
color: #fdbe22;
}
.rank_ico {
width: 50px;
background: url("cd /mnt/zctq/game/rank_ico.png") no-repeat center;
background-size: contain;
padding-top: 41px;
display: inline-block;
font-weight: bold;
color: #fdbe22;
}
}
}
</style>
pc服务端
<!-- eslint-disable no-alert -->
<!-- eslint-disable no-alert -->
<template>
<div class="container" id="container">
<div id="shu-money" class="shu-money">
<!-- 门帘 -->
<div class="shu-money-curtain"></div>
<!--飘钱-->
<div id="leafContainer" v-if="playStatus !== 1">
<div
style="top: -15%; left: 73%; animation-name: fade, drop; animation-duration: 5.55652s, 5.55652s; animation-delay: 0.34065s, 0.34065s;">
<img src="@/assets/images/realLeaf2.png" style="animation-name: clockwiseSpin; animation-duration: 4.71845s;">
</div>
<div
style="top: -15%; left: 43%; animation-name: fade, drop; animation-duration: 6.24451s, 6.24451s; animation-delay: 1.19191s, 1.19191s;">
<img src="@/assets/images/realLeaf3.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 5.4802s;">
</div>
<div
style="top: -15%; left: 94%; animation-name: fade, drop; animation-duration: 6.0655s, 6.0655s; animation-delay: 4.09718s, 4.09718s;">
<img src="@/assets/images/realLeaf4.png" style="animation-name: clockwiseSpin; animation-duration: 7.04969s;">
</div>
<div
style="top: -15%; left: 79%; animation-name: fade, drop; animation-duration: 5.61894s, 5.61894s; animation-delay: 4.42144s, 4.42144s;">
<img src="@/assets/images/realLeaf4.png" style="animation-name: clockwiseSpin; animation-duration: 7.69046s;">
</div>
<div
style="top: -15%; left: 66%; animation-name: fade, drop; animation-duration: 8.84404s, 8.84404s; animation-delay: 4.98969s, 4.98969s;">
<img src="@/assets/images/realLeaf1.png" style="animation-name: clockwiseSpin; animation-duration: 7.70195s;">
</div>
<div
style="top: -15%; left: 40%; animation-name: fade, drop; animation-duration: 9.01992s, 9.01992s; animation-delay: 0.744s, 0.744s;">
<img src="@/assets/images/realLeaf2.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 4.07854s;">
</div>
<div
style="top: -15%; left: 90%; animation-name: fade, drop; animation-duration: 8.0395s, 8.0395s; animation-delay: 2.08446s, 2.08446s;">
<img src="@/assets/images/realLeaf3.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 5.32582s;">
</div>
<div
style="top: -15%; left: 18%; animation-name: fade, drop; animation-duration: 9.71313s, 9.71313s; animation-delay: 2.77519s, 2.77519s;">
<img src="@/assets/images/realLeaf3.png" style="animation-name: clockwiseSpin; animation-duration: 5.03659s;">
</div>
<div
style="top: -15%; left: 59%; animation-name: fade, drop; animation-duration: 5.23788s, 5.23788s; animation-delay: 4.55604s, 4.55604s;">
<img src="@/assets/images/realLeaf1.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 7.3365s;">
</div>
<div
style="top: -15%; left: 66%; animation-name: fade, drop; animation-duration: 10.4667s, 10.4667s; animation-delay: 3.90653s, 3.90653s;">
<img src="@/assets/images/realLeaf2.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 6.4902s;">
</div>
<div
style="top: -15%; left: 29%; animation-name: fade, drop; animation-duration: 9.36064s, 9.36064s; animation-delay: 1.39082s, 1.39082s;">
<img src="@/assets/images/realLeaf4.png" style="animation-name: clockwiseSpin; animation-duration: 5.90662s;">
</div>
<div
style="top: -15%; left: 34%; animation-name: fade, drop; animation-duration: 5.75967s, 5.75967s; animation-delay: 2.69622s, 2.69622s;">
<img src="@/assets/images/realLeaf2.png" style="animation-name: clockwiseSpin; animation-duration: 4.10586s;">
</div>
<div
style="top: -15%; left: 11%; animation-name: fade, drop; animation-duration: 6.39992s, 6.39992s; animation-delay: 1.7334s, 1.7334s;">
<img src="@/assets/images/realLeaf1.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 5.01956s;">
</div>
<div
style="top: -15%; left: 51%; animation-name: fade, drop; animation-duration: 9.27916s, 9.27916s; animation-delay: 4.90076s, 4.90076s;">
<img src="@/assets/images/realLeaf3.png" style="animation-name: clockwiseSpin; animation-duration: 6.13165s;">
</div>
<div
style="top: -15%; left: 75%; animation-name: fade, drop; animation-duration: 7.84955s, 7.84955s; animation-delay: 2.18257s, 2.18257s;">
<img src="@/assets/images/realLeaf1.png" style="animation-name: clockwiseSpin; animation-duration: 7.25751s;">
</div>
<div
style="top: -15%; left: 70%; animation-name: fade, drop; animation-duration: 9.56084s, 9.56084s; animation-delay: 2.74761s, 2.74761s;">
<img src="@/assets/images/realLeaf1.png" style="animation-name: clockwiseSpin; animation-duration: 4.97211s;">
</div>
<div
style="top: -15%; left: 63%; animation-name: fade, drop; animation-duration: 7.37261s, 7.37261s; animation-delay: 4.42492s, 4.42492s;">
<img src="@/assets/images/realLeaf1.png" style="animation-name: clockwiseSpin; animation-duration: 6.98456s;">
</div>
<div
style="top: -15%; left: 97%; animation-name: fade, drop; animation-duration: 6.81612s, 6.81612s; animation-delay: 2.50155s, 2.50155s;">
<img src="@/assets/images/realLeaf4.png"
style="animation-name: counterclockwiseSpinAndFlip; animation-duration: 5.5112s;">
</div>
</div>
<!-- <div class="SecondRound" v-if="playStatus == 1">
<div class="game_SecondRound_div">
<div class="game_SecondRound_style">
第 <span class="game_SecondRound">{{ playCount }}</span> 轮
</div>
</div>
</div> -->
<div class="shu-rank-list">
<div class="shu-rank-item" v-for="(items,index) in readyList" :key="items.openId">
<div class="shu-rank-item-info" v-if="Number(items.scores) > 0">
<span class="shu-rank-item-score">{{ items.scores?items.scores:0 }}</span>
<p class="shu-rank-item-name">{{ items.nickName?items.nickName:'' }}</p>
<img :src="items.headimgurl">
<span class="ranking">{{ index + 1 }}</span>
</div>
<div class="shu-rank-item-head"></div>
<div class="shu-rank-item-body"></div>
<div class="shu-rank-item-desk"></div>
<div class="shu-rank-item-footer"></div>
</div>
</div>
<div class="number-ani-box" v-if="timeShow && !gameOver">
<img v-if="countDownNum == 30" src="@/assets/images/03.png" class="img-num imgNumberImg">
<img v-else-if="countDownNum <30&&countDownNum >19" src="@/assets/images/02.png" class="img-num imgNumberImg">
<img v-else-if="countDownNum <20&&countDownNum >9" src="@/assets/images/01.png" class="img-num imgNumberImg">
<img v-else src="@/assets/images/00.png" class="img-num imgNumberImg">
<img v-if="countDownNum == 29||countDownNum == 19||countDownNum == 9" src="@/assets/images/09.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 28||countDownNum == 18||countDownNum == 8" src="@/assets/images/08.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 27||countDownNum == 17||countDownNum == 7" src="@/assets/images/07.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 26||countDownNum == 16||countDownNum == 6" src="@/assets/images/06.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 25||countDownNum == 15||countDownNum == 5" src="@/assets/images/05.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 24||countDownNum == 14||countDownNum == 4" src="@/assets/images/04.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 23||countDownNum == 13||countDownNum == 3" src="@/assets/images/03.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 22||countDownNum == 12||countDownNum == 2" src="@/assets/images/02.png" class="img-num imgNumberImg2">
<img v-else-if="countDownNum == 21||countDownNum == 11||countDownNum == 1" src="@/assets/images/01.png" class="img-num imgNumberImg2">
<img v-else src="@/assets/images/00.png" class="img-num imgNumberImg2">
</div>
<div class="box-end" v-if="gameOver"></div>
<!-- 准备游戏 -->
<div class="game-cover-man" v-if="playStatus == 1">
<div class="game-cover-manTop">
<img src="@/assets/images/new-back-topbs.png">
</div>
<div class="game-cover-manCircleDiv">
<div class="game-cover-manCircle">
</div>
</div>
<div class="game-cover-manBottom"></div>
<div class="game-cover-div">
<div class="cover-box">
<div class="circle-light circle-light1"></div>
<div class="ribbon-flag"></div>
<div class="red-lefthand red-hand1"></div>
<div class="red-righthand red-hand1"></div>
<div class="red-build"></div>
<div class="glass-light"></div>
<div class="dai-left red-hand1"></div>
<div class="dai-right red-hand1"></div>
<div class="icon-coin1"></div>
<div class="icon-coin2"></div>
<div class="icon-coin3"></div>
</div>
<div class="game-coverTextDiv">
<div class="game-coverTitle">
<span class="game-coverTitleSpan">疯狂数钞票</span>
<span class="game-coverTitleSpan2">疯狂数钞票</span>
</div>
</div>
</div>
</div>
<!-- 开始游戏 -->
<div class="game-waiting-container" v-if="playStatus == 2">
<div class="game-waiting-body">
<div class="player-txt"></div>
<div class="player-count">{{ readyList.length }}</div>
<div class="player-box" style="overflow-x: auto;overflow-y:hidden">
<span v-for="(item,index) in readyList" :key="item.openId" class="waiting-box" :style="{left: 114*Number(index)+'px',opacity: 1}">
<img :src="item.headimgurl">
</span>
</div>
<div class="game-waiting-title">
<div class="game-w-title" data-text="疯狂数钞票">疯狂数钞票</div>
</div>
<!-- <div class="game-waiting-note">
<div class="game-w-note"></div>
</div> -->
</div>
</div>
<div class="winner-container" v-if="gameOver">
<div class="winner-body">
<div class="box-title animate__animated animate__backInDown">
<div class="title animate__animated animate__bounceIn animate__delay-1s"></div>
</div>
<div class="list-win-box">
<div class="list-item">
<div v-for="(items,index) in readyList" :key="items.openId" class="box-win" style="opacity: 1;">
<span class="name a" >{{ items.nickName }}</span>
<img class="a" alt="" :src="items.headimgurl" >
<div class="border a" style="">{{ index + 1 }}</div>
<span class="score a" style="">得分:<span class="score-num">{{ items.scores }}</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="game-countdown-divs-bg" v-if="playStatus == 3 && !timeShow && !gameOver">
<div class="game-countdown-divs">
<div class="game-titles-content">疯狂数钞票</div>
<div class="game-titles">疯狂数钞票</div>
<div class="wait-time" style="opacity: 1; transform: scale(1, 1);">
<img src="@/assets/images/ready.png" v-if="readySrc == 0">
<img src="@/assets/images/3.png" v-else-if="readySrc == 1">
<img src="@/assets/images/2.png" v-else-if="readySrc == 2">
<img src="@/assets/images/1.png" v-else-if="readySrc == 3">
<img src="@/assets/images/go.png" v-else-if="readySrc == 4">
</div>'
<div class="wait-num-name"></div>
</div>
</div>
<div class="hd-game-btn-container" v-if="playStatus == 1">
<div class="hd-game-btn" @click.stop="setFullScreen()">
<i class="iconfont icon-expand"></i>
<span>全屏</span>
</div>
<div class="hd-game-btn" @click.stop="readyGame()">
<i class="iconfont icon-go"></i>
<span>准备</span>
</div>
</div>
<div class="hd-game-btn-container" v-if="playStatus == 2">
<div class="hd-game-btn" @click.stop="setFullScreen()">
<i class="iconfont tools-ico icon-expand"></i>
<span>全屏</span>
</div>
<div class="hd-game-btn" @click.stop="startGame()">
<i class="iconfont icon-go"></i>
<span>开始</span>
</div>
</div>
<div class="hd-game-btn-container" v-if="playStatus == 3 && !timeShow && gameOver">
<!-- <div class="hd-game-btn" @click.stop="rePlayGame()">
<i class="iconfont icon-refresh"></i>
<span>再玩</span>
</div> -->
<div class="hd-game-btn" @click.stop="setFullScreen()">
<i class="iconfont tools-ico icon-expand"></i>
<span>全屏</span>
</div>
<div class="hd-game-btn" @click.stop="resetGame()">
<i class="iconfont icon-lajitong"></i>
<span>重置</span>
</div>
</div>
</div>
<span v-if="playStatus==1" style="writing-mode: vertical-lr;
position: relative;
z-index: 999;
color: #9975b3;
font-size: 50px;
top: 37%;
left: 20%;">众诚天麒</span>
<span v-if="playStatus==1" style="writing-mode: vertical-lr;
position: relative;
z-index: 999;
color: #9975b3;
font-size: 50px;
top: 37%;
left: 72%;">小麒物联</span>
<div class="qr_code" style="display: block;" v-if="playStatus!=3">
<div class="qr_movediv" v-drag
oncontextmenu="return false;"
onselectstart="return false;">
<div class="qr_code_img">
<img src="@/assets/images/game.png" style="width: 154px;height: 154px;" alt="">
</div>
<span style="color: #fff;
width: 154px;
font-size: 30px;
display: inline-block;
text-align-last: justify;">小麒物联</span>
</div>
</div>
<img src="@/assets/images/logo.png" style="width: 200px;height: auto;position: absolute;
z-index: 999;
right: 50px;top: 50px;" alt="">
</div>
</template>
<script setup lang="ts">
import screenfull from 'screenfull'
const wsUrl = 'xxx'
const playCount = ref(1)
const playStatus = ref(1)
const readySrc = ref(0)
const timeShow = ref(false)
const countDownNum = ref(30)
const gameOver = ref(false)
const readyList = ref([])
// eslint-disable-next-line no-var
let websocket = null
let timer = null
// eslint-disable-next-line consistent-return
const setFullScreen = () => {
//screenfull.isEnabled 此方法返回布尔值,判断当前能不能进入全屏
if (!screenfull.isEnabled) {
return false
}
//screenfull.toggle 此方法是执行全屏化操作。如果已是全屏状态,则退出全屏
screenfull.toggle()
}
//获取随机数
const randomNum = (length = 32) => {//默认32位
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
let num = '';
for (let i = 0; i < length; i++) {
num += arr[parseInt(Math.random() * arr.length)];
}
return num;
}
watch(readySrc, (newVal) => {
if (newVal === 4) {
setTimeout(() => {
timeShow.value = true
countDownNum.value = 30
for (let index = 0; index < 31; index++) {
setTimeout(() => {
countDownNum.value = 30 - index
}, index * 1000);
}
}, 1000);
}
})
watch(countDownNum, (newVal) => {
if (newVal === 0) {
setTimeout(() => {
gameOver.value = true
timeShow.value = false
clearInterval(timer);
timer = null
}, 1000);
}
})
//准备按钮
const readyGame = () => {
readyList.value = []
playStatus.value = 2
const websocket = new WebSocket(wsUrl, "943305991471");
websocket.onopen = function () {
timer = setInterval(function () {
if (playStatus.value === 3) {
clearInterval(timer);//如果距离顶部距离为0 清除定时器
}
websocket.send(JSON.stringify({ msgId: randomNum(32), messageType: 9, msgPayload: "", openId: '943305991471' }))
}, 2000);
}
websocket.onmessage = function (event) {
const eventInfo = JSON.parse(event.data)
if (eventInfo.messageType === 8) {
const list = JSON.parse(JSON.parse(event.data).msgPayload)
if(list.length < 11) {
readyList.value = JSON.parse(JSON.parse(event.data).msgPayload)
}else{
readyList.value = list.slice(0, 10)
}
}
}
}
//开始按钮
const startGame = () => {
const websocket = new WebSocket(wsUrl, "943305991471");
websocket.onopen = function () {
websocket.send(JSON.stringify({ msgId: randomNum(32), messageType: 5, msgPayload: "", openId: '943305991471' }))
}
websocket.onmessage = function (event) {
const eventInfo = JSON.parse(event.data)
if (eventInfo.messageType === 8) {
const list = JSON.parse(JSON.parse(event.data).msgPayload)
if(list.length < 11) {
readyList.value = JSON.parse(JSON.parse(event.data).msgPayload)
}else{
readyList.value = list.slice(0, 10)
}
}
}
playStatus.value = 3
clearInterval(timer);
timer = null
for (let index = 0; index < 5; index++) {
setTimeout(() => {
readySrc.value = index
}, index * 1000);
}
}
//再玩
// const rePlayGame = () => {
// playCount.value++
// playStatus.value = 1
// gameOver.value = false
// }
//重置
const resetGame = () => {
playStatus.value = 1
playCount.value = 1
gameOver.value = false
}
onMounted(() => {
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket(wsUrl, "943305991471");
} else {
// eslint-disable-next-line no-alert
alert('Not support websocket');
}
websocket.onopen = function () {
setInterval(function () {
websocket.send(JSON.stringify({ msgId: randomNum(32), messageType: 2, msgPayload: "", openId: '943305991471' }));
}, 60000);
}
//连接发生错误的回调方法
websocket.onerror = function () {
// eslint-disable-next-line no-alert
alert("打开连接失败");
};
//接收到消息的回调方法
websocket.onmessage = function (event) {
const eventInfo = JSON.parse(event.data)
console.log('eventInfo898', eventInfo)
}
//连接关闭的回调方法
websocket.onclose = function () {
// eslint-disable-next-line no-alert
// alert("关闭连接成功");
}
//监听窗口关闭事件,当窗口关闭时,主动关闭WebSocket连接
window.onbeforeunload = function () {
websocket.close();
}
})
</script>
<style lang='scss' scoped></style>