我正在尝试重新创建this effect,但我希望它在画布中,基本上使用循环绘制具有淡化效果的正方形。循环部分是好的,我无法弄清楚的是淡入效果。我正在使用requestAnimationFrame,每次重绘globalAlpha都会增加,删除旧的sqaure并绘制一个新的sqaure。这是功能:
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);
});
}
但我无法让它发挥作用。这是一个完整的代码。
http://codepen.io/easynowbaby/pen/GJKOej?editors=001
最终,我希望能够在loopSquares函数中使用该函数。非常感谢任何帮助。干杯!
编辑:我应该让自己更清楚。我不想用图像重新创建图库,我只对平方效果的级联淡化感兴趣。我想在画布中实现这个效果,我将使用fillRect函数淡化小方块。答案 0 :(得分:3)
首先要指出的是如何使用requestID
来设置alpha。来自MDN(我的重点):
一个长整数值,即请求ID,唯一标识 回调列表中的条目。这是一个非零值,但你可能没有 对其价值做出任何其他假设。您可以将此值传递给 window.cancelAnimationFrame()取消刷新回调请求。
换句话说,不要假设这将保持一个等于当前单元格索引的运行值。它可能在一个浏览器中意外地执行,但在另一个浏览器中没有。通过其他方式跟踪此值。
其次,globalAlpha
适用于其旁边绘制的任何内容的整个上下文。这意味着您需要跟踪当前alpha per 方块,或使用颜色样式rgba,它允许您为每个样式设置alpha。这并不重要,因为你还需要跟踪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
}
为了节省一些内存并提高性能,我们可以将原型用于常用功能/方法:
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);
}
};
我们现在需要做的是定义网格和单元格大小:
var cols = 10,
rows = 6,
cellWidth = canvas.width / cols,
cellHeight = canvas.height /rows;
现在我们可以使用每个单元格的对象填充网格:
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));
}
}
最后我们需要以任何我们喜欢的方式触发这些方块,这里只是一个对角级联方式。让我们跟踪是否所有事情都已完成:
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
}
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
w = canvas.width,
h = canvas.height;
// 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
}
// prototype methods that will be shared
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.globalAlpha = Math.min(1, this.alpha);
this.ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
// Populate grid
var cols = 10,
rows = 6,
cellWidth = canvas.width / cols,
cellHeight = canvas.height /rows,
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.025));
}
}
var index,
hasActive = true;
x = 0;
function loop() {
ctx.globalAlpha = 1;
ctx.clearRect(0, 0, w, h);
// trigger cells
for(y = 0; y < rows; y++) {
var gx = (x|0) - y;
if (gx >= 0 && gx < cols) {
index = y * cols + gx;
grid[index].trigger();
}
}
x += 0.25;
hasActive = false;
// update all
for(var i = 0; i < grid.length; i++) {
grid[i].update();
if (!grid[i].done) hasActive = true;
}
if (hasActive) requestAnimationFrame(loop)
}
loop();
&#13;
<canvas width=500 height=300></canvas>
&#13;
通过使用单个对象,您可以将代码保存在一个位置。为了好玩,我们也可以添加旋转和缩放:
var canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
w = canvas.width,
h = canvas.height;
// 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
}
// prototype methods that will be shared
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.globalAlpha = Math.min(1, this.alpha);
var t = this.ctx.globalAlpha, // use current alpha as t
cx = this.x + this.width * 0.5, // center position
cy = this.y + this.width * 0.5;
this.ctx.setTransform(t, 0, 0, t, cx, cy); // scale and translate
this.ctx.rotate(0.5 * Math.PI * (1 - t)); // rotate, 90° <- alpha
this.ctx.translate(-cx, -cy); // translate back
this.ctx.fillRect(this.x, this.y, this.width, this.height);
}
};
// Populate grid
var cols = 20,
rows = 12,
cellWidth = canvas.width / cols,
cellHeight = canvas.height /rows,
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.02));
}
}
var index,
hasActive = true;
x = 0;
function loop() {
ctx.setTransform(1,0,0,1,0,0);
ctx.globalAlpha = 1;
ctx.clearRect(0, 0, w, h);
// trigger cells
for(y = 0; y < rows; y++) {
var gx = (x|0) - y;
if (gx >= 0 && gx < cols) {
index = y * cols + gx;
grid[index].trigger();
}
}
x += 0.333;
hasActive = false;
// update all
for(var i = 0; i < grid.length; i++) {
grid[i].update();
if (!grid[i].done) hasActive = true;
}
if (hasActive) requestAnimationFrame(loop)
}
loop();
&#13;
<canvas width=500 height=300></canvas>
&#13;
答案 1 :(得分:1)
这不是画布也不是画布效果。
这些是由大小和不透明度动画的简单图像标签。 只需将任意图像拖动到URL栏,您就会看到全分辨率图像打开。这是因为它们是DOM元素。如果这是一个画布,你就不可能将它们拖到URL栏。
您需要做的就是正确设置一个图像标签的动画(大小和不透明度)。两者都非常简单,并且很好地解释了jQuery。接下来,将这个效果组合在一个数组中,然后延迟它们,你就可以了。