• Canvas动画(PC端 移动端)


    Canvas动画(PC端 移动端)

    一,介绍与需求

     1.1,介绍

    canvas是HTML5中新增一个HTML5标签与操作canvas的javascript API,它可以实现在网页中完成动态的2D与3D图像技术。<canvas> 标记和 SVG以及 VML 之间的一个重要的不同是,<canvas> 有一个基于 JavaScript 的绘图 API,而 SVG 和 VML 使用一个 XML 文档来描述绘图。SVG 绘图很容易编辑与生成,但功能明显要弱一些。canvas可以完成动画、游戏、图表、图像处理等原来需要Flash完成的一些功能

     1.2,需求

    实现特殊的动画效果

    二,动画实现

    以跟随鼠标/手指移动的火为例

    第一步:创建Canvas标签

    1 <canvas id="fire"></canvas>

    第二步:获取Canvas标签

    1  let canvas = document.getElementById('fire');
    2 if (canvas.getContext){
    3    var ctx = canvas.getContext('2d');
    4    // drawing code here
    5  } else {
    6    alert("不支持Canvas")
    7  }

    第三步:绘制火花

     1 var Spark = function (mouse) {
     2 
     3             this.cx = mouse.x;
     4             this.cy = mouse.y;
     5             this.x = rand(this.cx - 40, this.cx + 40);
     6             this.y = rand(this.cy, this.cy + 5);
     7             this.lx = this.x;
     8             this.ly = this.y;
     9             this.vy = rand(1, 3);
    10             this.vx = rand(-4, 4);
    11             this.r = rand(0, 1);
    12             this.life = rand(4, 5);
    13             this.alive = true;
    14             this.c = {
    15 
    16                 h: Math.floor(rand(2, 40)),
    17                 s: 100,
    18                 l: rand(40, 100),
    19                 a: rand(0.8, 0.9)
    20 
    21             }
    22 
    23         }
    24         Spark.prototype.update = function () {
    25 
    26             this.lx = this.x;
    27             this.ly = this.y;
    28 
    29             this.y -= this.vy;
    30             this.x += this.vx;
    31 
    32             if (this.x < this.cx)
    33                 this.vx += 0.2;
    34             else
    35                 this.vx -= 0.2;
    36 
    37             this.vy += 0.08;
    38             this.life -= 0.1;
    39 
    40             if (this.life <= 0) {
    41 
    42                 this.c.a -= 0.05;
    43 
    44                 if (this.c.a <= 0)
    45                     this.alive = false;
    46 
    47             }
    48 
    49         }
    50         Spark.prototype.draw = function (ctx) {
    51 
    52             ctx.beginPath();
    53             ctx.moveTo(this.lx, this.ly);
    54             ctx.lineTo(this.x, this.y);
    55             ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 2) + ")";
    56             ctx.lineWidth = this.r * 2;
    57             ctx.lineCap = 'round';
    58             ctx.stroke();
    59             ctx.closePath();
    60 
    61             ctx.beginPath();
    62             ctx.moveTo(this.lx, this.ly);
    63             ctx.lineTo(this.x, this.y);
    64             ctx.strokeStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
    65             ctx.lineWidth = this.r;
    66             ctx.stroke();
    67             ctx.closePath();
    68 
    69         }

    第四步:绘制火焰

     1     var Flame = function (mouse) {
     2 
     3             this.cx = mouse.x;
     4             this.cy = mouse.y;
     5             this.x = rand(this.cx - 25, this.cx + 25);
     6             this.y = rand(this.cy - 5, this.cy + 5);
     7             this.vy = rand(1, 3);
     8             this.vx = rand(-1, 1);
     9             this.r = rand(20, 30);
    10             this.life = rand(3, 6);
    11             this.alive = true;
    12             this.c = {
    13 
    14                 h: Math.floor(rand(2, 40)),
    15                 s: 100,
    16                 l: rand(80, 100),
    17                 a: 0,
    18                 ta: rand(0.8, 0.9)
    19 
    20             }
    21 
    22 
    23         }
    24         Flame.prototype.update = function () {
    25 
    26             this.y -= this.vy;
    27             this.vy += 0.05;
    28 
    29 
    30             this.x += this.vx;
    31 
    32             if (this.x < this.cx)
    33                 this.vx += 0.1;
    34             else
    35                 this.vx -= 0.1;
    36 
    37 
    38 
    39 
    40             if (this.r > 0)
    41                 this.r -= 0.1;
    42 
    43             if (this.r <= 0)
    44                 this.r = 0;
    45 
    46 
    47 
    48             this.life -= 0.15;
    49 
    50             if (this.life <= 0) {
    51 
    52                 this.c.a -= 0.05;
    53 
    54                 if (this.c.a <= 0)
    55                     this.alive = false;
    56 
    57             } else if (this.life > 0 && this.c.a < this.c.ta) {
    58 
    59                 this.c.a += .08;
    60 
    61             }
    62 
    63         }
    64         Flame.prototype.draw = function (ctx) {
    65 
    66             ctx.beginPath();
    67             ctx.arc(this.x, this.y, this.r * 3, 0, 2 * Math.PI);
    68             ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + (this.c.a / 20) + ")";
    69             ctx.fill();
    70 
    71             ctx.beginPath();
    72             ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
    73             ctx.fillStyle = "hsla( " + this.c.h + ", " + this.c.s + "%, " + this.c.l + "%, " + this.c.a + ")";
    74             ctx.fill();
    75 
    76         }

    第五步:绘制火

      1     var Fire = function () {
      2 
      3             this.canvas = document.getElementById('fire');
      4             this.ctx = this.canvas.getContext('2d');
      5             this.canvas.height = window.innerHeight;// window.innerHeight
      6             this.canvas.width = window.innerWidth;//window.innerWidth
      7 
      8             this.aFires = [];
      9             this.aSpark = [];
     10             this.aSpark2 = [];
     11 
     12 
     13 
     14             this.mouse = {
     15                 x: this.canvas.width * .5,
     16                 y: this.canvas.height * .75,
     17             }
     18 
     19 
     20 
     21             this.init();
     22 
     23         }
     24         Fire.prototype.init = function () {
     25             //跳转语句
     26             if (system.win || system.mac || system.xll) {
     27                 this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端
     28             } else {
     29                 this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端
     30             }
     31 
     32 
     33         }
     34         Fire.prototype.run = function () {
     35 
     36             this.update();
     37             this.draw();
     38 
     39             if (this.bRuning)
     40                 requestAnimationFrame(this.run.bind(this));
     41 
     42         }
     43         Fire.prototype.start = function () {
     44 
     45             this.bRuning = true;
     46             this.run();
     47 
     48         }
     49         Fire.prototype.stop = function () {
     50 
     51             this.bRuning = false;
     52 
     53         }
     54         Fire.prototype.update = function () {
     55 
     56             this.aFires.push(new Flame(this.mouse));
     57             this.aSpark.push(new Spark(this.mouse));
     58             this.aSpark2.push(new Spark(this.mouse));
     59 
     60 
     61 
     62             for (var i = this.aFires.length - 1; i >= 0; i--) {
     63 
     64                 if (this.aFires[i].alive)
     65                     this.aFires[i].update();
     66                 else
     67                     this.aFires.splice(i, 1);
     68 
     69             }
     70 
     71             for (var i = this.aSpark.length - 1; i >= 0; i--) {
     72 
     73                 if (this.aSpark[i].alive)
     74                     this.aSpark[i].update();
     75                 else
     76                     this.aSpark.splice(i, 1);
     77 
     78             }
     79 
     80 
     81             for (var i = this.aSpark2.length - 1; i >= 0; i--) {
     82 
     83                 if (this.aSpark2[i].alive)
     84                     this.aSpark2[i].update();
     85                 else
     86                     this.aSpark2.splice(i, 1);
     87 
     88             }
     89 
     90         }
     91 
     92         Fire.prototype.draw = function () {
     93 
     94             this.ctx.globalCompositeOperation = "source-over";
     95             this.ctx.fillStyle = "rgba( 15, 5, 2, 1 )";
     96             this.ctx.fillRect(0, 0, window.innerWidth, window.innerHeight);
     97 
     98             this.grd = this.ctx.createRadialGradient(this.mouse.x, this.mouse.y - 200, 200, this.mouse.x, this.mouse.y - 100, 0);
     99             this.grd.addColorStop(0, "rgb( 15, 5, 2 )");
    100             this.grd.addColorStop(1, "rgb( 30, 10, 2 )");
    101             this.ctx.beginPath();
    102             this.ctx.arc(this.mouse.x, this.mouse.y - 100, 200, 0, 2 * Math.PI);
    103             this.ctx.fillStyle = this.grd;
    104             this.ctx.fill();
    105 
    106 
    107             this.ctx.font = "15em Amatic SC";
    108             this.ctx.textAlign = "center";
    109             this.ctx.strokeStyle = "rgb(50, 20, 0)";
    110             this.ctx.fillStyle = "rgb(120, 10, 0)";
    111             this.ctx.lineWidth = 2;
    112             this.ctx.strokeText("", this.canvas.width / 2, this.canvas.height * .72);
    113             this.ctx.fillText("", this.canvas.width / 2, this.canvas.height * .72);
    114 
    115 
    116 
    117             this.ctx.globalCompositeOperation = "overlay";//or lighter or soft-light
    118 
    119             for (var i = this.aFires.length - 1; i >= 0; i--) {
    120 
    121                 this.aFires[i].draw(this.ctx);
    122 
    123             }
    124 
    125             this.ctx.globalCompositeOperation = "soft-light";//"soft-light";//"color-dodge";
    126 
    127             for (var i = this.aSpark.length - 1; i >= 0; i--) {
    128 
    129                 if ((i % 2) === 0)
    130                     this.aSpark[i].draw(this.ctx);
    131 
    132             }
    133 
    134 
    135             this.ctx.globalCompositeOperation = "color-dodge";//"soft-light";//"color-dodge";
    136 
    137             for (var i = this.aSpark2.length - 1; i >= 0; i--) {
    138 
    139                 this.aSpark2[i].draw(this.ctx);
    140 
    141             }
    142 
    143 
    144         }
    145 
    146         Fire.prototype.updateMouse = function (e) {
    147             //跳转语句
    148             if (system.win || system.mac || system.xll) {//PC端
    149                 this.mouse.x = e.clientX;
    150                 this.mouse.y = e.clientY;
    151             } else {//移动端
    152                 e.preventDefault();//阻止默认行为
    153                 this.mouse.x = e.changedTouches[0].clientX;
    154                 this.mouse.y = e.changedTouches[0].clientY;
    155             }
    156 
    157 
    158         }

    第六步:调用

    1 var oCanvas;
    2         init = function () {
    3 
    4             oCanvas = new Fire();
    5             oCanvas.start();
    6 
    7 
    8         }
    9         window.onload = init;

    随机数函数

    1  rand = function (min, max) { return Math.random() * (max - min) + min; };

    效果如下:

    三,PC端与移动端处理

    3.1,判断是PC端还是移动端

     1     //平台、设备和操作系统
     2         var system = {
     3             win: false,
     4             mac: false,
     5             xll: false
     6         };
     7         //检测平台
     8         var p = navigator.platform;
     9         system.win = p.indexOf("Win") == 0;
    10         system.mac = p.indexOf("Mac") == 0;
    11         system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
    12 
    13 //跳转语句
    14             if (system.win || system.mac || system.xll) {
    15                 this.canvas.addEventListener('mousemove', this.updateMouse.bind(this), false);//PC端 鼠标移动
    16             } else {
    17                 this.canvas.addEventListener('touchmove', this.updateMouse.bind(this), false);//移动端 手指滑动
    18             }

    3.2,PC端还是移动端的事件处理

    1 //跳转语句
    2             if (system.win || system.mac || system.xll) {//PC端
    3                 this.mouse.x = e.clientX;
    4                 this.mouse.y = e.clientY;
    5             } else {//移动端
    6                 e.preventDefault();//阻止默认行为
    7                 this.mouse.x = e.changedTouches[0].clientX;
    8                 this.mouse.y = e.changedTouches[0].clientY;
    9             }

     移动端需禁止缩放

    1     <meta name="viewport" content="target-densitydpi=320,width=640,user-scalable=no">
  • 相关阅读:
    Socket
    利用Python自动生成暴力破解的字典
    【转】六年测试工作的思考1
    【转】手机测试入行三年的感想
    【转】移动测试人员的未来:测试开发技术的融合
    【转】一个互联网项目即将结束的软件测试经验总结
    【转】电子商务网站测试经验总结
    【转】六年软件测试感悟-从博彦到VMware
    使用PL/SQL删除百万条记录的大表
    【转】百万级数据查询优化
  • 原文地址:https://www.cnblogs.com/jackson-yqj/p/10369815.html
Copyright © 2020-2023  润新知