示例代码:

<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. js 获取鼠标位置坐标

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  2. phpMemcache消息队列类

    <?php /** * Memcache 消息队列类 */ class QMC { const PREFIX = 'ASDFASDFFWQKE'; /** * 初始化 mc * @staticv ...

  3. 学习python——博客记录第一天

    HELLO WORLD!   今天第一次开立博客,专门记载学习编程语言中的点点滴滴.今日学习内容: 搭建vs code+ python3.5 "ide" 学习廖雪峰python教程 ...

  4. C# ORM—Entity Framework 之Code first(代码优先)(二)

    一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...

  5. USACO1.5 Checker Challenge(类n皇后问题)

    B - B Time Limit:1000MS     Memory Limit:16000KB     64bit IO Format:%lld & %llu   Description E ...

  6. ACCESS中类型操作(限制、转换)

    ACCESS如何保留两位小数 1.可以通过修改表结构中字段的“小数位数”即可. 2.可以通过“更新查询”,将所有该字段的值更新为round(字段名,2) ACCESS如何转换类型 每个函数都可以强制将 ...

  7. poj Pie

    http://poj.org/problem?id=3122 #include<cstdio> #include<cstring> #include<cmath> ...

  8. 常用SNS开源系统比较

    常用SNS开源系统比较 这 几天看了很多关于SNS(社交网络服务) 的东西..得到了不少启发..目前的IDEA是..可以在学校弄一个试试..主打的东西不能和现有的SNS冲突(如校内网).利用本地优势. ...

  9. [Poetize I]守卫者的挑战

    描述 Description 打开了黑魔法师Vani的大门,队员们在迷宫 般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过.“我,Nizem,是黑魔法圣殿的守卫者.如果 ...

  10. 【转】Java中本地时间的获取方法--不错

    原文网址:http://highforest.blog.51cto.com/125539/842496/ 熟悉Oracle数据库的人,应该知道:select to_char(sysdate,'yyyy ...