HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

Stella981
• 阅读 450

看到网上很多展示html5雪花飞动的效果,确实非常引人入胜,我相信大家也跟我一样看着心动的同时,也很好奇,想研究下代码如何实现;虽然哦很多地方也能下载这些源码,不过也不知道别人制作此类动画时的思路及难点分析。

我这几天刚好学习了一下,也趁着此刻有时间从需求分析、知识点、程序编写一步步给大家解剖下,要是在各位关公面前耍大刀了,可别见笑哟。

最终效果图如下:

HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

图1

一、需求分析

1、圆形雪花

本示例中雪花形状使用圆形

2、雪花数量固定

根据图1仔细观察白色雪花数量,飘落过程中,整张图的雪花数量应该是固定的,这个需求是需要通过我们观察分析所得。这与我们现实生活中看到一幅雪花满天飞的场景是一致的。

3、雪花大小不一致

每朵雪花它们大小各有不同,也就意味着雪花的半径是随机的。这与我们现实生活中看到一幅雪花满天飞的场景也是一致的。

4、雪花位置在移动

雪花飘落,自然它们的位置也在移动。

二、知识点

1、使用Html5 Canvas+JavaScript画圆——构成圆形雪花

在Html5中,需要使用Canvas同时借助JavaScript画圆,以构成圆形雪花——arc(x,y,r,start,stop);

2、随机数—产生不同半径、坐标的圆形雪花

本示例中,网页第一次加载时,需要生成一定数量的不同半径及位置的雪花,故半径、坐标为随机数;雪花在飘落过程中,其半径不变,坐标在一定幅度内变化,故此时坐标也为随机数——Math.random()

三、程序编写

1、准备工作

放一个画布canvas,并且设置整个body背景色为黑色

HTML代码:

<canvas id="mycanvas">
    您的浏览器不支持canvas画布
</canvas>

CSS代码:

* {    margin: 0;    padding: 0;}            #mycanvas {    background: black;}

此时效果如如下:

HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

注意:canvas默认是有一个初始化高度和宽度的,所以不用去纠结

2、画布满屏显示

JavaScript代码如下:

//获取mycanvas画布    var can = document.getElementById("mycanvas");    var ctx = can.getContext("2d");    //画布宽度    var wid = window.innerWidth;    //画布高度    var hei = window.innerHeight;    can.width=wid;    can.height=hei;

此时效果如如下:

HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

3、初始化生成固定数量的雪花

根据我们上述需求分析及知识点解读,首先雪花的数量是固定的,所以我们需要定义一个变量var snow = 100;这里假设雪花数量为100,;

生成雪花的时候,每个雪花半径、位置都不同,我们把每个雪花当做一个对象,那么这个对象的属性就包含:半径、坐标(X、Y),那么一个雪花对象可以写成var snowOject={x:1,y:10,r:5},这里就代表一个坐标为(1,10)半径为5的圆形雪花;本示例中由于半径和坐标都为随机数,故使用Math.random()分别为100个雪花生成半径、坐标(X、Y);

那我们这里是100个雪花,所以为了方便后面操作,就用一个数组保存这100个雪花对象。

JavaScript代码如下:

//雪花数目var snow = 100;//雪花坐标、半径var arr = []; //保存各圆坐标及半径for (var i = 0; i < snow; i++) {arr.push({x: Math.random() * wid,y: Math.random() * hei,r: Math.random() * 10 + 1})}

4、绘制雪花

上面我们已经将100个雪花半径、坐标(X、Y)生成,下面就是循环使用canvas画出雪花了(这里就是画圆),这里定义一个函数

JavaScript代码如下:

//画雪花
function DrawSnow() {
    ctx.fillStyle="white";
    ctx.beginPath();
    for (var i = 0; i < snow; i++) {
        var p = arr[i];
        ctx.moveTo(p.x,p.y);
        ctx.arc(p.x,p.y,p.r,0,2*Math.PI,false);
    }
    ctx.fill();

    ctx.closePath();
                
}

然后调用 DrawSnow()函数,效果如下:

HTML5 canvas绘制雪花飘落动画(需求分析、知识点、程序编写分布详解)

可以尝试多次刷新网页看是否会生成不同大小、位置的雪花(正常情况下是可以的),做到这里就已经接近最终效果了

注意:由于这里需要绘制100个圆,所以每当画一个圆时重新定义绘制开始坐标即:ctx.moveTo(p.x,p.y);否则会出现异样效果,不信可以试试呀

5、雪花飘动

上面我们已经画出100个雪花,可惜只能依靠刷新网页才能看到变化效果,但是我们需要实现的是雪花不停的移动位置。

首先我们需要借助setInterval函数不停的重画雪花,这里间隔时间为50毫秒:setInterval(DrawSnow,50);

