原生JS实现雪花特效

今天在校园招聘上被问到的问题,用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;
    }

    body {
      background: #000;
    }

    #curtain {
      width: 100%;
      height: 600px;
      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>
</head>

<body>
  <div id="curtain"></div>
</body>
<script type="text/javascript">
(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: 10,
    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.length) {
        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);
        // 唤醒 div
        this.Move(oDiv, now);
        ++this.count;
      } else {
        return false;
      }
    },
    Move: function (oDiv, now) {
      var timer = setInterval(function () {
        if (now.positionX < maxWidth && now.positionY < maxHeight - 50) {
          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);
          oDiv.style.left = now.positionX + "px";
          oDiv.style.top = 0 + "px";
        }
      }, 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>

</html>

思路4: 使用canvas来实现雪花特效

待更...

posted @ 2017-05-17 15:31  海客无心x  阅读(4704)  评论(0编辑  收藏  举报