右边的代码snowflake.js是完成的雪花代码,初学者可能会有点难度,尝试着慢慢理解下。在canvas飘雪(中)的基础上增加了运动的一个算法,然后把整个结构给规整了下。
入口是Snowflake函数,流程如下:
雪球的变化会有一系列的参数设置,这里会用initSnow函数完成这个默认的参数选择,并增加了速率等参数设置。
雪球的坐标变化update方法:
Y轴:
this.y += this.speedY; if (this.y > this.snowSettings.maxY) { this.y -= this.snowSettings.maxY; }
this.speedY是一个增量,每次都叠加赋予,如果溢出后就会还原
X轴:
this.angle += this.speedX; if (this.angle > Math.PI * 2) { this.angle -= Math.PI * 2; } this.x = this.initialX + this.moveX * Math.sin(this.angle);
X轴的变化是有个左右移动的,所以这里回用正玄值来计算左右的位移
移动:
在renderAndUpdate方法中,通过不断的调用requestAnimationFrame达到不断刷新雪球的坐标,感觉上雪球是不断在飘落
var renderAndUpdate = function() { render(); update(); requestAnimationFrame(renderAndUpdate); }
在snowflake.js文件141行处填入任务代码
计算出雪飘在x轴坐标中移动的距离
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <title>圣诞主题</title> <link rel='stylesheet' href='common.css' /> <link rel="stylesheet" type="text/css" href="pageC.css"> </head> <body> <section class="container"> <!-- 第一幅画面 --> <section class="page-a bg-adaptive"> </section> <!-- 第二幅画面 --> <section class="page-b bg-adaptive"> </section> <!-- 第三幅画面 --> <section class="page-c bg-adaptive"> <!-- 窗户关闭 --> <div class="window wood"> <div class="window-content" data-attr="red"> <div class="window-scene-bg"></div> <div class="window-close-bg"></div> <div class="window-left hover"></div> <div class="window-right hover"></div> </div> </div> </section> <!-- 雪花 --> <canvas id="snowflake"></canvas> </section> <script type="text/javascript"> var config = {}; //rem设置 (function(doc, win) { var docEl = doc.documentElement, resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize', recalc = function() { var clientWidth = docEl.clientWidth; if (!clientWidth) return; docEl.style.fontSize = 20 * (clientWidth / 320) + 'px'; //宽与高度 document.body.style.height = clientWidth * (900 / 1440) + "px" config.clientWidth = clientWidth; config.clientHeight = clientWidth * (900 / 1440) }; win.addEventListener(resizeEvt, recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false); })(document, window); </script> <script src="http://libs.baidu.com/jquery/1.9.1/jquery.js"></script> <script type="text/javascript" src="snowflake.js"></script> </body> </html>
/** * 雪花 * canvas版 */ $(function() { /** * 雪球 * @param {[type]} elementName [description] */ function Snowflake(elementName) { var snowElement = document.getElementById(elementName) var canvasContext = snowElement.getContext("2d"); var width = config.clientWidth; var height = config.clientHeight; //canvas尺寸修正 snowElement.width = width; snowElement.height = height; //构建雪球的数量 var snowNumber = 50; //构建雪球对象 var snowArrObjs = initSnow(snowNumber, width, height); var snowArrNum = snowArrObjs.length; /** * 绘制页面 * @return {[type]} [description] */ var render = function() { //清理之前的矩形数据 canvasContext.clearRect(0, 0, width, height); for (var i = 0; i < snowArrNum; ++i) { snowArrObjs[i].render(canvasContext); } } /** * 更新雪花 * @return {[type]} [description] */ var update = function() { for (var i = 0; i < snowArrNum; ++i) { snowArrObjs[i].update(); } } /** * 绘制与更新 * @return {[type]} [description] */ var renderAndUpdate = function() { render(); update(); requestAnimationFrame(renderAndUpdate); } renderAndUpdate(); } function initSnow(snowNumber, width, height) { //雪球参数 var options = { //雪球的半球距离 minRadius: 3, maxRadius: 10, // 运动的范围区域 maxX: width, maxY: height, //速率 minSpeedY: 0.05, maxSpeedY: 2, speedX: 0.05, //滤镜 minAlpha: 0.5, maxAlpha: 1.0, minMoveX: 4, maxMoveX: 18 } var snowArr = []; for (var i = 0; i < snowNumber; ++i) { snowArr[i] = new Snow(options); } return snowArr; } /** * 雪球类 */ function Snow(snowSettings) { this.snowSettings = snowSettings; this.radius = randomInRange(snowSettings.minRadius, snowSettings.maxRadius); //初始的x位置 this.initialX = Math.random() * snowSettings.maxX; this.y = -(Math.random() * 500); //运行的速率 this.speedY = randomInRange(snowSettings.minSpeedY, snowSettings.maxSpeedY); this.speedX = snowSettings.speedX; //滤镜 this.alpha = randomInRange(snowSettings.minAlpha, snowSettings.maxAlpha); //角度.默认是360 this.angle = Math.random(Math.PI * 2); //运行的距离 this.x = this.initialX + Math.sin(this.angle); //x移动距离 this.moveX = randomInRange(snowSettings.minMoveX, snowSettings.maxMoveX); } /** * 绘制雪球 * @param {[type]} canvasContext [description] * @return {[type]} [description] */ Snow.prototype.render = function(canvasContext) { //清除路径 //开始一个画布中的一条新路径(或者子路径的一个集合) canvasContext.beginPath(); //用来填充路径的当前的颜色,白色的雪球 canvasContext.fillStyle = "rgba(255, 255, 255, " + this.alpha + ")"; //一个中心点和半径,为一个画布的当前子路径添加一条弧线 //坐标,圆,沿着圆指定弧的开始点和结束点的一个角度 //弧沿着圆周的逆时针方向(TRUE)还是顺时针方向(FALSE)遍历 canvasContext.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); //关闭子路径 canvasContext.closePath(); //fill() 方法使用 fillStyle 属性所指定的颜色、渐变和模式来填充当前路径 canvasContext.fill(); } Snow.prototype.update = function() { this.y += this.speedY; if (this.y > this.snowSettings.maxY) { this.y -= this.snowSettings.maxY; } this.angle += this.speedX; if (this.angle > Math.PI * 2) { this.angle -= Math.PI * 2; } //? } /** * 随机处理 * @param {[type]} min [description] * @param {[type]} max [description] * @return {[type]} [description] */ function randomInRange(min, max) { var random = Math.random() * (max - min) + min; return random; } Snowflake("snowflake") })
*{ margin: 0; padding: 0; } .container { width: 100%; height: 100%; position: relative; overflow: hidden; } .bg-adaptive { background-size: 100% 100%; }
.page-c { width : 100%; height : 100%; background-image: url("http://img1.sycdn.imooc.com//565d0b280001788014410901.png"); position: absolute; z-index: 30; } #snowflake{ position:absolute; left:0; top:0; z-index: 999999; }