• [js高手之路]html5 canvas动画教程


    利用canvas,实现一个下雪的效果,我们先预览下效果:

     

    我们先分析下这个效果:

    1,随机产生雪花

    2,雪花的产生不是同时产生,而是有先后顺序的

    3,雪花怎么表示

    4,怎么源源不断的下雪

    5,雪花有大有小

    搞清楚上面几个问题之后,这个效果基本上就实现了,

    首先,由于这个是全屏效果,我采用动态创建canvas,把整个浏览器的宽与高赋值给canvas

     1         var Canvas = function (w, h) {
     2                 this.width = w;
     3                 this.height = h;
     4             }
     5             Canvas.prototype = {
     6                 init: function () {
     7                     var oC = document.createElement("canvas");
     8                     oC.setAttribute('width', this.width);
     9                     oC.setAttribute('height', this.height);
    10                     oC.setAttribute('id', 'canvas');
    11                     oC.style.backgroundColor = '#000';
    12                     document.body.appendChild(oC);
    13                 }
    14             }
    15             var curWinWidth = window.innerWidth,
    16                 curWinHeight = window.innerHeight;
    17             var oCanvas = new Canvas(curWinWidth, curWinHeight);
    18             oCanvas.init();

    调用oCanvas对象的init方法之后,就会在body的最后面追加一个canvas,id为canvas,宽、高与浏览器的宽、高相同,背景为黑色,晚上下雪的效果

    接下来,有了舞台,演员该上场了,怎么产生雪花呢?这里把下雪相关的操作,封装成一个类,他的基本结构如下:

    var Snow = function(){}

    Snow.prototype = {

      init : function(){},

      draw : function( cxt ) {},

      update : function(){}

    }

    这个类一共有三个方法( init, draw, update ).

    init:初始化雪花的位置( x, y 坐标 )、速度、半径( 雪花的大小,在这里我们把雪花用半径不同的圆表示 )

                function random(min, max) {
                    return Math.random() * (max - min) + min;
                }
    
                init: function () {
                        this.x = random(0, width);
                        this.y = 0;
                        this.r = random(1, 5);
                        this.vy = random(3, 5);
                    }

    那么init 加上 这个random函数 就可以完成雪花的初始化

    1,雪花出来的时候,一般是在屏幕的最上方出现的,所以雪花的y坐标都是0,  其次,雪花的x坐标是随机的,他的范围是从屏幕的左边到右边,那么就是 0 ~ width. 这个width就是canvas的宽度,也就是浏览器的宽度

    2,雪花的半径r, 设置为1 ~ 5之间的任意值

    3,雪花下降的速度设置为3 ~ 5之间的随机速度,这里我做的下雪是垂直方向往下飘,你可以拓展,考虑风力影响( 这个时候肯定有水平方向的速度 )

    有了这些初始化的参数之后,我们完善draw方法,绘制雪花:

    1                 draw: function (cxt) {
    2                     cxt.beginPath();
    3                     cxt.fillStyle = 'white';
    4                     cxt.arc(this.x, this.y + this.r, this.r, 0, Math.PI * 2, false);
    5                     cxt.fill();
    6                     cxt.closePath();
    7                     this.update(cxt);
    8                 },

    参数cxt就是canvas的上下文,这个函数很简单,就是一个arc方法调用init中设置的值来画圆(雪花),在该方法的最后调用了一个update方法,他是干嘛的?他是更新雪花在垂直方向的速度

                 update: function (cxt) {
                        if (this.y < height - this.r) {
                            this.y += this.vy;
                        } else {
                            this.init();
                        }
                    }

    在update方法中,我们做了边界判断: 雪花往下飘落的时候,肯定会消失,消失之后怎么处理?没有到达边界怎么处理?

    canvas的高度减去雪花的半径,这就是雪花要消失时候的边界,所以this.y  < height - this.r  如果这个条件成立,那么说明雪花一直在飘着,我们就要把雪花的y方向的位置更新,雪花看起来(‘正在下雪’),当一个雪花快要消失的时候,我们再把他移动到初始的位置,这样看起来就是在圆圆不断的下雪,而不需要重新绘制雪花(如果这样做,肯定会影响性能,这个特效最后肯定会被卡死,这个小技巧很多类似的特效都会用到)。至此核心的流程已经搞定,接下来,我们就要大量的生成雪花了。

    1             var snow = [];
    2             for (var i = 0; i < 500; i++) {
    3                 setTimeout(function () {
    4                     var oSnow = new Snow();
    5                     oSnow.init();
    6                     snow.push(oSnow);
    7                 }, 10 * i);
    8             }

    生成500个雪花,不是同时生成的,然后把这些雪花保存到数组snow中.

    然后,开启定时器,让雪花不断的飘落吧,

    关于requestAnimationFrame的使用,可以参考我的这篇文章:[js高手之路] html5新增的定时器requestAnimationFrame实战进度条

    1              (function move() {
    2                 oGc.clearRect(0, 0, width, height);
    3                 for (var i = 0; i < snow.length; i++) {
    4                     snow[i].draw(oGc);
    5                 }
    6                 requestAnimationFrame(move);
    7             })();

    完整的demo代码:

     1 <head>
     2     <meta charset="UTF-8">
     3     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     4     <meta http-equiv="X-UA-Compatible" content="ie=edge">
     5     <title>雪花效果 - by ghostwu</title>
     6     <!-- <script src="lib.js"></script> -->
     7     <style>
     8         * {
     9             margin: 0;
    10             padding: 0;
    11         }
    12 
    13         body {
    14             overflow: hidden;
    15         }
    16     </style>
    17 </head>
    18 
    19 <body>
    20     <script>
    21         window.onload = function () {
    22             var Canvas = function (w, h) {
    23                 this.width = w;
    24                 this.height = h;
    25             }
    26             Canvas.prototype = {
    27                 init: function () {
    28                     var oC = document.createElement("canvas");
    29                     oC.setAttribute('width', this.width);
    30                     oC.setAttribute('height', this.height);
    31                     oC.setAttribute('id', 'canvas');
    32                     oC.style.backgroundColor = '#000';
    33                     document.body.appendChild(oC);
    34                 }
    35             }
    36             var curWinWidth = window.innerWidth,
    37                 curWinHeight = window.innerHeight;
    38             var oCanvas = new Canvas(curWinWidth, curWinHeight);
    39             oCanvas.init();
    40 
    41             var oC = document.querySelector('#canvas');
    42             var width = oC.width, height = oC.height, oGc = oC.getContext('2d');
    43 
    44             function random(min, max) {
    45                 return Math.random() * (max - min) + min;
    46             }
    47             var Snow = function () {
    48 
    49             }
    50             Snow.prototype = {
    51                 init: function () {
    52                     this.x = random(0, width);
    53                     this.y = 0;
    54                     this.r = random(1, 5);
    55                     this.vy = random(3, 5);
    56                 },
    57                 draw: function (cxt) {
    58                     cxt.beginPath();
    59                     cxt.fillStyle = 'white';
    60                     cxt.arc(this.x, this.y + this.r, this.r, 0, Math.PI * 2, false);
    61                     cxt.fill();
    62                     cxt.closePath();
    63                     this.update(cxt);
    64                 },
    65                 update: function (cxt) {
    66                     if (this.y < height - this.r) {
    67                         this.y += this.vy;
    68                     } else {
    69                         this.init();
    70                     }
    71                 }
    72             }
    73 
    74             var snow = [];
    75             for (var i = 0; i < 500; i++) {
    76                 setTimeout(function () {
    77                     var oSnow = new Snow();
    78                     oSnow.init();
    79                     snow.push(oSnow);
    80                 }, 10 * i);
    81             }
    82 
    83             (function move() {
    84                 oGc.clearRect(0, 0, width, height);
    85                 for (var i = 0; i < snow.length; i++) {
    86                     snow[i].draw(oGc);
    87                 }
    88                 requestAnimationFrame(move);
    89             })();
    90         }
    91     </script>
    92 </body>
    View Code
  • 相关阅读:
    Hadoop Gateway 部署
    java 命令--备忘
    整理下常用硬件性能参数
    python 脚本备份 mysql 数据库到 OSS
    pip 更换国内源
    记录闭包和立即执行函数
    Django 中文乱码问题&富文本显示
    mysql exceeded the 'max_questions' resource 记录
    sql server 数据字典的妙用
    Sublime Text指南
  • 原文地址:https://www.cnblogs.com/ghostwu/p/7690639.html
Copyright © 2020-2023  润新知