【问题标题】:HTML canvas fillRect with low opacity doesn't affect dark pixels具有低不透明度的 HTML 画布 fillRect 不会影响暗像素
【发布时间】:2018-05-03 03:33:32
【问题描述】:

在每个动画帧之前在整个画布上反复绘制一个半不透明的黑色矩形是一种为移动形状获得残像效果的简单方法,它完全满足了我的需要 - 在一定程度上。褪色太慢,它不会一直褪色到黑色。这是一个例子:

var canv = document.createElement('canvas');
document.body.appendChild(canv);
var ctx = canv.getContext('2d');

ctx.fillStyle = 'rgba(0, 0, 0, 1)';
ctx.fillRect(0, 0, 100, 100);
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(20, 20, 60, 60);

window.requestAnimationFrame(doFade);

function doFade() {
    // Never fades away completely
    ctx.fillStyle = 'rgba(0, 0, 0, 0.02)';  
    ctx.fillRect(20, 20, 60, 60);
    window.requestAnimationFrame(doFade);  
}

jsfiddle

这在我看来像是一个数值精度问题——你不能指望画布保持浮点像素值——但我不知道如何解决这个问题。

我尝试将图像读入图案,使画布空白,然后以较低的不透明度填充图案,希望可以使舍入误差对我有利,但似乎具有相同的结果。

没有读取图像数据并将低于某个阈值的任何像素设置为黑色,这将非常慢,我已经没有想法了,可以使用一些建议。

谢谢!

【问题讨论】:

  • 欢迎来到 Stack Overflow。在这个站点中,提出的每个问题都必须是具体的,因此如果可能的话,可以用一个具体的答案来回答。您现在的问题(征求意见)被认为过于宽泛或基于意见。所以请您编辑它以针对一个问题(也许尝试实施您的一个想法并询问您遇到的问题)。
  • 问题还是有点抽象。您能否包含一些复制您的情况的示例代码?
  • 我重写了整个内容并添加了代码和 jsfiddle。一键应该足以证明问题。
  • 可以用简单的counter吗?
  • 不,我不明白如何在这里使用计数器。问题是画布中有一个形状不断移动并留下新的痕迹。这是需要移除的最古老的足迹,无需追踪许多历史框架。

标签: html5-canvas


【解决方案1】:

我想我会分享我的解决方案,以帮助其他可能遇到此问题的人。我希望避免进行任何像素级操作,但是超过某个阈值,内置画布操作就不可能了,因为底层位图每个通道只有 8 位,并且小淡入淡出会小于一个最不重要的位位,不会对图像数据产生任何影响。

我的解决方案是创建一个表示每个像素年龄的数组。绘制完每一帧后,我扫描 imageData 数组,只查看 alpha 通道。如果 alpha 为 255,我知道像素刚刚被写入,所以我将年龄设置为 0,并将 alpha 设置为 254。对于任何其他非零 alpha 值,我增加像素年龄,然后根据像素年龄。

像素年龄到 Alpha 值的映射是通过在设置淡化率时填充的查找表完成的。这让我可以在渲染循环期间使用我想要的任何衰减曲线,而无需额外的数学运算。

CPU 利用率略高,但对性能影响不大,它可以在几秒钟内平滑淡入淡出,最终总是完全淡入黑色。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-19
    • 2012-05-07
    • 2017-03-18
    • 2012-02-05
    • 1970-01-01
    相关资源
    最近更新 更多