在HTML5画布上有成千上万个运动粒子,我的目标是在每个粒子后面绘制一个短暂的淡出轨迹。一种不错且快速的方法是不完全清除画布每帧,而是用半透明颜色覆盖它。以下是仅包含一个粒子的示例:
var canvas = document.getElementById('display');
var ctx = canvas.getContext('2d');
var displayHeight = canvas.height;
var backgroundColor = '#000000';
var overlayOpacity = 0.05;
var testParticle = {
pos: 0,
size: 3
};
function render(ctx, particle) {
ctx.globalAlpha = overlayOpacity;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalAlpha = 1.0;
ctx.fillStyle = '#FFF';
ctx.fillRect(particle.pos, displayHeight / 2, particle.size, particle.size);
}
function update(particle) {
particle.pos += 1;
}
// Fill with initial color
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
function mainLoop() {
update(testParticle);
render(ctx, testParticle);
requestAnimationFrame(mainLoop);
}
mainLoop();
<canvas id="display" width="320" height="240"></canvas>
有一个明显的问题:当透明度值较低时,拖尾永远不会完全消失。您可以在我的单粒子示例中看到几乎不褪色的水平线。我理解为什么会出现这种情况。半透明的ColorB覆盖在ColorA上基本上是一种线性插值,如果我们反复执行以下操作,则ColorA永远无法完全收敛到ColorB:
ColorA = lerp(ColorA, ColorB, opacityOfB)
我的问题是,我该怎么做才能使它收敛到背景颜色,这样轨迹就不会永远留在那里了?使用WebGL或手动绘制轨迹都不是有效的选择(因为兼容性和性能原因)。一种可能的解决方案是循环所有画布像素并手动将亮度较低的像素设置为背景颜色,尽管对于大画布来说可能会很昂贵。我想知道是否有更好的解决方案。