一段时间没更新,是因为公司下面的子公司移动端开发需要人员去支援,好了,鄙人被派去了,主要完成四个小游戏的H5开发。接着挨个介绍这四个小游戏我是怎么完成的,以下只贴上核心代码文件,想要直接cv运行的话,可能不行嗷,看懂逻辑,自己去改也是一种学习过程!有问题私信我
红包雨
这里的需求:大小红包,点击大红包10分,小红包5分,点击之后还有打开效果,大红包:小红包比例,二比五。我这里采用的是100以内的随机数,2的整除数和5的整除数。
CountdownTimer.vue 倒计数组件,时间到,跳出游戏结束弹框
<template>
<div class="countdown_box">
<p class="countdown">{
{
formattedTime }}s</p>
</div>
</template>
<script>
import {
Bus } from '@/util/bus'
export default {
data() {
return {
timeLeft: 15000, // 总时间(毫秒)
countdownInterval: null,
microsecondIncrement: 0, // 用于模拟微秒增加
Count: 0
}
},
computed: {
formattedTime() {
const seconds = Math.floor(this.timeLeft / 1000)
const milliseconds = Math.floor((this.timeLeft % 1000) / 10)
const microseconds = this.microsecondIncrement % 100
return `${
seconds.toString().padStart(2, '0')}:${
milliseconds
.toString()
.padStart(2, '0')}:${
microseconds.toString().padStart(2, '0')}`
}
},
mounted() {
this.startCountdown()
Bus.$on('Total', Total => {
this.Count = Total
})
},
beforeDestroy() {
this.stopCountdown()
},
methods: {
startCountdown() {
this.countdownInterval = setInterval(() => {
if (this.timeLeft > 0) {
this.timeLeft -= 10 // 每10毫秒减少10毫秒
this.microsecondIncrement++ // 模拟微秒增加
if (this.microsecondIncrement >= 1000) {
this.microsecondIncrement = 0 // 重置微秒模拟
}
} else {
this.stopCountdown()
Bus.$emit('countdownEnd', this.Count)
}
}, 10) // 每10毫秒更新一次时间
},
stopCountdown() {
clearInterval(this.countdownInterval)
}
}
}
</script>
<style lang="less" scoped>
.countdown_box {
text-align: center;
color: red;
.countdown {
font-size: 9vw;
}
}
</style>
index.vue 核心代码
<template>
<div class="rain-wrapper">
<CountdownTimer style="margin-top: 7.0667vw" ref="cutdown"></CountdownTimer>
<div ref="rainBox" id="rainBox" class="rainBox">
<rain-point
v-for="(item, idx) in rains"
:key="`rain-point-${idx}`"
:ref="`rain-point-${idx}`"
@rainPoinclick="rainPoinclick"
></rain-point>
</div>
</div>
</template>
<script>
import rainPoint from './tpl.vue'
import countdown from './countdown'
import CountdownTimer from '../CountdownTimer.vue'
import {
Bus } from '@/util/bus.js'
export default {
name: 'rain',
props: {
density: {
// 雨点创建速度
type: Number,
default: 600
},
delay: {
// 雨点时长
type: Number,
default: 5
},
time: {
// 动画时长(秒)
type: Number,
default: 10
}
},
data() {
return {
count: 0, // 点击统计
rains: [], // 组件列表
rainsCount: 0, // 组件下标
createTimer: null, // 创建雨点计时器
flag: true, // 是否结束
isFiveCount: 0,
isTenCount: 0,
event: ''
}
},
components: {
rainPoint,
CountdownTimer
},
methods: {
// 结束后回调
timeoutCallback() {
this.$emit('timeoutCallback', this.count, this.isFiveCount, this.isTenCount)
},
// 点击雨点
rainPoinclick(e) {
if (!this.flag) return
this.count += 1
if (e.target._prevClass == 'rain-point_small') this.isFiveCount += 1
if (e.target._prevClass == 'rain-point_big') this.isTenCount += 1
Bus.$emit('Total', this.Total)
},
// 生成随机起始与落点坐标
grid() {
let [startX, startY, endX, endY] = [0, 0, 0, 0]
let rects = document.documentElement.getBoundingClientRect()
startX = Math.random() * (rects.width - 20)
startY = -20
endX = Math.random() * (rects.width - 20)
endY = rects.height
return {
startX,
startY,
endX,
endY
}
},
// 随机速度曲线值
newCubicBezier() {
let arr = ['0,.49,1,.3', '.04,.2,.93,.49', '.99,.36,.54,.46'] // 快 中 慢
// let idx = parseInt(Math.random() * 10) > 2 ? 0 : 1
let idx = parseInt(Math.random() * 3)
return arr[idx]
},
// 创建雨点
async create(rainscount) {
// 生成Dom
this.rains.push(`rain-point-${
rainscount}`)
// 生成坐标
let rects = await this.grid()
// 渲染完成后执行
await this.$nextTick(async function () {
// Dom节点
let el = this.$refs[`rain-point-${
rainscount}`][0]
let initStyleText = {
transform: `translate(${
rects.startX}px, ${
rects.startY}px)`
}
let actionStyleText = {
transition: `transform ${
this.delay}s cubic-bezier(${
this.newCubicBezier()})`,
transform: `translate(${
rects.endX}px, ${
rects.endY}px)`
}
// 设置初始坐标
await el.setStyle(initStyleText)
// 设置结束坐标
await setTimeout(() => {
el.setStyle(actionStyleText)
}, 50)
// 动画结束
el.$el.addEventListener('transitionend', el.destory, false)
})
},
// 执行
start() {
// this.$nextTick(() => {
// this.$refs.cutdown.startCountdown()
// })
this.clear()
// 开启雨点点击
this.flag = true
// 重置点击数
this.count = 0
// 清除动画定时器
countdown.clearAssignTimer('rain')
// 动画定时器
countdown.creatTimer({
remainTime: parseInt(this.time) * 1000,
label: 'rain',
timeoutFn: () => {
this.clear()
this.timeoutCallback()
}
})
// 创建节点
this.createTimer = setInterval(async () => {
await this.create(this.rainsCount)
this.rainsCount += 1
}, this.density)
},
// 停止
stop() {
this.flag = false
clearInterval(this.createTimer)
},
// 清空
clear() {
this.stop()
countdown.clearAssignTimer('rain')
this.rains = []
this.rainsCount = 0
}
},
computed: {
Total() {
return this.isFiveCount * 5 + this.isTenCount * 10
}
},
mounted() {
// window.start = this.start
// window.stop = this.stop
// window.clear = this.clear
// this.start()
}
}
</script>
<style>
.rain-wrapper {
width: 100%;
height: 250vw;
/* height: 100%; */
overflow: hidden;
position: relative;
}
.rainBox {
width: 100%;
}
</style>
tpl.vue
<template>
<div class="tyh">
<div
v-if="this.isShow"
@click="rainPoinclick"
:class="[
isClick ? 'action' : '',
this.isEven ? 'rain-point_small' : this.MultiFive ? 'rain-point_small' : 'rain-point_big'
]"
:style="styleText"
>
<transition name="number-fade">
<div class="addNum" v-if="showNumber">
<span>+</span>
<span>{
{
this.isEven ? 5 : this.MultiFive ? 5 : 10 }}</span>
</div>
</transition>
</div>
</div>
</template>
<script>
export default {
name: 'rain-point',
props: {
},
data() {
return {
styleText: {
},
isShow: true,
isClick: false,
// 红包
total: 0,
showNumber: false,
event: ''
}
},
methods: {
rainPoinclick(e) {
this.event = e
if (this.isClick) return
this.isClick = true
this.showNumber = true
// 在动画完成后隐藏数字
this.$nextTick(() => {
setTimeout(() => {
this.showNumber = false
}, 500) // 动画持续时间,与CSS中的transition-duration保持一致
})
this.$emit('rainPoinclick', e)
},
setStyle(params) {
this.styleText = params
},
destory() {
this.isShow = false
},
created() {
}
},
computed: {
isEven() {
return Math.floor(Math.random() * 100 + 1) % 2 === 0
},
MultiFive() {
return Math.floor(Math.random() * 100 + 1) % 10 === 0
}
},
watch: {
}
}
</script>
<style lang="less" scoped>
.tyh {
.rain-point_small {
position: absolute;
width: 51px;
height: 65px;
background-image: url('~@/assets/image/draw/red-envelope-rain/envelope_small.png');
border-radius: 2.5vw;
}
.rain-point_big {
position: absolute;
width: 75px;
height: 95px;
background-image: url('~@/assets/image/draw/red-envelope-rain/envelope_big.png');
border-radius: 2.5vw;
}
.action {
width: 90px;
height: 120px;
background-image: url('~@/assets/image/draw/red-envelope-rain/envelope_open.png');
}
.number-fade-enter-active,
.number-fade-leave-active {
transition: opacity 0.5s;
}
.number-fade-enter,
.number-fade-leave-to {
opacity: 0;
}
.addNum {
font-size: 9vw;
color: red;
position: absolute;
}
}
</style>
打地鼠
倒计时组件和上述红包雨的一样,需要的话自行改造
<template>
<div class="draw-box">
<div v-if="centerDialogVisible" class="cover">
<div class="dialog">
<div class="el-dialog__header">
<div class="title">
{
{
isTrue ? '挑战成功!' : '挑战失败!' }}
</div>
<img
:style="isTrue ? 'top:-31vw' : 'top:-22vw'"
:src="
isTrue
? require('@/assets/image/draw/red-envelope-rain/success.png')
: require('@/assets/image/draw/red-envelope-rain/fail.png')
"
/>
</div>
<div class="el-dialog__body">
<div class="content">
<h1 style="margin-top: 7.7333vw">
您的成绩为:
<span style="color: #fa3e56">{
{
RankCount }}分</span>
</h1>
<span
class="tip"
v-if="!isTrue"
:style="isTrue ? 'margin-bottom: 4vw,margin-top:1.333vw' : ''"
>
成绩必须达到80分才能抽奖
</span>
<div class="divider1"></div>
<div class="the_Best">
<div class="BestGrade" style="margin-right: 6vw">
<span class="text">最佳成绩</span>
<span class="count">{
{
rankBestgrade.bestPoint || RankCount }} 分</span>
</div>
<div class="vertical-divider"></div>
<div class="BestGrade" style="margin-left: 6vw">
<span class="text">最佳排名</span>
<span class="count">NO.{
{
rankBestgrade.ranking || 1 }}</span>
</div>
</div>
<div class="divider2"></div>
<span v-show="isTrue" style="margin-top: 4vw">
今天还有
<span style="color: #fa3e56">{