网上下载html5+js做成的烟火程序。有一个地方不太懂,向大家提问。

发布于 2021-12-01 21:20:17 字数 6355 浏览 863 评论 1

bgColor = '#111';
gravity = 0.03;
particleColor = '#f73';

//创建canvas对象,获取2d渲染
canvas = document.querySelector('canvas');
ctx = canvas.getContext('2d');

//调整窗体大小的时候触发
(onresize = function(){
  width = canvas.width = canvas.clientWidth;
  height = canvas.height = canvas.clientHeight;
  o = {x:Math.floor(width/2),y:Math.floor(height/2)};
  edge = {top:-o.y,right:width-o.x,bottom:height-o.y,left:-o.x}
})();

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
    };
  };
})();

//移动鼠标时候触发,获取鼠标的移动的坐标,并计算出与pos1位置移动的距离
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);
  // console.log('移动触发,坐标是:');
  // console.log(mouse);
  // console.log(time);
  // console.log(fireballs);
};

//鼠标按下时候触发,第一次位置的坐标
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;
  }
};

time = 0;
times=0;
requestAnimationFrame(loop = function(){
	//console.log(++times);
  // context.setTransform(a,b,c,d,e,f);
  // 将当前转换重置为单位矩阵
  // a 水平缩放绘图。b 水平倾斜绘图。c 垂直倾斜绘图。d 垂直缩放绘图。e 水平移动绘图。f  垂直移动绘图。
  ctx.setTransform(1,0,0,1,0,0);
  //默认。在目标图像上显示源图像。
  //源图像 = 您打算放置到画布上的绘图。
  //目标图像 = 您已经放置在画布上的绘图。
  ctx.globalCompositeOperation = 'source-over';
  //设置或返回绘图的当前 alpha 或透明值。
  ctx.globalAlpha = 1;
  //设置背景颜色,#111
  ctx.fillStyle = bgColor;
  //设置矩形的大小,与上面窗体调整时候已经设置
  ctx.fillRect(0,0,width,height);
  //重新映射画布上的 (0,0) 位置。将上面窗体调整时候设置中心位置为0,0 x,y轴
  ctx.translate(o.x,o.y);
  
  //鼠标按下时候为charging为true,画出鼠标按下与抬起之间的一条直线
  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);
    //设置或返回线条的结束端点样式
    //butt  默认。向线条的每个末端添加平直的边缘。
    //round 向线条的每个末端添加圆形线帽。
    //square  向线条的每个末端添加正方形线帽。
    ctx.lineCap = 'round';
    //绘制已定义的路径。
    ctx.stroke();
  }
  //鼠标没有点击的时候自动释放烟火
  if(showInstructions){
    pos1.x = -70;
    pos1.y = -35;
    
    //x,y为终点坐标
    if(time<10){
      var x = -70,
          y = -35,
          r = 30-time*2,//这个参数表示圆的从30到10渐变的过程
          a = time/10;
    }else if(time<80){
      //自动划线time记数
      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);
    //每次请求的time值在不断的变化,这里是自动划线的功能,time的值在10到80之间划线,准备发射烟火
    //这里是坐标(-70,-35)到(70,35)划线的过程,time每次变化都要跟着划线
    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();
    }
    //当time小于140的时候画园
    if(time<140){
      ctx.globalCompositeOperation = 'source-over';
      ctx.globalAlpha = a;
      ctx.beginPath();
      //画圆,参数分别是x,y为坐标,r半径,0表示角度,PI*2
      ctx.arc(x,y,r,0,Math.PI*2);
      ctx.lineWidth = 2;
      ctx.strokeStyle = '#aaa';
      ctx.stroke();
    }
    //当time=80的时候制造一个火球
    if(time==80){
      newFireball(
        x,
        y,
        dx*0.03,
        dy*0.03,
        240
      );
    }
    //0-179自增
    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);
});

烟火小程序在线地址



如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文