• HTML5 Canvas火焰效果 像火球发射一样


    Canvas是HTML5中非常重要而且有用的东西,我们可以在Canvas上绘制任意的元素,就像你制作Flash一样。今天我们就在Canvas上来制作一款火焰发射的效果。就像古代的火球炮一样,而且可以在浏览器边缘反弹,感觉会比较屌。来看看效果图:

    我们可以在这里查看火焰球的DEMO演示

    当然,我们要来分析一下源代码,主要是一些JS代码。

    首先很简单地在页面上放一个canvas标签,并且给它点简单的样式:

    <canvas></canvas>
    canvas{
      position: absolute;
      height: 100%;
      width: 100%;
      left: 0;
      top: 0;
      cursor: crosshair;
    }

    接下来就来分析一下JS代码。我们来逐步分解JS。

    由于这个是二维动画,所以我们利用canvas的getContext方法来返回一个对象,这个对象包含我们对二维动画操作的API,代码如下:

    canvas = document.querySelector('canvas');
    ctx = canvas.getContext('2d');

    下面我们来定义粒子:

    particles = {};
    newParticle = (function(){
      var nextIndex = 0;
      return function(x,y,r,o,c,xv,yv,rv,ov){
        particles[++nextIndex] = {
          index: nextIndex,
          x: x,
          y: y,
          r: r,
          o: o,
          c: c,
          xv: xv,
          yv: yv,
          rv: rv,
          ov: ov
        };
      };
    })();

    然后我们来定义火球:

    fireballs = {};
    newFireball = (function(){
      var nextIndex = 0;
      return function(x,y,xv,yv,life){
        fireballs[++nextIndex] = {
          index: nextIndex,
          x: x,
          y: y,
          xv: xv,
          yv: yv,
          life: life
        };
      };
    })();

    这里life表示火球的生命周期,下面我们可以看到,life值会随着火球发射力度的改变而改变。

    接下来是定义鼠标拖动弹弓,准备发射火球:

    mouse = {x:0,y:0,d:0};
    onmousemove = function(e){
      mouse.x = e.clientX-o.x;
      mouse.y = e.clientY-o.y;
      var dx = mouse.x - pos1.x,
          dy = mouse.y - pos1.y;
      mouse.d = Math.sqrt(dx*dx+dy*dy);
    };
    
    charging = false;
    pos1 = {x:0,y:0};
    showInstructions = true;
    onmousedown = function(e){
      pos1.x = mouse.x;
      pos1.y = mouse.y;
      charging = true;
      showInstructions = false;
    };
    
    onmouseup = function(){
      if(charging){
        newFireball(
          mouse.x,
          mouse.y,
          (pos1.x-mouse.x)*0.03,
          (pos1.y-mouse.y)*0.03,
          600
        );
        charging = false;
      }
    };

    可以看到,当鼠标按键弹起时,新建一个火球,并初始化life值。

    下面是火球运动时的动画执行代码,包括碰到浏览器边缘时的反射效果:

    time = 0;
    requestAnimationFrame(loop = function(){
      ctx.setTransform(1,0,0,1,0,0);
      ctx.globalCompositeOperation = 'source-over';
      ctx.globalAlpha = 1;
      ctx.fillStyle = bgColor;
      ctx.fillRect(0,0,width,height);
      
      ctx.translate(o.x,o.y);
      
      if(charging){
        var c = Math.floor(30+mouse.d/2);
        ctx.strokeStyle = 'rgba('+c+','+c+','+c+',1)';
        ctx.lineWidth = 4;
        ctx.beginPath();
        ctx.moveTo(pos1.x,pos1.y);
        ctx.lineTo(mouse.x,mouse.y);
        ctx.lineCap = 'round';
        ctx.stroke();
      }
      
      if(showInstructions){
        pos1.x = -70;
        pos1.y = -35;
        
        if(time<10){
          var x = -70,
              y = -35,
              r = 30-time*2,
              a = time/10;
        }else if(time<80){
          var x = (time-10)*2-70,
              y = (time-10)-35,
              r = 10,
              a = 1;
        }else if(time<90){
          var x = 70,
              y = 35,
              r = 10+(time-80)*2,
              a = 1-(time-80)/10;
        }else if(time<140){
          var x = 70,
              y = 35,
              r = 30,
              a = 0;
        }
        var dx = pos1.x-x,
            dy = pos1.y-y,
            d = Math.sqrt(dx*dx+dy*dy);
        if(time<80&&time>10){
          ctx.globalCompositeOperation = 'source-over';
          ctx.globalAlpha = 1;
          var c = Math.floor(30+d/2);
          ctx.strokeStyle = 'rgba('+c+','+c+','+c+',1)';
          ctx.lineWidth = 4;
          ctx.beginPath();
          ctx.moveTo(pos1.x,pos1.y);
          ctx.lineTo(x,y);
          ctx.lineCap = 'round';
          ctx.stroke();
        }
        if(time<140){
          ctx.globalCompositeOperation = 'source-over';
          ctx.globalAlpha = a;
          ctx.beginPath();
          ctx.arc(x,y,r,0,Math.PI*2);
          ctx.lineWidth = 2;
          ctx.strokeStyle = '#aaa';
          ctx.stroke();
        }
        if(time==80){
          newFireball(
            x,
            y,
            dx*0.03,
            dy*0.03,
            240
          );
        }
        time = (time+1)%180;
      }
      
      ctx.globalCompositeOperation = 'lighter';
      for(var i in particles){
        var p = particles[i];
        ctx.beginPath();
        ctx.arc(p.x,p.y,p.r,0,Math.PI*2);
        ctx.globalAlpha = p.o;
        ctx.fillStyle = p.c;
        ctx.fill();
      }
      
      for(var i in particles){
        var p = particles[i];
        p.x += p.xv;
        p.y += p.yv;
        p.r += p.rv;
        p.o += p.ov;
        if(p.r<0)delete particles[p.index];
        if(p.o<0)delete particles[p.index];
      }
      
      for(var i in fireballs){
        f = fireballs[i];
        var numParticles = Math.sqrt(f.xv*f.xv+f.yv*f.yv)/5;
        if(numParticles<1)numParticles=1;
        var numParticlesInt = Math.ceil(numParticles),
            numParticlesDif = numParticles/numParticlesInt;
        for(var j=0;j<numParticlesInt;j++){
          newParticle(
            f.x-f.xv*j/numParticlesInt,
            f.y-f.yv*j/numParticlesInt,
            7,
            numParticlesDif,
            particleColor,
            Math.random()*0.6-0.3,
            Math.random()*0.6-0.3,
            -0.3,
            -0.05*numParticlesDif
          );
        }
        f.x += f.xv;
        f.y += f.yv;
        f.yv += gravity;
        var boundary;
        if(f.y<(boundary = edge.top+7)){
          f.y = boundary;
          f.yv *= -1;
        }else if(f.y>(boundary = edge.bottom-7)){
          f.y = boundary;
          f.yv *= -1;
        }
        if(f.x>(boundary = edge.right-7)){
          f.x = boundary;
          f.xv *= -1;
        }else if(f.x<(boundary = edge.left+7)){
          f.x = boundary;
          f.xv *= -1;
        }
        if(--f.life<0)delete fireballs[f.index];
      }
      
      requestAnimationFrame(loop);
    });

    这款HTML5 Canvas火球动画就到这里了,js代码比较多,最终的源码可以到这里下载,下载地址>>

  • 相关阅读:
    Flash性能相关
    穿过某点绘制曲线
    oracle 动态列
    oracle 失效对象自动重新编译
    EBS 重新编译无效对象 invalid object
    oracle ebs Customer Info
    Oracle Customer Contacts Info
    Report Builder中的页码问题
    APPFND01564 ORA6502,ORA06512 in afscpcon IE 9
    EBS中发送电子邮件
  • 原文地址:https://www.cnblogs.com/html5tricks/p/3684828.html
Copyright © 2020-2023  润新知