你的位置:首页 > Java教程

[Java教程]使用JavaScript和Canvas实现下雪动画效果


该下雪动画效果使用了HTML5中Canvas画布实现,其中涉及了物理学中曲线运动的相关知识与运算。

index.html

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" name="viewport">  <meta content="yes" name="apple-mobile-web-app-capable">  <meta content="black" name="apple-mobile-web-app-status-bar-style">  <meta content="telephone=no" name="format-detection">  <meta content="email=no" name="format-detection">  <title>Snow</title>  <link rel="stylesheet" href="css/main.css"></head><body>  <canvas id="canvas"></canvas>  <script src="js/snow.js"></script>  <script>    window.addEventListener('load', function(){      this.snow = new Snow();      // 初始化snow对象并开始下雪动画      snow.init().start();    });  </script></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

main.css

html, body{  width: 100%;  height: 100%;  overflow: hidden;  margin: 0;  padding: 0;  background-color: #000;  font-family: 微软雅黑, 华文细黑, 黑体;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Snow.js

(function(exports, undefined){  'use strict';  var document = exports.document;  function Snow(){    this.colors = ['#fff'];    this.balls = [];    this.windDirection = -1;    this.ballRadius = 3;    this.ballsPerFrame = 2;    this.timeInterval = 40;    this.windDirectionChangedInterval = 5000;    this.accumulativeTime = 0;    return this;  };  exports.Snow = Snow;  Snow.prototype = {    init: function(args){      for(var p in args){        this[p] = args[p];      }      this.canvas = this.canvas || document.querySelector('#canvas');      this.context = this.context || this.canvas.getContext('2d');      this.canvasWidth = this.canvasWidth || document.body.offsetWidth || document.body.clientWidth;      this.canvasHeight = this.canvasHeight || document.body.offsetHeight || document.body.clientHeight;      this.canvas.width = this.canvasWidth;      this.canvas.height = this.canvasHeight;      return this;    },    start: function(){      this.timer = this.timer || setTimeout(this.frame.bind(this), this.timeInterval);      return this;    },    frame: function(){      this.accumulativeTime += this.timeInterval;      (this.accumulativeTime % this.windDirectionChangedInterval < this.timeInterval) && (this.windDirection *= -1);      this.render.call(this);      this.update.call(this);      this.timer = null;      this.timer = setTimeout(this.frame.bind(this), this.timeInterval);    },    update: function(){      this.addBalls.call(this);      this.updateBalls.call(this);    },    updateBalls: function(){      var balls = this.balls,        len = balls.length,        i = 0,        cnt = 0;      for(;i<len;i++){        balls[i].x += balls[i].vx * this.windDirection;        balls[i].y += balls[i].vy;        balls[i].vy += balls[i].g * balls[i].t;        balls[i].t += this.timeInterval;        if(balls[i].y - this.ballRadius < this.canvasHeight){          balls[cnt++] = balls[i];        }      }      while(len>cnt){        balls.pop();        len--;      }    },    addBalls: function(){      var ball,        i = 0,        len = this.ballsPerFrame,        _this = this;      for(;i<len;i++){        ball = {          x: Math.pow(-1, Math.ceil(Math.random() * 1000)) * Math.floor(Math.random() * _this.canvasWidth * 1.5),          y: Math.floor(Math.random() * this.ballRadius) * -1,          g: 0.00005,          vx: 1 + Math.floor(Math.random() * 2),          vy: 2 + Math.floor(Math.random() * 5),          t: 0,          color: _this.colors[Math.floor(Math.random() * _this.colors.length)]        }        this.balls.push(ball);      }    },    render: function(){      var cxt = this.context,        i = 0,        len = this.balls.length;      cxt.clearRect(0, 0, this.canvasWidth, this.canvasHeight);      for(;i<len;i++){        cxt.fillStyle = this.balls[i].color;        cxt.beginPath();        cxt.arc(this.balls[i].x, this.balls[i].y, this.ballRadius, 0, 2 * Math.PI, true);        cxt.closePath();        cxt.fill();      }    },    pause: function(){      clearTimeout(this.timer);      this.timer = null;    },    resume: function(){      this.start.call(this);    },    clear: function(){      clearTimeout(this.timer);      this.timer = null;      this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight);    }  }})(window);