原生javascript雪花飘落3d效果

先上代码

<!DOCTYPE html>
<html>
<head>
	<title></title>
	<meta charset="utf-8">
	<style>
		html,body{background-color:#282923;height:100%;width:100%;font-size:65.5%;margin:0;padding:0;}
		.snow{
			color:white;
			animation:rotes 3s infinite linear;
		}
		@keyframes rotes{
			100%{
				transform:rotate3d(1,-1,1,720deg);
			}
		}
	</style>
</head>
<body>
</body>
</html>
<script type="text/javascript">
	snow = function(){
		this.body = document.body;
		this.millisec = 30;//下一朵雪花生成的速度
		this.timer;
		this.winwidth = window.innerWidth;
		this.winHeight = window.innerHeight;
		//创建并返回 一个雪花对象
		this.create = function(){
			snowborder = document.createElement('div');
			snow = document.createElement('div');
			snowborder.appendChild(snow);
			snowborder.style.position='absolute';
			//雪花的属性
			snow.classList.add('snow');
			snow.innerHTML = '❉';			
			return snowborder;
		}
		//开始下雪效果   var 定义变量为局部,为了指定当前的雪花元素
		this.play = function(){
			this.body.style.cssText=`transform-style:preserve-3d;
			transform:perspective(50rem);`;
			var that = this; //将this保存在that内,因为 闭包函数内和外部不联系
			this.timer = setInterval(function(){
				var snowborder = that.create();
				//克隆一个雪花
				var cloneSnow = snowborder.cloneNode(1);
				/*开始位置*/
				var startx = (that.winwidth*.95)*Math.random();						
				var starty = (that.winHeight*.95)*Math.random();				
				/*结束位置*/
				var endx = (that.winwidth*.95) * Math.random();
				var endy = (that.winHeight*.95) * Math.random();
				var endz = (that.winHeight*.5) * Math.random();
				/* 持续时间  这个时间是元素从初始化状态到最终状态所需的过渡时间,也是删除元素的时间 !!! */
				var duration = parseInt(4000 + Math.random()*4000);
				var fontSize = 1 + Math.random()*30;
				// 开始时透明度
				var startOpacity = .5+.3*Math.random();
				// 结束时透明度
				var endOpacity = .1;
				//设置初始的雪花位置和大小
				cloneSnow.style.cssText += `
					transform:translate3d(${startx}px,0,${endz}px);
					opacity:${startOpacity};
					transition:all ${duration}ms linear;
					font-size:${fontSize}px;`;

				/* adding  to body */
				that.body.appendChild(cloneSnow);
				//0.1秒后设置一下css,覆盖掉一些位置的,使得位置发送变化
				setTimeout(function(){
					cloneSnow.style.cssText += `
					transform:translate3d(${endx}px,${endy}px,${endz}px);
					opacity:${endOpacity};
					`;
					setTimeout(function(){
						cloneSnow.remove();
					},duration);//刚好是过渡效果结束的时间,把元素删除
				},100);
			},this.millisec);
			return "play";
		};
		//停止下雪效果
		this.stop=function(){
			clearInterval(this.timer);
			return 'stop';
		}
	}
// 实 例 化
snowObject = new snow();
snowObject.play(); //开始
// snowObject.stop(); //停止
</script>

snow类有两个主要方法
​ play() 开启定时器,雪花开始生成飘落

​ stop() 删除定时器,雪花停止生成

类的使用需要:

必要的
html,body{background-color:#282923;height:100%;width:100%;font-size:65.5%;margin:0;padding:0;}
【不是必要的】

需要定义一个动画 rotes 这是雪花飘落过程中雪花本身的动作,这里用的是旋转;可以不要
@keyframes rotes{
100%{
transform:rotate3d(1,-1,1,720deg);
}
}
定义一下.snow的样式
.snow{
color:white;
animation:rotes 3s infinite linear;
}

标题说一下主要的实现方法

  • 或许你没猜到,那么这个动画效果是如何实现的呢?transition属性!!第一个定时器生成了雪花的初始状态,第二个在生成的100毫秒后给了元素一个结束状态(关键帧);第三个定时器只用了一行代码,snowClone.remove();三个定时器嵌套使用了
    确定删除的属性。因为用的是嵌套,里面对元素都是用局部变量定义的,这样的话,不用给元素起id或者class,就可以确定是哪个元素了,因为一个局部区域里,只有一个雪花元素snowClone;第三个定时器选定到时间点则删除
  • 3d的效果的实现:给父元素添加两个属性
    transform-style:preserve-3d; //保留子元素的3d效果
    transform:perspective(50rem); //屏幕离场景的距离,可以用px。rem主要是移动端用的单位;
    子元素的3d移动 :
    用 tranform : translate3d(x,y,z)属性;三个值不表示三个方位的位移量水平x,竖直y,垂直向屏幕是z单位可以是px,rem,等
    这样做有什么好处呢?
    雪花的飘落用的是translate3d属性,这属性会触发GPU加速,和positionl相比动画会更流畅
    setInterval定时器只用了一个,用来生成雪花,雪花的移动和元素删除分别用了两个setTimeout定时器来完成;定时器的减少对降低了性能的开销;

效果图
在这里插入图片描述

发布了15 篇原创文章 · 获赞 4 · 访问量 1869

猜你喜欢

转载自blog.csdn.net/jayLog/article/details/103634261