Javascript 为什么此画布在不同浏览器中的反应不同

Javascript 为什么此画布在不同浏览器中的反应不同,javascript,html,css,canvas,Javascript,Html,Css,Canvas,我在codepen中找到了这个漂亮的小画布粒子效果: /** * Generates random particles using canvas * * @class Particles * @constructor */ function Particles(){ //particle colors this.colors = [ '255, 255, 255', '255, 99, 71', '19, 19, 19' ] //adds gr

我在codepen中找到了这个漂亮的小画布粒子效果:

/**
 * Generates random particles using canvas
 * 
 * @class Particles
 * @constructor
 */
function Particles(){
  //particle colors
  this.colors = [
    '255, 255, 255',
    '255, 99, 71',
    '19, 19, 19'
  ]
  //adds gradient to particles on true
  this.blurry = true;
  //adds white border
  this.border = false;
  //particle radius min/max
  this.minRadius = 10; 
  this.maxRadius = 35;
  //particle opacity min/max
  this.minOpacity = .005;
  this.maxOpacity = .5;
  //particle speed min/max
  this.minSpeed = .05;
  this.maxSpeed = .5;
  //frames per second 
  this.fps = 60;
  //number of particles
  this.numParticles = 75;
  //required canvas variables
  this.canvas = document.getElementById('canvas');
  this.ctx = this.canvas.getContext('2d');
}

/**
 * Initializes everything
 * @method init
 */
Particles.prototype.init = function(){
  this.render();
  this.createCircle();
}

/**
 * generates random number between min and max values
 * @param  {number} min value
 * @param  {number} max malue
 * @return {number} random number between min and max
 * @method _rand
 */
Particles.prototype._rand = function(min, max){
  return Math.random() * (max - min) + min;
}

/**
 * Sets canvas size and updates values on resize
 * @method render
 */
Particles.prototype.render = function(){ 
  var self = this,
      wHeight = $(window).height(),
      wWidth = $(window).width();

  self.canvas.width = wWidth;
  self.canvas.height = wHeight;

  $(window).on('resize', self.render);
}

/**
 * Randomly creates particle attributes
 * @method createCircle
 */
Particles.prototype.createCircle = function(){
  var particle = [];

  for (var i = 0; i < this.numParticles; i++) {
    var self = this,
        color = self.colors[~~(self._rand(0, self.colors.length))];

    particle[i] = {
      radius    : self._rand(self.minRadius, self.maxRadius),
      xPos      : self._rand(0, canvas.width),
      yPos      : self._rand(0, canvas.height),
      xVelocity : self._rand(self.minSpeed, self.maxSpeed),
      yVelocity : self._rand(self.minSpeed, self.maxSpeed),
      color     : 'rgba(' + color + ',' + self._rand(self.minOpacity, self.maxOpacity) + ')'
    }

    //once values are determined, draw particle on canvas
    self.draw(particle, i);
  }
  //...and once drawn, animate the particle
  self.animate(particle);
}

/**
 * Draws particles on canvas
 * @param  {array} Particle array from createCircle method
 * @param  {number} i value from createCircle method
 * @method draw
 */
Particles.prototype.draw = function(particle, i){
  var self = this,
      ctx = self.ctx;

  if (self.blurry === true ) {
    //creates gradient if blurry === true
    var grd = ctx.createRadialGradient(particle[i].xPos, particle[i].yPos, particle[i].radius, particle[i].xPos, particle[i].yPos, particle[i].radius/1.25);

    grd.addColorStop(1.000, particle[i].color);
    grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)');
    ctx.fillStyle = grd;
  } else {
    //otherwise sets to solid color w/ opacity value
    ctx.fillStyle = particle[i].color; 
  }

  if (self.border === true) {
    ctx.strokeStyle = '#fff';
    ctx.stroke();
  }

  ctx.beginPath();
  ctx.arc(particle[i].xPos, particle[i].yPos, particle[i].radius, 0, 2 * Math.PI, false);
  ctx.fill();
}

/**
 * Animates particles 
 * @param  {array} particle value from createCircle & draw methods
 * @method animate
 */
Particles.prototype.animate = function(particle){
  var self = this,
          ctx = self.ctx;

  setInterval(function(){
    //clears canvas
    self.clearCanvas();
    //then redraws particles in new positions based on velocity
    for (var i = 0; i < self.numParticles; i++) {
      particle[i].xPos += particle[i].xVelocity;
      particle[i].yPos -= particle[i].yVelocity;

      //if particle goes off screen call reset method to place it offscreen to the left/bottom
      if (particle[i].xPos > self.canvas.width + particle[i].radius || particle[i].yPos > self.canvas.height + particle[i].radius) {
        self.resetParticle(particle, i);
      } else {
        self.draw(particle, i);
      }
    }  
  }, 1000/self.fps); 
}

/**
 * Resets position of particle when it goes off screen
 * @param  {array} particle value from createCircle & draw methods
 * @param  {number} i value from createCircle method
 * @method resetParticle
 */
Particles.prototype.resetParticle = function(particle, i){
  var self = this;

  var random = self._rand(0, 1);

  if (random > .5) { 
    // 50% chance particle comes from left side of window...
    particle[i].xPos = -particle[i].radius;
    particle[i].yPos = self._rand(0, canvas.height);
  } else {
    //... or bottom of window
    particle[i].xPos = self._rand(0, canvas.width);
    particle[i].yPos = canvas.height + particle[i].radius;   
  }
  //redraw particle with new values
  self.draw(particle, i);
}

