zoukankan      html  css  js  c++  java
  • 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">
  • 相关阅读:
    【codecombat】 试玩全攻略 第九关 循环又循环
    【codecombat】 试玩全攻略 第十三关 已知敌人
    【codecombat】 试玩全攻略 第十一关 再次迷宫经历
    【codecombat】 试玩全攻略 第六关 cell commentary
    【codecombat】 试玩全攻略 第八关 火舞
    【codecombat】 试玩全攻略 第十二关 恐惧之门
    【codecombat】 试玩全攻略 第十四关 已知敌人
    苹果apns推送总结
    Xcode 提升速度小技巧
    UITextField 限制输入字数
  • 原文地址:https://www.cnblogs.com/jackson-yqj/p/10369815.html
Copyright © 2011-2022 走看看