用键盘事件来消除产生的字母块,这里使用面向对象的思想来使用,未使用Unicode编码。
框架:
<div class="box1">
<button id="start">开始</button>
<button id="stop">暂停</button>
</div>
<div id="box" class="box"></div>
CSS样式:
* {
margin: 0;
padding: 0;
}
.box {
position: relative;
width: 800px;
height: 400px;
margin: 0 auto;
border: 2px solid #ccc;
}
.box1 {
width: 800px;
height: 40px;
margin: 0 auto;
}
JS功能:
<script>
// 用面向对象的思想来写
// 获取元素
let start = document.getElementById('start')
let stop = document.getElementById('stop')
// 构造一个函数来调用原型中的方法并传参方便满足不同的需求
function Demo(id, size, speed) {
// 获取元素的id属性值(这里的id是一个参数 当你调用构造函数时传参进去 这里的id就会变成不同的属性值 比较灵活)
this.box = document.getElementById(id)
// 定义一个类似于变量的东西(这里的this就是这个函数本身,是构造函数的一种机制 默认绑定 不写不行)来储存创建的元素
this.ele = document.createElement('div')
// 随机产生26个字母中的任意一个
this.text = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' [parseInt(Math.random() * 26)]
// 可以更改的元素大小
this.size = size
// 元素每次的运动布距
this.speed = speed
// 把定义的方法放入函数中执行
this.random()
this.uptree()
}
// 在构造函数Demo的原型下书写方法
Demo.prototype = {
// 将原先Demo函数中的原型中的方法重新获取回来(如果不重新获取就会被你新添加的方法替代所以需要重新获取回来)
constructor: Demo,
// 定义一个产生随机数的方法
random() {
// 给定义的元素this.ele添加样式
this.ele.style.width = this.size + 'px'
this.ele.style.height = this.size + 'px'
this.ele.style.position = 'absolute'
// 随即获取颜色
this.ele.style.backgroundColor = 'rgba(' + parseInt(Math.random() * 256) + ',' + parseInt(Math
.random() * 256) + ',' + parseInt(Math.random() * 256) + parseInt(Math.random()) + ')'
this.ele.style.textAlign = 'center'
this.ele.style.lineHeight = this.size + 'px'
this.ele.style.left = 0
// 让上面构造函数中随机产生的字母书写到创建的元素中并书写到页面上
this.ele.innerHTML = this.text
// 让新创建的元素在大盒子中随机位置出现
// 大盒子的自身高度减去新建元素的大小
this.ele.style.top = parseInt(Math.random() * (this.box.clientHeight - this.size)) + 'px'
},
// 定义一个运动方法
move() {
// 定义运动距离(创建的元素到父元素的左间距加上运动间距,因为每次运动完之后到父元素的左间距都在发生变化)
this.ele.style.left = this.ele.offsetLeft + this.speed + 'px'
},
// 定义上树方法
uptree() {
// 将创建的元素上树
this.box.appendChild(this.ele)
},
// 定义下数方法
downtree() {
// 将创建的元素下树
this.box.removeChild(this.ele)
}
}
// 定义一个新数组来储存上方创建的每一个构造函数(包含所有样式和移动数据及方法)
let arr = []
// 因为要累计所以定义一个变量初始值为0
// (至于为啥要定义这个是因为 下方定时器定义的时间为20毫秒一次 但是不能让元素每20毫秒产生一个所以只能用这种计数的方法来让时间加到1000毫秒)
//每1000毫秒产生一个元素时,此时i的值是50
let i = 0
// 将定时器设置初始值为空,这样就可以再点击事件函数中更改此变量的值
let timer = null
// 给开始按钮绑定点击事件
start.onclick = function () {
// 将timer的值改为定时器
timer = setInterval(function () {
// 定时器每开一次就加一
i++
// 判定 如果当i的值累加到50时,此时时间为1000毫秒也就是一秒钟 让判定条件%50===0时调用构造函数,这时就会每一秒钟产生一个元素
if (i % 50 === 0) {
// 定义一个变量来执行这个构造函数并传参
var h = new Demo('box', 50, 2)
// 将每秒钟得到的构造函数填充进空数组中
arr.push(h)
}
// 遍历包含构造函数的数组
arr.forEach(value => {
// 调用运动方法(将每一个成员也就是每一个构造函数运动起来)
value.move()
})
}, 20)
}
// 给停止按钮绑定点击事件用来清除定时器
stop.onclick = () => {
clearInterval(timer)
}
// 绑定键盘事件用来完成游戏要求
document.onkeydown = e => {
// 定义一个变量来储存当按下键盘相应键时的值(将它们转为大写是因为上面随机生成的字母为大写字母)
var key = e.key.toUpperCase()
// 循环构造函数数组
for (var i = 0; i < arr.length; i++) {
// 判定按下的键盘值是否等于数组中每个构造函数的字母
if (key === arr[i].text) {
// 如果相等就下树并且从数组中删除(如果不删除的话虽然页面中没有了但数组中会越来越多 占据内存)
arr[i].downtree()
arr.splice(i, 1)
// 跳出循环
break
}
}
}
</script>