3D炫酷雪花背景的实现
3D炫酷雪花背景,并且雪的大小还会随时间变化。目前已经开源到码云上,源码下载地址:https://gitee.com/hj1991/snowFalling 。
效果展示(微信截动态变化背景图,效果不太好。另外,由于不会P图,雪花用的图片就是一个白色的圆,特别是近镜头的时候,效果有点搓哈,囧囧囧~,会p图的同学可以将ParticleSmoke.png P成无背景的雪花图片,要是能把P好的图片给我的话就太谢谢了!):
代码讲解:
index.html
<!DOCTYPE html >
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,hight=device-hight,minimum-scale=1.0,maximum-scale=1.0,ser-scalable=none">
<title>开始下雪了</title>
<link type="text/css" rel="stylesheet" href="">
<style>
*{margin: 0;padding: 0;overflow: hidden;}
body{
background-image:url('images/background.jpg');
background-size:cover;
background-repeat: no-repeat;
position: relative;
width:100%;
}
</style>
</head>
<body>
<audio autoplay="autoplay" loop="loop"><source src="js/网络歌手-冰海.mp3" type="audio/ogg"></audio>
</body>
<script type="text/javascript" src="./js/ThreeCanvas.js"></script>
<script src="http://www.jq22.com/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="./js/Snow.js"></script>
<script type="text/javascript" src="./js/snowFall.js"></script>
<script type="text/javascript" src="./js/snowFalling.js"></script>
<script>
$.snowFalling({
//初始雪花粒子数量,密度
particleNo:0,
//粒子下拉速度
particleSpeed:50,
//粒子在垂直(Y轴)方向运动范围
particleY_Range:window.innerWidth,
//粒子在垂直(X轴)方向运动范围
particleX_Range:window.innerHeight,
//相机离Z轴原点距离
zIndex:600,
//摄像机视野角度
angle:55,
wind_weight:10 //风速:大于0,雪花向右飘;小于0,雪花向左飘;等于0,无风。
});
</script>
</html>
index.html除了设置下雪的参数,加个背景音乐外,没有其他的了。
snowFalling.js
//创建snowFall对象
var snowFall=new snowFall(window.innerWidth,window.innerHeight,true,20);
//容器
var container;
//绑定jquery方法
jQuery.extend({
snowFalling:function(options){
var defaults = {
//创建粒子数量,密度
particleNo: 500,
//粒子下拉速度
particleSpeed:15,
//粒子在垂直(Y轴)方向运动范围
particleY_Range:1300,
//粒子在垂直(X轴)方向运动范围
particleX_Range:1000,
//相机离Z轴原点距离
zIndex:600,
//风力强度,正值向右,负值向左
wind_weight:0,
//摄像机视野角度
angle:55
};
var particleImage = new Image();
particleImage.src = "images/ParticleSmoke.png";
var opts = $.extend(defaults, options);
opts.particleImage=particleImage;
opts.screenWidth=window.innerWidth;
opts.screenHeight=window.innerHeight;
//初始化下雪厂景
snowFall.init(opts);
container = document.createElement('div');
document.body.appendChild(container);
container.appendChild(snowFall.renderer.domElement );
//雪景变化
snowFall.snowFallChange();
}
});
snowFalling.js主要做了三件事:1、获取index.html中设置的参数;2、new 一个snowFall对象,并进行初始化;3、调用snowFall.snowFallChange()函数;
snowFall.js
function snowFall(screenWidth,screenHeight,flag,parameter){
this.screenWidth=screenWidth;
this.screenHeight=screenHeight;
this.flag=flag;
this.parameter=parameter;
}
snowFall.prototype.init=function(opts){
snowFall.options=opts;
// 透视相机,物体大小随距离摄像机远近改变,对比投影相机
// 相机的上方向为Y轴,右方向为X轴,沿着Z轴垂直朝里(视野角:fov; 纵横比:aspect; 相机离视最近的距离:near; 相机离视体积最远距离:far)
snowFall.camera = new THREE.PerspectiveCamera( opts.angle, snowFall.screenWidth / snowFall.screenHeight, 1, 10000 );
//设置摄像机z坐标位置距离原点向外距离
snowFall.camera.position.z = snowFall.options.zIndex;
//创建场景
snowFall.scene = new THREE.Scene();
snowFall.scene.add(snowFall.camera);
//创建渲染器
snowFall.renderer = new THREE.CanvasRenderer();
snowFall.renderer.setSize(snowFall.screenWidth, snowFall.screenHeight);
//创建材料
snowFall.material = new THREE.ParticleBasicMaterial( { map: new THREE.Texture(snowFall.options.particleImage) } );
snowFall.particles = [];
for (var i = 0; i < snowFall.options.particleNo; i++) {
snowFall.addparticle();
}
}
snowFall.prototype.loop=function(){
for(var i = 0; i<snowFall.particles.length; i++){
snowFall.particle = snowFall.particles[i];
snowFall.particle.updatePhysics();
with(snowFall.particle.position){
if(y<-snowFall.options.particleY_Range/2){
y+=snowFall.options.particleY_Range;
}
// Z轴位置不变
if(x>snowFall.options.screenWidth/2){
x-=snowFall.options.screenWidth;
}else if(x<-snowFall.options.screenWidth/2){
x+=snowFall.options.screenWidth;
}
//风力偏向效果
x+=snowFall.options.wind_weight;
}
}
snowFall.camera.lookAt(snowFall.scene.position);
snowFall.renderer.render( snowFall.scene, snowFall.camera );
}
snowFall.prototype.addParticle=function(){
snowFall.particle = new Snow(snowFall.material);
snowFall.particle.position.x = Math.random() * snowFall.options.screenWidth *2- snowFall.options.screenWidth/2;
snowFall.particle.position.y = Math.random() * snowFall.options.screenHeight * 2 - snowFall.options.screenHeight;
snowFall.particle.position.z = Math.random() * snowFall.options.zIndex * 2 - snowFall.options.zIndex*1;
snowFall.particle.scale.x = snowFall.particle.scale.y = 1;
snowFall.scene.add( snowFall.particle );
snowFall.particles.push(snowFall.particle);
}
snowFall.prototype.removeParticle=function(){
snowFall.particle=snowFall.particles.pop();
snowFall.scene.remove( snowFall.particle );
}
snowFall.prototype.parameterChange=function(){
if(snowFall.particles.length>=500){
snowFall.parameter=500;
}else if(snowFall.particles.length>=200&&snowFall.particles.length<500){
snowFall.parameter=300;
}else if(snowFall.particles.length>=100&&snowFall.particles.length<200){
snowFall.parameter=100;
}else if(snowFall.particles.length>=50&&snowFall.particles.length<100){
snowFall.parameter=50;
}else{
snowFall.parameter=20;
}
}
snowFall.prototype.particlesCountChange=function(){
snowFall.parameterChange(snowFall.particles);
if(snowFall.flag){
for(var j=0;j<parseInt(snowFall.parameter*Math.random());j++){
if(snowFall.particles.length>=1500){
snowFall.flag=false;
return snowFall.flag;
}
snowFall.addParticle();
}
}else{
for(var j=0;j<parseInt(snowFall.parameter*Math.random());j++){
if(snowFall.particles.length>0){
snowFall.removeParticle();
}else{
snowFall.flag=true;
}
}
}
}
snowFall.prototype.snowFallChange=function(){
var time1=setInterval( snowFall.loop, snowFall.options.particleSpeed );
setInterval(function(){
snowFall.options.particleNo+=parseInt(10*Math.random());
window.clearInterval(time1);
snowFall.particlesCountChange();
time1=setInterval( snowFall.loop, snowFall.options.particleSpeed);
},3000);
}
snowFall.js主要是已Prototype/Constructor杂合方式创建了一个snowFall类。
function snowFall() 构造函数;
snowFall.init() 初始化,主要实现包括三维相机、场景、渲染器、材料的初始化,以及开始雪花粒子数量的设置;
snowFall.snowFallChange() 雪景的变化,包括雪花粒子数量的变化以及雪花移动位置的动态变化;
snowFall.particlesCountChange() 雪花粒子数量的变化,雪花粒子数量一开始是默认增加,当达到1500的时候,雪花粒子数量 就会减小;雪花粒子每次循环增加/减小的数量是随机的,但增加/减少的雪花粒子速
率 和当前雪花粒子数量正相关。
snowFall.loop() 雪花粒子位置的变化;
snowFall.parameterChange() 雪花粒子增加/减少速度变化;
snowFall.addParticle() 增加雪花粒子;
snowFall.removeParticle() 移除雪花粒子;
Snow.js
Snow=function(material){
THREE.Particle.call(this,material);
this.velocity=new THREE.Vector3(0,-8,0);//速度;
//this.velocity.rotateX(2);//旋转;
this.gravity=new THREE.Vector3(0,0,0);//加速度;
this.drag=1;//速度相乘系数;
};
//Particle:粒子;
//prototype:原形;
Snow.prototype=new THREE.Particle();
Snow.prototype.constructor=Snow;//构造函数
Snow.prototype.updatePhysics=function(){
this.velocity.multiplyScalar(this.drag);//矢量相乘函数
this.velocity.addSelf(this.gravity);//矢量相加函数
this.position.addSelf(this.velocity);//矢量相加函数
}
var TO_RADIANS=Math.PI/180;//角度向弧度转换系数*
THREE.Vector3.prototype.rotateY=function(angle){
//绕Y轴顺时针旋转angle;
cosRY=Math.cos(angle*TO_RADIANS);
sinRY=Math.sin(angle*TO_RADIANS);
var tempz=this.z;
var tempx=this.x;
this.x=(tempx*cosRY)+(tempz*sinRY);
this.z=(tempx*-sinRY)+(tempz*cosRY);
}
THREE.Vector3.prototype.rotateX=function(angle){
//绕X轴顺时针旋转angle;
cosRY=Math.cos(angle*TO_RADIANS);
sinRY=Math.sin(angle*TO_RADIANS);
var tempz=this.z;;
var tempy=this.y;
this.y=(tempy*cosRY)+(tempz*sinRY);
this.z=(tempy*-sinRY)+(tempz*cosRY);
}
THREE.Vector3.prototype.rotateZ=function(angle){
//绕Z轴顺时针旋转angle;
cosRY=Math.cos(angle*TO_RADIANS);
sinRY=Math.sin(angle*TO_RADIANS);
var tempx=this.x;;
var tempy=this.y;
this.y=(tempy*cosRY)+(tempx*sinRY);
this.x=(tempy*-sinRY)+(tempx*cosRY);
}
snow.js 主要是对ThreeCanvas.js的应用,想学的可以去了解一下three.js和ThreeCanvas.js
上一篇: Tkinter教程之Canvas篇(2)
下一篇: SQL Server进行递归查询实现方法