1. 实现效果
2. 知识点总结
-
最后一行元素的移除时
removeChild
:通过父节点对象调用,用于除去父节点中的指定子节点
调用方法为:main.removeChild(main.childNodes[len - 1]);
removeNode
:被除去节点调用,去除某个节点
remove:
被除去节点调用,去除某个节点
调用方法为:main.childNodes[len - 1].remove();
-
浏览器关闭事件
window.close();
浏览器重启事件window.location.reload(true);
-
offsetTop:元素相对于父元素的高,只能读取,不能设置,没有单位,如果父元素没有设置相对定位,则元素的offset是相对于浏览器的而言的
和style属性的区别:
无论元素有没有设置定位,offset属性都可以返回位置,而style属性不行,只有定位后才能获取
3. 实现功能
- 点击游戏开始按钮后从上至下出现钢琴块,开始按钮隐藏
- 游戏失败后显示弹框:得分,选择退出游戏(关闭浏览器)或者重新开始(刷新浏览器)
- 分数每达到10的倍数则加速
4. 设计思路
- 声明变量
var main = document.getElementById('main');
var go = document.getElementById('go');
var score = document.getElementsByClassName('score')[0];
var restart = document.getElementsByClassName('restart')[0];
var buttonExit = document.getElementsByClassName('exit')[0];
var buttonAgain = document.getElementsByClassName('again')[0];
var speed1 =6;/*控制移动速度*/
var speed2 =100;
var num = 0;/*分数*/
var timer = null;
var flag = true;/*是否可以点击*/
- 创建元素
创建 行元素
div
,每行四个div
,之后动态添加行
随机数(0-4)设置变色块(需要点击的),并添加类名称方便之后调用
// 创建每一行div元素
function creatDiv() {
var rowDiv = document.createElement('div');
rowDiv.className = "row";
for (var j = 0; j < 4; j++) {
var inDiv = document.createElement('div');
rowDiv.appendChild(inDiv);
}
// 插入新生成的行
main.insertBefore(rowDiv, main.childNodes[0]);
var index = Math.floor(Math.random() * 4); // 根据随机数 设置一行中有颜色的div
var clickDiv = main.childNodes[0].childNodes[index];
clickDiv.className = "need";
clickDiv.style.backgroundColor = "black";// 设置上背景颜色
}
- 移动
1.主要问题在于控制
main
部分元素向下移动,利用offsetTop
可以获取动态的值(-150+speed—— -5 +speed),而main
里每行元素的高度为150px
,每新加一行元素,top
的值随之改变,从而实现内容下移
2. 当检测到当前main区域里有6(可视区域4+生成最新的一行+触底后的一行)行时删除最后一行
3)计时器也可以通过刷新来控制速度
// 移动
function move() {
timer = setInterval(function () {
// 利用top值移动main区域
var step = parseInt(main.offsetTop) + speed;
console.log(main.offsetTop);
main.style.top = step + 'px';
// 如果main区域移动到可视区域 创建一行新的元素
if (parseInt(main.offsetTop) >= 0) {
creatDiv();
// 同时将main区域移动到可视区域上方
main.style.top = '-150px';
}
// 获得mian区域内的行数
var len = main.childNodes.length;
if (len == 6) {
// 遍历最后一行的每一个div
for (var i = 0; i < 4; i++) {
// 如果其中有一个包含没有被点击的 游戏结束
if (main.childNodes[len - 1].children[i].className == "need") {
score.innerHTML=num;
restart.style.display="block";
clearInterval(timer);
// 游戏结束后不可以继续点击
flag = false;
}
}
// 将展示过后的每一行移除
/*main.removeChild(main.childNodes[len - 1]);*/
main.childNodes[len - 1].remove();
}
}, speed2)
// 点击事件
bindEvent();
}
- 点击事件
如果选中黑色则计数器+1;如果选择其他区域背景色变为红色,
flag
修改为false
,显示弹框(display:block
)
监听事件监听click,并获取当前点击的对象
function bindEvent() {
// 给main添加点击事件
main.addEventListener('click', function (event) {
// 根据flag值判断是否可以点击
if (flag) {
// 获得到点击的源事件
var tar = event.target;
// 判断点击的块是否为有颜色的
if (tar.className == 'need') {
// 改变背景颜色
tar.style.backgroundColor = '#999';
tar.className = "";
// 计数++
num++;
} else {
// 如果点到了白色的块 游戏结束
tar.style.backgroundColor = 'red';
score.innerHTML=num;
restart.style.display="block";
clearInterval(timer);
flag = false;
}
// 如果当前分数为10的倍数 速度++
if (num % 10 == 0) {
speed++;
}
}
})
}
- 开始点击后开始游戏按钮隐藏,调用move函数
// 开始按钮点击 开始移动 创建每一行元素
clickStart();
function clickStart() {
go.addEventListener('click', function () {
go.style.display = 'none';
move();
});
}
- 弹框按钮功能
buttonExit.onclick=function(){
window.close();/*浏览器关闭事件*/
}
/*重新开始*/
buttonAgain.onclick=function(){
flag=true;
window.location.reload(true);/*浏览器重启事件*/
}
5. 待解决bug
- 没有动态设置移动速度,可以在代码中修改变量speed的值
- 刚开始元素还未填满main的空间,点击其他部分(除钢琴块外)会使所有区域变红
html框架
<div class="wrapper">
<div id="go"><span>Game Start</span></div>
<div id="main"></div>
</div>
<div class="restart">
<div>游戏结束,得分:<span class="score"></span></div>
<button class="exit">退出游戏</button>
<button class="again">再来一局</button>
</div>
css样式
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
margin: 100px auto;
width: 400px;
height: 600px;
position: relative;
border: 1px solid black;
overflow: hidden;
}
#go {
width: 100%;
position: absolute;
top: 0;
text-align: center;
z-index: 99;
}
#go span {
display: block;
height: 100px;
width: 100%;
color: cyan;
border-bottom: 1px solid #000000;
background-color: #b1b1b1;
font-size: 60px;
cursor: pointer;
}
#main {
width: 400px;
height: 600px;
position: relative;
}
.row {
width: 400px;
height: 150px;
}
.row div {
width:100px;
height: 149px;
border-left: 1px solid #222;
border-bottom: 1px solid #222;
float: left;
cursor: pointer;
}
.restart {
width: 500px;
height: 200px;
border: 1px solid #ff0000;
position: relative;
margin: 100px auto;
top: -450px;
background: #ebebeb;
padding-top: 50px;
display: none;
}
.restart div {
font-size: 30px;
width: 498px;
text-align: center;
}
.restart button{
width: 200px;
height: 50px;
border-radius: 5px;
border: 1px solid #b1b1b1;
outline: none;
color: #fca298;
font-size: 30px;
position: absolute;
bottom: 10px;
cursor: pointer;
}
.restart button:nth-of-type(1){
left: 30px;
}
.restart button:nth-of-type(2){
right: 30px;
}
</style>