HTML5 Canvas中的动画不透明度

eas*_*aby 1 javascript canvas

我正在尝试重新创建此效果,但是我希望将此效果放在画布中,基本上是使用循环使用淡入效果绘制正方形。循环部分还可以,我不知道是淡入淡出的效果。我正在使用requestAnimationFrame,每次重绘时,globalAlpha都会增加,旧的squre将被删除,而新的将会被绘制。这是功能:

function renderSquare(x, y) {

requestID = requestAnimationFrame(renderSquare);
alpha = requestID/100;  

ctx.clearRect(x,y,size,size);
ctx.globalAlpha = alpha;

var colour = "rgb(58,150,270)";
ctx.fillStyle = colour;
ctx.fillRect(x, y, size, size);


console.log("ID: " + requestID);  
console.log("Alpha: " + alpha);

if(alpha == 1) {
    cancelAnimationFrame(requestID);
}   

};

function drawSquare(x,y) {
  requestAnimationFrame(function render(){
    renderSquare(x,y);          
  });   
}
Run Code Online (Sandbox Code Playgroud)

但是我就是无法正常工作。这是完整的代码库。

http://codepen.io/easynowbaby/pen/GJKOej?editors=001

最终,我希望能够在loopSquares函数中使用该函数。任何帮助都非常感谢。干杯!

编辑:我应该让自己更清楚。我不想用图像重新创建画廊,我只对正方形的级联渐弱感兴趣。我想在画布上实现这种效果,在画布上我将使用fillRect函数在小方块中淡出。

小智 5

问题

这里要指出的第一件事是如何使用requestID来设置Alpha。来自MDN(我的重点):

一个长整数值,即请求ID,用于唯一标识回调列表中的条目。这是一个非零值,但您不能对其值进行任何其他假设。您可以将此值传递给window.cancelAnimationFrame()来取消刷新回调请求。

换句话说,不要假设这将使运行值等于单元格的当前索引。它可能偶然在一个浏览器中这样做,而在另一个浏览器中却没有。通过其他方式跟踪此值。

其次,在globalAlpha整个上下文中对其旁边绘制的内容进行处理。这意味着您需要跟踪平方的当前Alpha值,或使用允许您为每种样式设置Alpha的颜色样式rgba。这无关紧要,尽管您还需要在此处跟踪Alpha。

一种解决方案

我建议为此使用一个对象,即方形猴子,可以训练它正确设置其alpha,然后在网格上复制。

主对象将跟踪所有设置,例如当前的Alpha,要更新的数量,什么颜色等等。当然,不仅限于这些-您还可以为其添加比例,旋转等,但是这里我仅显示alpha:

// Square-monkey object
function Rectangle(ctx, x, y, w, h, color, speed) {

  this.ctx = ctx;
  this.x = x;
  this.y = y;
  this.height = h;
  this.width = w;
  this.color = color;

  this.alpha = 0;                        // current alpha for this instance
  this.speed = speed;                    // increment for alpha per frame
  this.triggered = false;                // is running
  this.done = false;                     // has finished
}
Run Code Online (Sandbox Code Playgroud)

为了节省一些内存并提高性能,我们可以将原型用于常见的功能/方法:

Rectangle.prototype = {

  trigger: function() {                  // start this rectangle
    this.triggered = true
  },

  update: function() {
    if (this.triggered && !this.done) {  // only if active
      this.alpha += this.speed;          // update alpha
      this.done = (this.alpha >= 1);     // update status
    }

    this.ctx.fillStyle = this.color;           // render this instance
    this.ctx.alpha = Math.min(1, this.alpha);  // clamp value
    this.ctx.fillRect(this.x, this.y, this.width, this.height);
  }  
};
Run Code Online (Sandbox Code Playgroud)

现在,我们需要定义一个网格和像元大小:

var cols = 10,
    rows = 6,
    cellWidth = canvas.width / cols,
    cellHeight = canvas.height /rows;
Run Code Online (Sandbox Code Playgroud)

现在,我们可以在每个单元格中填充一个对象:

var grid = [],
    len = cols * rows,
    y = 0, x;

for(; y < rows; y++) {
  for(x = 0; x < cols; x++) {
    grid.push(new Rectangle(ctx, x * cellWidth, y * cellHeight,
                            cellWidth, cellHeight, "#79f", 0.25));
  }
}
Run Code Online (Sandbox Code Playgroud)

最后,我们需要以我们喜欢的任何方式触发这些正方形,这里只是对角线级联的方式。让我们还跟踪是否全部完成:

function loop() {
  ctx.globalAlpha = 1;           // reset alpha
  ctx.clearRect(0, 0, w, h);     // clear canvas

  // trigger cells
  for(y = 0; y < rows; y++) {    // iterate each row
    var gx = (x|0) - y;          // calc an x for current row
    if (gx >= 0 && gx < cols) {  // within limit?
      index = y * cols + gx;     // calc index
      grid[index].trigger();     // trigger this cell's animation if not running
    }
  }

  x += 0.25;                     // how fast to cascade

  hasActive = false;             // enable ending the animation when all done

  // update/render all cells
  for(var i = 0; i < grid.length; i++) {
    grid[i].update();
    if (!grid[i].done) hasActive = true;      // anyone active?
  }

  if (hasActive) requestAnimationFrame(loop); // animate if anyone's active
}
Run Code Online (Sandbox Code Playgroud)

现场例子

// Square-monkey object
function Rectangle(ctx, x, y, w, h, color, speed) {

  this.ctx = ctx;
  this.x = x;
  this.y = y;
  this.height = h;
  this.width = w;
  this.color = color;

  this.alpha = 0;                        // current alpha for this instance
  this.speed = speed;                    // increment for alpha per frame
  this.triggered = false;                // is running
  this.done = false;                     // has finished
}
Run Code Online (Sandbox Code Playgroud)
Rectangle.prototype = {

  trigger: function() {                  // start this rectangle
    this.triggered = true
  },

  update: function() {
    if (this.triggered && !this.done) {  // only if active
      this.alpha += this.speed;          // update alpha
      this.done = (this.alpha >= 1);     // update status
    }

    this.ctx.fillStyle = this.color;           // render this instance
    this.ctx.alpha = Math.min(1, this.alpha);  // clamp value
    this.ctx.fillRect(this.x, this.y, this.width, this.height);
  }  
};
Run Code Online (Sandbox Code Playgroud)

实时示例扩展对象

通过使用单个对象,您可以在单个位置维护代码。有趣的是,我们还可以添加旋转和缩放:

var cols = 10,
    rows = 6,
    cellWidth = canvas.width / cols,
    cellHeight = canvas.height /rows;
Run Code Online (Sandbox Code Playgroud)
var grid = [],
    len = cols * rows,
    y = 0, x;

for(; y < rows; y++) {
  for(x = 0; x < cols; x++) {
    grid.push(new Rectangle(ctx, x * cellWidth, y * cellHeight,
                            cellWidth, cellHeight, "#79f", 0.25));
  }
}
Run Code Online (Sandbox Code Playgroud)