tags: javascript
在B站中看见了一个JS大气球这么一个教程,才知道原来JS+HTML5+CSS3能那么有趣。但是视频中没并没有给出源码。于是在别人的博客中搜到了对应的源码以及他自己实现的思路,该博主对其进行了改编。
http://www.cnblogs.com/morang/p/7636148.html
以上的博文有源码的下载。下面我就直接贴上源码了。思路就在博文中。
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
<head>
<title>气球大战</title>
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0">
<style>
/*CSS3能够将气球描绘出来,使用到了圆形、旋转、阴影等技术*/
body{margin:0px;padding:0px;}
#ballDiv{position: fixed;top: 0;left: 0;}
.balloon{
width:150px;
height:150px;
position:absolute;
left:0px;
top:0px;
background-color:#f3778d;
border-radius:50% 50% 10% 50%;
transform:rotate(45deg);
box-shadow:1px 1px 20px 20px pink inset;
z-index:10;
}
/*这里使用到了伪元素,可以不用到html中定义元素就可以实现功能了!*/
.balloon:after{
width:20px;
height:20px;
content:"";
display:block;
background:transparent;
position:absolute;
right: -15px;
bottom: -15px;
border-left:5px solid pink;
border-top:5px solid pink;
}
/*这里使用到了伪元素,可以不用到html中定义元素就可以实现功能了!*/
.balloon:before{
width: 2px;
height: 50px;
content: "";
display: block;
background: #ffc0cb;
position: absolute;
right: -10px;
top: 100%;
margin-top: -16px;
transform: rotate(-45deg);
}
</style>
</head>
<body>
<div id="gameinfo" style="transform: translateZ(360px);">
<p>
最高连击:<span id='maxDoubleHit'>0</span>
</p>
<p>
本次游戏:<span id='currentDoubleHit'>0</span>
</p>
<p id="gamemsg" style="display:none;">
<span style="color:red;font-weight:bold;">
Game Over
</span>
<button onclick="javscript:location.reload();">
重新开始
</button>
</p>
</div>
<div id="ballDiv">
</div>
<!--<div class="balloon"></div>-->
<script>
var maxDoubleHit=localStorage.getItem('eliminateCount')||0
var currentDoubleHit=0
//当做一个缓存池,优化性能的。
var bnElements=[];//存放所有气球
var random=Math.random;//随机函数
var wW=window.innerWidth;//窗口宽度
var wH=window.innerHeight;//窗口高度
var ballW=160;//气球的宽度
var ballH=300;//气球的宽度
var minSpeed=3;//最小速度,每次向上移动至少3px
var speedNum=5;//速度的定量
var defBnNumber=5;//初始化气球
var moveTimer;
var isEnd=false;
var jindex=1;
var ballDiv=document.getElementById('ballDiv');
//初始化
init(defBnNumber);
//移动
move();
//绑定单击事件
bindClick();
//游戏信息
document.getElementById('maxDoubleHit').innerText=maxDoubleHit
function record(){
if(isEnd){
clearTimeout(moveTimer);
bnElements=[];
document.getElementById('gamemsg').style.display='block';
document.getElementById('gameinfo').style='transform: translateZ(360px);position: fixed;top:0;left:0;z-index:999';
}
else{
init(1);
document.getElementById('currentDoubleHit').innerText=++currentDoubleHit;
if(currentDoubleHit>maxDoubleHit){
document.getElementById('maxDoubleHit').innerText=currentDoubleHit;
localStorage.setItem('eliminateCount',currentDoubleHit)
}
}
}
//初始化气球
function init(num){
//创建一个虚拟文档节点
var docFragment=document.createDocumentFragment();
for(var i=0;i<num;i++){
var bnElement=document.createElement('div');
bnElement.className='balloon';
//速度随机,限定最小值
var speed=Math.max(minSpeed,~~(random()*speedNum));
bnElement.setAttribute('speed',speed);//~~取整 移动速度
bnElement.setAttribute('id','ball-'+jindex++);
//分散排列
var x=(~~(random()*wW))-ballW;
x=Math.max(0,x);
bnElement.style.left=x+'px';
bnElement.style.top=wH+'px';//露一点出来
//1.先将创建的气球放入创建的虚拟文档节点
docFragment.appendChild(bnElement);
bnElements.push(bnElement);
}
//2.将虚拟文档节点添加到body中
ballDiv.appendChild(docFragment);
}
//使用定时器来对气球进行移动。
function move(){
var bl=bnElements.length
for(var i=0;i<bl;i++){
var currentElement=bnElements[i]
if(currentElement==null){
continue;
}
var offsetTop=currentElement.offsetTop;
if(offsetTop>0){//窗口中
//offset就是针对窗口的位置来进行移动的。
var speed=currentElement.getAttribute('speed');
currentElement.style.top=offsetTop-speed+'px'
}
else{
//移除dom节点
//ballDiv.removeChild(currentElement);
//移除数组中
//bnElements.splice(i,1);
//init(1);
isEnd=true;
record();
}
}
moveTimer=setTimeout(move,1000/30);
}
//对所有的气球进行单击监听事件,不要单独为每个气球来进行监听,这样耗费性能!
function bindClick(){
ballDiv.addEventListener('click',clickFunc,false);
function clickFunc(e){
if(!isEnd && e.target.className=='balloon'){
bnElements.splice(bnElements.lastIndexOf(e.target),1);
//这里使用call主动调用,在boom方法中我们就可以使用this指针了。
boom.call(e.target,function(){
e.target.parentNode.removeChild(e.target);
record();
});
}
}
}
function boom(callback){
//var that=this; //替换了上下文,但是没有使用this的意义.
var speed=this.getAttribute('speed');
this.timer=setInterval(function(){
this.style.opacity=0.1*(speed--)
if(speed<1){
callback&&callback();
clearInterval(this.timer);
}
}.bind(this),30);
}
</script>
</body>
</html>
复制代码
看了视频也学到了之前一直没有注意的东西:
- CSS3很厉害啊,能将方形的div转成是椭圆形的[也就是气球的形状],还有盒子的阴影设置。
- 使用伪元素就可以不用直接在html中设置标签了。配合CSS3也能够做出对应的样式。
- 使用实体边框配合CSS3也可以做出不同的形状样式
- 在生成元素的时候,可以先将要生成的元素加入到文档片段中,再使用文档片段来进行一次性添加到body上,这样性能会好很多!
- 使用~~运算符能够取整数
- 限定气球的边界就可以使用max和min函数来进行限定。这也是很好用的。
- 移动气球我们需要用到定时器。
- 使用call主动调用方法,把目标对象传递过去的话,我们就可以使用this指针了。
- 在定时器中使用bind(this),就可以在定时器中使用this指针的,因为定时器默认是由浏览器window来进行调用的,默认是不能使用this的
- 绑定单击事件的时候,不要使用循环来进行绑定,这样太耗费性能了,我们可以使用监听事件来进行一次绑定。
- 在遍历元素数组的时候,条件是元素数组的长度时,我们可以先把该元素数组的长度初始化出来,那么也可以提升性能!不然就每次判断前都要去查询数据的长度!
for(var i=0,len = array.length; i<len;i++){}
复制代码
如果您觉得这篇文章帮助到了您,可以给作者一点鼓励