1. 實作效果
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNiZpdmLxIzN5UjM1EjM4IDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
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
可以擷取動态的值(-150+speed—— -5 +speed),而
offsetTop
裡每行元素的高度為
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架構
原生js實作别踩白塊
<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>