示例代码:

<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. cxf框架使用(一)

    1.创建调用接口 @WebService public interface IQueryBusinessService { public @WebResult(name="QueryBusi ...

  2. DeDe内容调用img

    文章内容页调用缩略图方法如下两种.第一种没有大小设置.原图显示.第二种.可以设大小, {dede:field.image/} <img src="{dede:field.litpic ...

  3. Python学习笔记四--字典与集合

    字典是Python中唯一的映射类型.所谓映射即指该数据类型包含哈希值(key)和与之对应的值(value)的序列.字典是可变类型.字典中的数据是无序排列的. 4.1.1字典的创建及赋值 dict1={ ...

  4. c构造函数

    构造函数   任何一们面向对象语言里都会涉及构造函数这一概念,只是实现的方式各有差异.需要这main函数之前执行一段代码是非常容易的事情,只需要声明一对象的全局变量,在构造函数可以为所欲为干你想干的事 ...

  5. 转:WebSocket与Java

    Bozhidar Bozhanov是Ontotext AD的高级软件工程师,拥有多年的从业经验,也是stackoverflow上的活跃用户.他精通于Java与Java技术栈,如Spring.JPA.J ...

  6. 为什么同时需要IP地址和MAC地址

    每个以太网设备在出厂时都有一个唯一的MAC地址,为什么还需要为每台主机再分配一个IP地址?或者说每台主机都分配唯一的IP地址,为什么还要在网络设备(如网卡,集线器,路由器等)生产时内嵌一个唯一的MAC ...

  7. BZOJ1754: [Usaco2005 qua]Bull Math

    1754: [Usaco2005 qua]Bull Math Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 374  Solved: 227[Submit ...

  8. 什么是Web Service?

    Web service到底是什么:在什么情况下你应该使用Web service. 分布式应用程序和浏览器 研究一下当前的应用程序开发,你会发现一个绝对的倾向:人们开始偏爱基于浏览器的瘦客户应用程序.这 ...

  9. Data Guard 之 浅析Switchover与Failover

    Data Guard主从库之间的角色切换分为以下两种:1)SwitchoverSwithchover通常都是人为的有计划的进行角色互换,比如升级等.它通常都是无损的,即不会有数据丢失.其执行主要分为两 ...

  10. SKKeyframeSequence类

    继承自 NSObject 符合 NSCodingNSCopyingNSObject 框架  /System/Library/Frameworks/SpriteKit.framework 可用性 可用于 ...