html+vue+vant 接雨滴小游戏。
倒计时3秒后,开始15秒接雨滴游戏,通过点击水滴获得水滴。
效果如下:
接雨滴小游戏.gif
问题:
ios
不能自动播放bgm
?
解决:ios
内置浏览器不允许自动播放音乐,需通过WeixinJSBridgeReady()
实现自动触发。连续点击水滴,点击音效只触发一次,之后不生效(同时播放多种音效)?
解决:不使用audio组件,使用AudioContext
,生成音频实例。点击水滴后消失,添加‘+1’效果?
解决:找到所点击的水滴元素添加样式,100ms后移除document.getElementById(`li${index}`).classList.add("disappear"); setTimeout(() => { document.getElementById(`li${index}`).remove(); // 点击后移除 }, 100);
h5
长按点击出现保存到本地等信息?
解决:在所需要禁用该功能的图片上添加css属性:pointer-events: none;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no,viewport-fit=cover" />
<meta content="yes" name="apple-mobile-web-app-capable" />
<meta content="black" name="apple-mobile-web-app-status-bar-style" />
<title>接雨滴游戏</title>
<link rel="stylesheet" href="https://unpkg.com/vant@2.12/lib/index.css"/>
<style>
[v-cloak] {
display: none;
}
* {
margin: 0;
padding: 0;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
/* webkit是苹果浏览器引擎,tap点击,highlight背景高亮,color颜色,颜色用数值调节。 */
}
#app {
width: 100vw;
height: 100vh;
overflow: scroll;
background: #383e37;
}
.bg {
position: relative;
width: 100%;
height: 100%;
background-image: linear-gradient(#1c0476,
#2833c4,
#3558f0,
#5f94fe,
#8399fd,
#f5c6ed,
#faeefa);
overflow: hidden;
}
.drop {
-webkit-animation: aim_drop 5s linear 1 forwards;
animation: aim_drop 5s linear 1 forwards;
}
@keyframes aim_drop {
0% {
-webkit-transform: translateY(0);
transform: translateY(0);
}
100% {
-webkit-transform: translateY(120vh);
transform: translateY(120vh);
}
}
.ser_home {
width: 100%;
height: 100%;
}
.drop_rain{
display: block;
position: relative;
overflow: hidden;
width: 100%;
height: 100%;
}
li {
position: absolute;
animation: all 3s linear;
top: -100px;
z-index: 10;
list-style: none;
width: 47px;
height: 74px;
display: block;
background: url("./images/drop.png") no-repeat;
}
.count_animation {
width: 100%;
text-align: center;
color: #fff;
animation: animation 1s linear 5;
animation-fill-mode: forwards;
}
@keyframes animation {
0% {
font-size: 10rem;
opacity: 1;
}
100% {
font-size: 8rem;
opacity: 0;
}
}
.flex {
position: relative;
top: 20px;
display: flex;
justify-content: space-between;
align-items: center;
color: #fff;
font-weight: bold;
}
.info {
width: 60px;
padding: 10px 20px;
text-align: center;
font-size: 14px;
z-index: 99;
}
.left {
color: #fff;
background-image: linear-gradient(#4ac3fa, #368ff3);
border-radius: 0 20px 35px 5px;
box-shadow: 0px 3px 2px #52dafc;
}
.right {
color: #9791e3;
background-image: linear-gradient(#fcf8fe, #e5cded);
border-radius: 20px 0 5px 35px;
box-shadow: 0px 3px 2px #e7d6f8;
}
.text {
font-size: 24px;
}
.disappear {
opacity: 0.5;
}
.disappear::before {
content: "+1";
color: #fff;
font-size: 1rem;
}
img {
pointer-events: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<div class="bg">
<!-- 3s倒计时bgm -->
<audio src="bgm1.mp3" controls canplaythrough hidden preload id="audioCountdown" ref="audioCountdown"></audio>
<!-- 游戏bgm -->
<audio src="bgm2.mp3" controls canplaythrough hidden preload loop id="audioGame" ref="audioGame"></audio>
<div class="flex">
<div class="info left">
<div>获得水滴</div>
<div class="text">{{ clickNum }}g</div>
</div>
<div class="info right">
<div>剩余时间</div>
<div class="text">{{ count_15 }}s</div>
</div>
</div>
<!-- 倒计时3s -->
<div v-if="countDownTimer_3" style="text-align: center">
<span class="count_animation">{{ count_3 }}</span>
</div>
<template v-else>
<div class="ser_home">
<ul class="drop_rain" id="drop_rain">
<template v-for="(item, index) in liParams">
<li
:id="`li${index}`"
:style="{ left: item.left, animationDuration: item.durTime, webkitAnimationDuration: item.durTime}"
:class="item.cls"
:data-index="index"
@webkitAnimationEnd="removeDom"
@click="touch(index)">
</li>
</template>
</ul>
</div>
</template>
</div>
</div>
<script src="https://unpkg.com/vue@2.6/dist/vue.min.js"></script>
<script src="https://unpkg.com/vant@2.12/lib/vant.min.js"></script>
<script>
window.onload = () => {
// 兼容低版本系统
var AudioContext = window.AudioContext || window.webkitAudioContext;
var audioContext = new AudioContext()
new Vue({
el: "#app",
data() {
return {
liParams: [],
timer: null,
duration: 15000, // 定义游戏时间15s
countDownTimer_3: null,
count_3: 0,
countDownTimer_15: null,
count_15: 15,
clickNum: 0,
AudioSource: {}
};
},
created() {
},
mounted() {
this.countDown_3();
},
methods: {
countDown_3() {
this.audioAutoPlay('audioCountdown') // 倒计时bgm开始
const TIME_COUNT = 3;
if (!this.countDownTimer_3) {
this.count_3 = TIME_COUNT;
this.countDownTimer_3 = setInterval(() => {
if (this.count_3 > 1 && this.count_3 <= TIME_COUNT) {
// 限制倒计时区间
this.count_3--;
} else {
clearInterval(this.countDownTimer_3); // 删除定时器
this.countDownTimer_3 = null;
this.count_3 = 0;
this.audioAutoPlay('audioGame') // bgm播放
this.countDown_15(); // 15s倒计时开始
this.startGame();
}
}, 1000);
}
},
// 15s倒计时
countDown_15() {
const TIME_COUNT = 15;
if (!this.countDownTimer_15) {
this.count_15 = TIME_COUNT;
this.countDownTimer_15 = setInterval(() => {
if (this.count_15 > 1 && this.count_15 <= TIME_COUNT) {
// 限制倒计时区间
this.count_15--;
} else {
clearInterval(this.countDownTimer_15); // 删除定时器
this.countDownTimer_15 = null;
this.count_15 = 0;
setTimeout(() => {
this.sumitResult(); // 提交成绩
}, 2000);
}
}, 1000);
}
},
// 点击水滴
touch(index) {
this.play('bgm3') // 点击音效
this.clickNum++;
document.getElementById(`li${index}`).classList.add("disappear");
setTimeout(() => {
document.getElementById(`li${index}`).remove(); // 点击后移除
}, 100);
},
/**
* 开启游戏动画
*/
startGame() {
let win = document.documentElement.clientWidth || document.body.clientWidth;
let left = parseInt(Math.random() * (win - 50) + 0);
let durTime = Math.random() * 2 + 3.2 + "s"; // 下落速度
this.liParams.push({
left: left + "px",
cls: "drop",
durTime: durTime,
});
setTimeout(() => {
// 多少时间结束
clearTimeout(this.timer);
return;
}, this.duration);
this.timer = setTimeout(() => {
this.startGame();
}, 300);
},
/**
* 回收dom节点
*/
removeDom(e) {
let target = e.currentTarget;
document.querySelector("#drop_rain").removeChild(target);
},
sumitResult() {
this.$dialog({
title: "游戏结束",
message: `恭喜你获得了<span style="color: red;font-size: 2rem;">${this.clickNum}g</span>水滴~`,
});
this.audioAutoPause('audioGame') // 暂停bgm
},
// 音频播放
async play(music) {
let source = audioContext.createBufferSource()
if (!this.AudioSource[music]) {
const res = await fetch(`${music}.mp3`)
const arraybuffer = await res.arrayBuffer() // 获取arraybuffer文件流
const audioBuffer = await audioContext.decodeAudioData(arraybuffer)
this.AudioSource[music] = audioBuffer;
}
source.connect(audioContext.destination) //连接上实例
source.buffer = this.AudioSource[music]
source.start()
},
// 播放bgm
audioAutoPlay(id) {
var audio = document.getElementById(id)
play = function () {
setTimeout(function () {
audio.play();
}, 200);
document.removeEventListener('touchstart', play, false);
}
audio.load()
setTimeout(function () {
audio.play();
}, 200);
// 监听在微信浏览器中页面加载完毕触发
document.addEventListener('WeixinJSBridgeReady', function () {
play();
}, false);
// 监听用户触摸到页面后触发
document.addEventListener('touchstart', play, false);
},
// 暂停bgm
audioAutoPause(id) {
var audio = document.getElementById(id),
pause = function () {
audio.pause();
document.removeEventListener('touchstart', pause, false);
};
audio.pause();
document.addEventListener('WeixinJSBridgeReady', function () {
pause();
}, false);
document.addEventListener('touchstart', pause, false);
}
},
});
};
</script>
</body>
</html>