同时每一朵雪花的坐标(X、Y)需要不停的改变(在一定幅度内),我们这里的雪花是从左上方飘落到右下方,所以每朵X、Y坐标值都在不停的增大,那我们用一个函数SnowFall()定义雪花飘过规则

该函数代码如下:

//雪花飘落function SnowFall() {    for (var i = 0; i < snow; i++) {        var p = arr[i];        p.y += Math.random() * 2 + 1;        if (p.y > hei) {            p.y = 0;        }        p.x += Math.random() * 2 + 1;        if (p.x > wid) {            p.x = 0;    <span style="white-space:pre">    </span>}    }}

然后将该函数放入DrawSnow()执行,注意:我们每隔50毫毛重画雪花,必须擦除画布,所以DrawSnow()函数体内必须在前面执行clearRect()函数,即:ctx.clearRect(0, 0, wid, hei);

此时DrawSnow函数定义如下:

//画雪花function DrawSnow() {    ctx.clearRect(0, 0, wid, hei);    ctx.fillStyle = "white";    ctx.beginPath();    for (var i = 0; i < snow; i++) {        var p = arr[i];        ctx.moveTo(p.x, p.y);        ctx.arc(p.x, p.y, p.r, 0, 2 * Math.PI, false);    }    ctx.fill();    SnowFall();    ctx.closePath();}

最后执行setInterval(DrawSnow, 50);

OK,经过我们上述步骤,小伙伴们是否已经对整个过程及技术实现很清晰了。


完整代码如下(大家可以直接复制到自己项目中执行,测试下效果):

<!DOCTYPE html><html>    <head>        <meta charset="utf-8" />        <title></title>        <script src="js/jquery-1.8.3.min.js"></script>        <style type="text/css">            * {                margin: 0;                padding: 0;            }                        #mycanvas {                background: black;            }        </style>    </head>    <body>        <canvas id="mycanvas">            您的浏览器不支持canvas画布        </canvas>        <script>            //获取mycanvas画布            var can = document.getElementById("mycanvas");            var ctx = can.getContext("2d");            //画布宽度            var wid = window.innerWidth;            //画布高度            var hei = window.innerHeight;            can.width = wid;            can.height = hei;            //雪花数目            var snow = 100;            //雪花坐标、半径            var arr = []; //保存各圆坐标及半径            for (var i = 0; i < snow; i++) {                arr.push({                    x: Math.random() * wid,                    y: Math.random() * hei,                    r: Math.random() * 10 + 1                })            }            //画雪花            function DrawSnow() {                ctx.clearRect(0, 0, wid, hei);                ctx.fillStyle = "white";                ctx.beginPath();                for (var i = 0; i < snow; i++) {                    var p = arr[i];                    ctx.moveTo(p.x, p.y);                    ctx.arc(p.x, p.y, p.r, 0, 2 * Math.PI, false);                }                ctx.fill();                SnowFall();                ctx.closePath();            }            //雪花飘落            function SnowFall() {                for (var i = 0; i < snow; i++) {                    var p = arr[i];                    p.y += Math.random() * 2 + 1;                    if (p.y > hei) {                        p.y = 0;                    }                    p.x += Math.random() * 2 + 1;                    if (p.x > wid) {                        p.x = 0;                    }                }            }            setInterval(DrawSnow, 50);        </script>    </body></html>

好了,今天分享就到这里,我现在都写到半夜了哟(此刻:2016年3月8日00:22:27),没有功劳也有苦劳啊,大家都给我评论下嘛

以后还有更多哟,请大家一起来交流下。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Python进阶者 Python进阶者
2年前
Canvas之鼠标滑动特效
大家好,我是皮皮。我们会看到很多网页的粒子特效;如上图所示,这些都是借助HTML新特性,使用新增标签Canvas得到的效果;那么我们来了解下canvas。什么是Canvas在MDN中是这样定义  的: 是HTML5新增的元素,可用于通过使用JavaScript中的脚本来绘制图形。例如,它可以用于绘制图形、制作照片、创建动画,甚至可以进行实时
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
03.Android崩溃Crash库之ExceptionHandler分析
目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃
Stella981 Stella981
2年前
Android用Canvas画一个真正能跑的跑马灯
以前自学,都是用帧动画来实现跑马灯,这几天常失眠,晚上学东西也学不进,所以用Canvas写个小Demo,这么无聊的应该只有我一个了吧,废话不多说,下面上内容。老规矩,最后有源码效果图如下
Stella981 Stella981
2年前
Android 应用的动画实践
<h2id"menuIndex0"前言</h2<p尝试搜索了一下android动画的中文资料,很多都是一些枯燥的翻译api的一些文档,很少有系统讲解如何利用动画开发一个应用的资料,忽然,发现很多应用也不怎么注重动画在app的应用,想了想,自己尝试总结一下吧。因为,本人也不是什么动画制作师,没法把动画做得很绚丽,只好,利用内置的效果,进行简单加工
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这