示例代码:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<meta charset="utf-8" />
<style>
body {
background:#333;
}
</style>
</head>
<body>
<button id="start-snowFall">开始</button>
<button id="stop-snowFall">停止</button>
<button id="pause-snowFall">暂停</button>
<button id="resume-snowFall">回复</button>
<script>
window.onload = function () {
//绑定事件
var snow = new snowFall({ maxFlake: 200 });
var start = document.getElementById('start-snowFall'),
stop = document.getElementById('stop-snowFall'),
pause = document.getElementById('pause-snowFall'),
resume = document.getElementById('resume-snowFall');
//开始
start.onclick = function () {
snow.start();
}
//停止
stop.onclick = function () {
snow.stop();
}
//暂停
pause.onclick = function () {
snow.pause();
}
//回复
resume.onclick = function () {
snow.resume();
}
}
//控制对象封装
function snowFall(snow) {
//可配置属性
snow = snow || {};
this.maxFlake = snow.maxFlake || 200; //最多骗术
this.flakeSize = snow.flakeSize || 10;// 雪花形状
this.fallSpeed = snow.fallSpeed || 2;//坠落速度
this.status = 0; //0-初始化、1-开始下雪 、2--停止下雪 、3--暂停下雪、4--继续下雨
}
//兼容写法
requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function (callback) { setTimeout(callback, 1000 / 60) };
cancelAnimationFrame = window.cancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.msCancelAnimationFrame ||
window.oCancelAnimationFrame; //开始下雪
snowFall.prototype.start = function () {
if (this.status == 1 || this.status == 4)
return false;
this.status = 1;
//创建画布
snowCanvas.apply(this);
//创建雪花形状
createFlakes.apply(this);
//画学
drawSnow.apply(this);
}
//停止下雪
snowFall.prototype.stop = function () {
if (this.status == 2 || this.status == 0 || !this.canvas) {
return false;
}
//定制动画循环
this.pause();
this.status = 2;
//删除画布
this.canvas.parentNode.removeChild(this.canvas);
this.canvas = null;
};
//暂停下雪
snowFall.prototype.pause = function () {
if (this.status == 3) {
return false;
}
this.status = 3;
cancelAnimationFrame(this.loop);
}
//继续下雪
snowFall.prototype.resume = function () {
if (this.status == 3 && this.canvas) {
this.status = 4;
//动画的计时控制
this.loop = requestAnimationFrame(function () {
drawSnow.apply(that);
});
}
}
//创建画布
function snowCanvas() {
//添加Dom节点
var snowcanvas = document.createElement('canvas');
snowcanvas.id = 'snowfall';
snowcanvas.width = window.innerWidth;
snowcanvas.height = window.innerHeight;
snowcanvas.setAttribute('style', 'position:fixed;top:0;left:0;z-index:2999;pointer-events:none;'); document.getElementsByTagName('body')[0].appendChild(snowcanvas);
this.canvas = snowcanvas;
this.ctx = snowcanvas.getContext('2d');
//窗口大小改变处理
window.onresize = function () {
snowcanvas.width = window.innerWidth;
snowcanvas.height = window.innerHeight;
}
}
//创建雪花
function createFlakes() {
var maxFlake = this.maxFlake,
flakes = this.flakes = [],
canvas = this.canvas;
for (var i = 0; i < maxFlake; i++) {
flakes.push(new flakeMove(canvas.width, canvas.height, this.flakeSize, this.fallSpeed));
}
}
//雪运动对象
function flakeMove(canvasWidth, canvasHeight, flakeSize, fallSpeed) {
this.x = Math.floor(Math.random() * canvasWidth); //x坐标
this.y = Math.floor(Math.random() * canvasHeight); //y坐标
this.size = Math.random() * flakeSize + 2; //形状
this.masSize = flakeSize; //最大形状
this.speed = Math.random() * 1 + fallSpeed; //坠落速度
this.fallSpeed = fallSpeed; //坠落速度
this.velY = this.speed; //y方向速度
this.velX = 0; //x方向速度
this.stepSize = Math.random() / 30; //步长
this.step = 0; //步数
}
//重置当前雪花的位置
flakeMove.prototype.update = function () {
var x = this.x,
y = this.y;
//左右摆动(余弦)
this.velX *= 0.98;
if (this.velY <= this.speed) {
this.velY = this.speed;
}
this.velX += Math.cos(this.step += 0.05) * this.stepSize; this.y += this.velY;
this.x += this.velX;
//飞出边界处理
if (this.x >= canvas.width || this.x <= 0 || this.y >=canvas.height || this.y <= 0) {
this.reset(canvas.width,canvas.height);
}
}
//飞出边界--放置最顶端继续坠落
flakeMove.prototype.reset = function (width, height) {
this.x = Math.floor(Math.random() * width);
this.y = 0;
this.size = Math.random() * this.masSize + 2;
this.speed = Math.random() * 1 + this.fallSpeed;
this.velY = this.speed;
this.velX = 0;
}
//渲染雪花--随机形状
flakeMove.prototype.render = function (ctx) {
var snowFlake = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size);
snowFlake.addColorStop(0, 'rgba(255,255,255,0.9)');
snowFlake.addColorStop(0.5, 'rgba(255,255,255,0.5)');
snowFlake.addColorStop(1, 'rgba(255,255,255,0)');
ctx.save();
ctx.fillStyle = snowFlake;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fill();
ctx.restore();
}
//滑雪
function drawSnow() {
var maxFlake = this.maxFlake,
flakes = this.flakes;
ctx = this.ctx,
canvas = this.canvas,
that = this;
//清空
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < maxFlake; i++) {
flakes[i].update();
flakes[i].render(ctx);
}
//一折一帧的画
this.loop = requestAnimationFrame(function () {
drawSnow.apply(that);
});
}
</script>
</body>
</html>

