【问题标题】:html canvas motion blur with transparent background具有透明背景的html画布运动模糊
【发布时间】:2011-03-14 20:38:28
【问题描述】:

我刚刚使用廉价的运动模糊创建了一个精美的画布效果

ctx.fillStyle = "rgba(255,255,255,0.2)";
ctx.fillRect(0,0,canvas.width,canvas.height);

现在我也想做同样的事情,但背景是透明的。有没有办法做这样的事情?我正在玩 globalAlpha,但这可能是错误的方式。

PS:Google 今天真的不喜欢我

【问题讨论】:

  • 你基本上是在用半透明的颜色填充画布,没有任何动作,不是吗?
  • 正如我所说,它的效果真的很“便宜”,但应用在运动中的物体上,看起来真的很不错。但现在我必须做一些事情,比如改变全局 alpha,淡出。我唯一能想象的是迭代每个像素,但它真的很慢(我现在应用了简单的物理)。
  • 我可能忽略了一些东西,但请尝试使用setInterval,第一次填写0.1,然后填写0.2等。
  • 我只发布了 2 行代码,但整个脚本是一个包含物理更新和绘图的大型实时循环。现在我这样做(我发布的内容)而不是清除整个屏幕。它有效,但只有当我有白色背景时。我试图找到一种方法来做某事,比如 fadeRect(0.2, ...);
  • 当没有高级着色器和类似的东西时,您的运动模糊效果非常流行。其他评论者根本不知道这一点;-)

标签: javascript html canvas


【解决方案1】:

这是一种对性能更友好的方法,它需要一个不可见的缓冲区和一个可见的画布。

buffer.save();
buffer.globalCompositeOperation = 'copy';
buffer.globalAlpha = 0.2;
buffer.drawImage(screen.canvas, 0, 0, screen.canvas.width, screen.canvas.height);
buffer.restore();

基本上你将你的 objs 绘制到缓冲区,它是不可见的非常快,然后将它绘制到屏幕上。然后,您将清除缓冲区替换为使用全局 alpha 将最后一帧复制到缓冲区,并使用 globalCompositeOperation 'copy' 使缓冲区成为前一帧的半透明版本。

【讨论】:

    【解决方案2】:

    您可以使用globalAlpha 和两个不同的画布对象来创建这样的效果:一个用于前景,一个用于背景。例如,使用以下画布元素:

    <canvas id="bg" width="256" height="256"></canvas>
    <canvas id="fg" width="256" height="256"></canvas>
    

    您可以像这样复制背景纹理和运动模糊复制的前景:

    bg.globalAlpha = 0.1;
    bg.fillStyle = bgPattern;
    bg.fillRect(0, 0, bgCanvas.width, bgCanvas.height);
    
    bg.globalAlpha = 0.3;
    bg.drawImage(fgCanvas, 0, 0);
    

    这是一个jsFiddle example

    OP 询问如何使用 HTML 背景来执行此操作。由于您无法保留背景的副本,因此您必须保留先前帧的副本,并在每帧的不同 alpha 处绘制所有这些副本。怀旧:旧的3dfx Voodoo 5 显卡有一个称为“t-buffer”的硬件功能,它基本上可以让你通过硬件加速来完成这项技术。

    这里是那种风格的jsFiddle example。不过,这远没有以前的方法那么高效。

    【讨论】:

    • 好吧,确实不错,但是当我的画布下有 html 内容时怎么办?
    • @Frizi 为此,您必须保存先前画布帧的副本,并在每帧的不同 alpha 处绘制所有这些帧。我已经用一个例子更新了这个问题。
    • 我认为为了获得更好的性能,我唯一能做的就是绘制具有“历史记录”的对象,在动画中实现运动模糊,但这几乎是不可能的。你的例子很有趣。非常感谢。
    【解决方案3】:

    您在示例中所做的是使用半透明颜色部分清除屏幕,但实际上,您将始终“添加”到 Alpha 通道,最高为 1(无透明度)。

    要使用透明画布(这样您可以看到下面的内容),您应该减去 alpha 值而不是添加,但我不知道使用可用工具执行此操作的方法,除了运行所有像素一点一点地降低 alpha 值,但这会非常非常慢。

    【讨论】:

      【解决方案4】:

      如果您要跟踪屏幕上的实体,您可以通过在鼠标移动时生成新实体然后将其在补间中的 alpha 级别设置为零来做到这一点。一旦他们达到零阿尔法,从内存中删除实体。

      这需要多次绘制,如果你把它调得太快,会减慢渲染速度。显然,从渲染性能的角度来看,双画布方法是最简单且成本最低的,但它不允许您控制其他功能,例如使“粒子”不规则地移动或对它们应用物理!

      【讨论】:

        猜你喜欢
        • 2015-03-18
        • 2016-09-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多