【发布时间】:2017-08-11 02:48:12
【问题描述】:
我试图让它看起来好像我的<canvas> 上的运动会产生运动轨迹。为了做到这一点,我没有清除帧之间的画布,而是通过将clearRect 调用替换为以下内容来降低现有内容的不透明度:
// Redraw the canvas's contents at lower opacity. The 'copy' blend
// mode keeps only the new content, discarding what was previously
// there. That way we don't have to use a second canvas when copying
// data
ctx.globalCompositeOperation = 'copy';
ctx.globalAlpha = 0.98;
ctx.drawImage(canvas, 0, 0);
ctx.globalAlpha = 1;
ctx.globalCompositeOperation = 'source-over';
但是,由于设置 globalAlpha 会乘以 alpha 值,因此轨迹的 alpha 值可能会接近零,但实际上永远不会达到它。这意味着图形永远不会完全褪色,在画布上留下这样的痕迹,即使在数千帧过去几分钟后也不会褪色:
为了解决这个问题,我一直在逐个像素地减去 alpha 值,而不是使用 globalAlpha。减法保证像素不透明度为零。
// Reduce opacity of each pixel in canvas
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Iterates, hitting only the alpha values of each pixel.
for (let i = 3; i < data.length; i += 4) {
// Use 0 if the result of subtraction would be less than zero.
data[i] = Math.max(data[i] - (0.02 * 255), 0);
}
ctx.putImageData(imageData, 0, 0);
这解决了问题,但它非常慢,因为我手动更改每个像素值,然后使用昂贵的 putImageData() 方法。
有没有一种更高效的方法来减去而不是乘以画布上绘制的像素的不透明度?
【问题讨论】:
-
如果你输入 0.98 那么你可能还可以检查它是否接近 1 左右并将其设置为 0?
-
@EricG 图像不同部分的不透明度不同,整个东西是一次绘制的。该效果是通过以较低的不透明度绘制整个最后一帧来实现的,这意味着之前的帧也是可见的,但不透明度进一步降低。我没有在任何地方检查单个像素的不透明度;太贵了。
-
如何维护您绘制的像素并仅更新它们?然后你不必去每一个像素,当有重叠时你替换像素/值。灵感来自perfectionkills.com/exploring-canvas-drawing-techniques/…
标签: javascript html canvas alpha alphablending