今天在校园招聘上被问到的问题,用JS写出雪花的效果。我打算使用多种方法来试试如何实现雪花。
这是目前按照网上某种思路模仿的第一种雪花,不太好看,但是大致意思清楚。
思路1:该思路直接由JS实现。
- 雪花对象的定时创建 + 雪花对象的下落方法(包含消失判定)
- 雪花创建的位置和雪花形状的建立 + 雪花的速度和雪花可能的左右移动和消失
缺点:
- 不好看
- 兼容性
- 雪花方法不好,需要实时检索元素,应该改用数组维持
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,div{
margin: 0;
padding: 0;
}
body{
width: 100%;
height: 100%;
background-color: #000;
overflow: hidden;
}
#divCanvas{
width: 800px;
height: 800px;
background: #212123;
}
</style>
</head>
<body>
<div id="divCanvas"></div>
</body>
<script type="text/javascript">
var canvas = document.getElementById("divCanvas");
var maxWidth = canvas.clientWidth;
var maxHeight = canvas.clientHeight;
function Obj() {};
Obj.prototype.action = function(o) {
o.style.left = Math.ceil(Math.random() * maxWidth) + "px";
o.style.top = 0 + "px";
var speed = 0;
setInterval(function() {
if (parseInt(o.style.top) < maxHeight) {
o.style.top = parseInt(o.style.top) + speed + "px";
speed += 5;
} else {
o.style.display = "none";
}
}, 400);
}
setInterval(function() {
var oDiv = document.createElement("div");
oDiv.style.color = "#fff";
oDiv.innerHTML = "*";
oDiv.style.position = "absolute";
canvas.appendChild(oDiv);
var obj = new Obj();
obj.action(oDiv);
}, 300);
</script>
</html>
思路2:该思路由JS和CSS3共同实现。
- 雪花对象的创建 + 雪花的方法
- 用CSS3完善雪花的渐隐和出现动画 + 雪花固定的top值增加
缺点:
- 依旧没有用数组来维持,比较占内存
- 不够好看
- 兼容性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body,div{
margin: 0;
padding: 0;
}
body{
background: #000;
}
.snow{
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
animation: mysnow 20s;
position: absolute;
}
@keyframes mysnow{
0%{opacity: 0;}
50%{opacity: 1}
100%{opacity: 0;}
}
#canvas{
width: 800px;
height: 800px;
background: #213123;
}
</style>
<script type="text/javascript">
window.onload=function(){
var canvas=document.getElementById("canvas");
var maxWidth=canvas.clientWidth;
var maxHeight=canvas.clientHeight;
function Snow(){};
Snow.prototype.Move=function(x){
var speed=Math.ceil(Math.random()*1);
x.style.top=Math.floor(Math.random()*maxWidth);
x.style.left=Math.floor(Math.random()*maxHeight);
setInterval(function(){
if(parseInt(x.style.top)<maxHeight){
x.style.top=parseInt(x.style.top)+speed+"px";
}else{
x.style.display="none";
}
},30);
}
setInterval(function(){
var oDiv=document.createElement("div");
oDiv.className="snow";
oDiv.style.top=0+"px";
oDiv.style.left=Math.ceil(Math.random()*maxHeight)+"px";
canvas.appendChild(oDiv);
var snow=new Snow();
snow.Move(oDiv);
},200);
};
</script>
</head>
<body>
<div id="canvas"></div>
</body>
</html>
思路3:使用数组维持雪花对象,在一开始的时候便随机创建好每个雪花的动态属性
原型模式创建的雪花对象 + 雪花方法
优点:数组维持
缺点:
- 没有用上 window.requestAnimationFrame方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>mySnow- oH!!!Sexy!</title>
<style type="text/css">
body,div{margin: 0;padding: 0;}
#curtain{
width: 1600px;
height: 800px;
background-color: #111123;
}
.snow{
width: 10px;
height: 10px;
border-radius: 50%;
background: #fff;
position: absolute;
animation: mysnow 10s;
}
@keyframes mysnow{
0%{opacity: 0;}
50%{opacity: 1;}
100%{opacity: 0;}
}
.empty{
display: none;
}
</style>
<script type="text/javascript">
window.onload=function(){
var $=function(id){return typeof id==="string"?document.getElementById(id):id};
var curtain=$("curtain");
var maxWidth=curtain.clientWidth-50;
var maxHeight=curtain.clientHeight;
var snowControl=function(){};
snowControl.prototype={
Obj:[],
maxCount:400,
count:0,
Prepare:function(){
for(var i=0;i<this.maxCount;i++){
var o={
positionX:Math.ceil(Math.random()*maxWidth),
positionY:Math.ceil(Math.random()*50),
speed:Math.ceil(Math.random()*5+3),
shake:Math.ceil(Math.random()*3)
};
this.Obj.push(o);
};
},
Init:function(){
if(this.Obj!=null){
var oDiv=document.createElement("div");
oDiv.className="snow";
var now=this.Obj.shift();
oDiv.style.top=now.positionY+"px";
oDiv.style.left=now.positionX+"px";
curtain.appendChild(oDiv);
this.Move(oDiv,now);
++this.count;
}else{
return false;
}
},
Move:function(oDiv,now){
var timer=setInterval(function(){
if(now.positionX<maxWidth || now.positioY<maxHeight){
now.positionY=now.positionY+now.speed;
now.positionX=now.positionX+now.shake;
oDiv.style.top=now.positionY+"px";
oDiv.style.left=now.positionX+"px";
}else{
now.positionX=Math.ceil(Math.random()*maxWidth);
now.positionY=Math.ceil(Math.random()*50);
}
},30);
},
Letsgo:function(){
var oThis=this;
var gotimer=setInterval(function(){
if(oThis.count==oThis.maxCount){
clearInterval(gotimer);
}else{
oThis.Init();
}
},400);
}
};
var snow=new snowControl();
snow.Prepare();
snow.Letsgo();
};
</script>
</head>
<body>
<div id="curtain"></div>
</body>
</html>
思路4: 使用canvas来实现雪花特效
待更...