/**
 * Clears canvas between animation frames
 * @method clearCanvas
 */
Particles.prototype.clearCanvas = function(){
  this.ctx.clearRect(0, 0, canvas.width, canvas.height);
}


// go go go!
var particle = new Particles().init();
/**
*使用画布生成随机粒子
* 
*@类粒子
*@constructor
*/
函数粒子(){
//粒子颜色
此项。颜色=[
'255, 255, 255',
'255, 99, 71',
'19, 19, 19'
]
//将渐变添加到“真”上的粒子
这个。模糊=真实;
//添加白色边框
this.border=false;
//最小/最大粒子半径
这个最小半径=10;
这个.maxRadius=35;
//粒子不透明度最小值/最大值
这是最小产能=.005;
这个.maxOpacity=.5;
//粒子速度最小/最大值
这个.min速度=0.05;
这是.maxSpeed=.5;
//每秒帧数
这是1.fps=60;
//粒子数
这个.numParticles=75;
//必需的画布变量
this.canvas=document.getElementById('canvas');
this.ctx=this.canvas.getContext('2d');
}
/**
*初始化一切
*@methodinit
*/
Particles.prototype.init=函数(){
这个。render();
这个.createCircle();
}
/**
*在最小值和最大值之间生成随机数
*@param{number}最小值
*@param{number}max-malue
*@return{number}最小值和最大值之间的随机数
*@method\u-rand
*/
粒子.原型._rand=函数(最小值,最大值){
返回Math.random()*(max-min)+min;
}
/**
*设置画布大小并在调整大小时更新值
*@methodrender
*/
Particles.prototype.render=函数(){
var self=这个,
wHeight=$(窗口).height(),
wWidth=$(窗口).width();
self.canvas.width=wWidth;
self.canvas.height=wHeight;
$(window.on('resize',self.render));
}
/**
*随机创建粒子属性
*@methodcreatecircle
*/
Particles.prototype.createCircle=函数(){
var粒子=[];
对于(var i=0;iself.canvas.width+particle[i]。半径| | particle[i]。yPos>self.canvas.height+particle[i]。半径){
自复位粒子(粒子,i);
}否则{
自绘制(粒子,i);
}
}  
},1000/每平方英尺);
}
/**
*当粒子离开屏幕时重置其位置
*createCircle和draw方法中的@param{array}粒子值
*createCircle方法中的@param{number}i值
*@方法重置粒子
*/
Particles.prototype.resetParticle=函数(粒子,i){
var self=这个;
var random=自随机(0,1);
如果(随机>0.5){
//50%的几率粒子来自窗口左侧。。。
粒子[i].xPos=-particle[i].半径;
粒子[i].yPos=self.\u rand(0,canvas.height);
}否则{
//…或窗口底部
粒子[i].xPos=self.\u rand(0,canvas.width);
粒子[i]。yPos=canvas.height+particle[i]。半径;
}
//使用新值重新绘制粒子
自绘制(粒子,i);
}
/**
*清除动画帧之间的画布
*@方法clearCanvas
*/
Particles.prototype.clearCanvas=函数(){
this.ctx.clearRect(0,0,canvas.width,canvas.height);
}
//快走!
var particle=新粒子().init();

。为什么它在Chrome中工作得很好,在Firefox中没有颜色,在InternetExplorer中看起来+运行得很糟糕,有什么方法可以解决这个问题吗?我确保所有3个浏览器都运行最新的更新

在FF中,问题在于:

在模糊if中,更改以下两行:

grd.addColorStop(1.000, particle[i].color);
grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)');
致:


在EDGE中,问题也在于模糊代码,如果将模糊设置为“false”,则所有动画都是流体。如果可以的话,我会尝试解决这个问题…

在一个经常被称为循环的过程中,创建渐变是一个应该避免的操作。在这里,我认为这就是Edge无法成功的原因。
但是,即使在FF/Chrome中,您也可以通过只创建一次渐变然后重新使用它来获得更好的性能。
你会怎么做

1) 创建标准化的径向渐变,即中心渐变,wi
grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)');
grd.addColorStop(1.000, particle[i].color);
// add this in the Particles cttor
( function() {
  var gradients = [], grd = null;
  var colors = this.colors, color=null;
  //
  for (var i=0; color=colors[i]; i++) {      
     var grd = ctx.createRadialGradient(0,0,1, 0,0,1/1.25);
     grd.addColorStop(0.000, 'rgba(34, 34, 34, 0)');
     grd.addColorStop(1.000, color);
     gradients.push(grd);
  }
  this.colorGradients = gradients;
})();
var thisParticle = particles[i];
//
if (this.blurry) {
  ctx.save();
  ctx.translate(thisParticle.xPos, thisParticle.yPos);
  ctx.scale(thisParticle.radius, thisParticle.radius);
  ctx.beginPath();
  ctx.arc(0,0,1,0, 2*Math.PI);
  ctx.fillStyle = this.colorGradients[thisParticle.colorIndex];
  ctx.fill();
  ctx.restore();
}
ctx.strokeStyle = ...some 'rgb ' color string
var convertedColor = ctx.strokeStyle ;  // converted color is '#...' color string