显示结果:

1.主要代码

this.step = 0;
this.stepSize = Math.random() / 30;
this.velX += Math.cos(this.step += .05) * this.stepSize;
this.x += this.velX;

step从0开始,每一帧增加0.05,相当于上图的横轴(X坐标)随着时间向右走

Math.cos(this.step += .05)则为上图对应的数轴(Y坐标),会随着step的增加,呈现1到-1的抛物线变换,正负值使得velX有左右方向

stepSize为步长,因为一帧有几十毫秒,很快,所以这个值为小于1/30的一个随机数

x为雪花的X坐标位置,就会在界面左右摆动

使用Canvas实现下雪功能的更多相关文章

  1. html5 canvas 实现倒计时 功能

    function showTime(a) { var b = { id: "showtime", //canvasid x: 60, //中心点坐标 X轴; y: 60, //中心 ...

  2. canvas实现画板功能(渐变、动画、阴影...)

    刚刚在博客园落户了,希望能在这认识更多大神,希望能和大家交好朋友. 闲来无事,把以前用canvas写的画板代码改进了一番,用Html5提供的表单标签给其 加了一个选择颜色的功能,因此发现了该标签的一个 ...

  3. Canvas的下雪效果

    cfs.snow.js canvas 下雪场景 不会影响页面使用 使用方式非常简单 利用这个js文件,我们就能很快的让页面出现下雪的动画效果. 例如 <script type="tex ...

  4. 【分享】用Canvas实现画板功能

    前言 PC端测试:QQ浏览器全屏绘画完成.缩小时内容会被清空,切换背景颜色内容会被重置,其他暂无发现: 手机端测试:微信内置浏览器不通过:Safari 浏览器使用画笔时没固定页面会有抖动效果,使用橡皮 ...

  5. H5利用canvas实现海报功能

    最近接到一个需求,微信中用户上传图片生成海报.这个需求比较常规,实现思路也比较简单,通过利用用户的input输入,对所上传的图片进行处理,最后通过第三方库html2canvas合成对应的图片即可.思路 ...

  6. canvas实现验证码功能

    我们在做一些后台系统登录功能的时候,一般都会用到验证码,最多的就是后台生成的验证码图片返回给前端的.也可以不调用后端接口,前端使用canvas直接生成验证码. 由于功能过于简单,不需要多少代码和文字说 ...

  7. 使用JavaScript和Canvas实现下雪动画效果

    该下雪动画效果使用了HTML5中Canvas画布实现,其中涉及了物理学中曲线运动的相关知识与运算. index.html <!DOCTYPE html> <html lang=&qu ...

  8. 通过jcrop和canvas的画布功能完成对图片的截图功能与视频的截图功能实现

    最近因为工作需要,做了视频截图和图截图的功能.大概需求是,用户点击某个按钮,可以对图片区域进行部分截取,然后进行进一步的业务操作. 首先说图片截图功能的思路, (1)下载Jcrop插件,添加css和j ...

  9. Canvas现实画板功能

    先看图片 HTML <!doctype html> <html lang="en"> <head> <meta charset=" ...

随机推荐

  1. angularJS中如何写控制器

    angularJS中的控制器是一个函数,用来向视图作用域中添加额外的功能,我们用它来给作用域对象设置初始状态,并添加自定义行为 当我们在页面上创建一个新的控制器时,angularJS会生成并传递一个新 ...

  2. Spring Cp30配置

    1.配置db.properties <bean id= "propertyConfigurer" class="org.springframework.beans. ...

  3. yum 搭建lnmp环境详细步骤

    1.关闭防火墙[root@CentOS ~]# chkconfig iptables off 2.关闭selinuxvi /etc/sysconfig/selinux//将SELINUX=enforc ...

  4. js移动设备手机跳转地址代码

    if(/AppleWebKit.*mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alc ...

  5. 学c语言做练习之文件

    打开两个文件,让程序打印第一个文件的第一行,第二个文件的第一行,第一个文件的第二行,第二个文件的第二行,依此类推,直到打印完行数较多的文件的最后一行. #include<stdio.h> ...

  6. 百度地图LBS云平台读写数据操作类

    最近写了个叫<行踪记录仪>的手机软件,用了百度云来记录每个用户的最近位置,以便各用户能在地图上找到附近的人,为此写了个类来读写数据,大致如下: import java.util.Array ...

  7. ajax vs oauth

    http://www.cnblogs.com/rush/archive/2012/05/15/2502264.html https://www.ibm.com/developerworks/cn/xm ...

  8. poj2352 Stars

    http://poj.org/problem?id=2352 #include <cstdio> #include <cstring> #define maxn 400000 ...

  9. Linux&shell之结构化命令

    写在前面:案例.常用.归类.解释说明.(By Jim)使用if-then语句如果命令的退出状态是0(成功执行命令),将执行then后面的所有命令.如果命令的退出状态是0以外的其他值,那么then后面的 ...

  10. 可以把一些常用的方法,写入js文件,引入html界面

    这样,可以在多处应用.更好一些.缺点是不够灵活. 优点是,一处修改,多处应用. 函数这东西,一般都是先加载的,之后就可以随便调用了. function delquestion(obj){ //conf ...