【问题标题】:What is the most efficient way to fade out passed frames on canvas while animating on it?在画布上制作动画时淡出画布上传递的帧的最有效方法是什么?
【发布时间】:2018-09-28 01:28:03
【问题描述】:

我正在使用 HTML Canvas 制作类似于可视化工具的东西。在绘制每一帧时,我想获取当前的画布数据并将其淡出。

我发现获得这种效果的几种方法是:

  1. 在整个画布上绘制背景颜色的半透明框。实际上不会淡出内容,因此画布后面的任何内容都会被覆盖。这已经足够快了,而且它可以完成的事实证明浏览器能够进行所有必要的计算。

  2. 使用 canvas.getImageData(),操作图像数据,然后使用 canvas.putImageData() 重新应用它。这样做是非常低效的,将大量应该是本机逻辑的东西放入 js 中。太慢了,不适合实际使用。

  3. 使用 canvas.toDataUrl() 生成图像 (png/jpg) 并使用 ctx.globalOpacity 重新绘制具有一定透明度的图像。将画布数据转换为图像并返回的步骤非常昂贵(压缩、标题等)。太慢了,不适合实际使用。

如何在画布上淡出我传递的帧,同时在顶部设置新帧的动画?

我已经检查了这些:

Canvas Fade Out Particles - 非常相似的问题,答案建议对我的问题不适用的解决方案(使用精灵并重绘整个画布)

FadeIn FadeOut in Html5 canvas - 问题是关于淡入/淡出画布上的图像,而不是画布内容本身。

编辑:我想我可能已经找到了解决方案: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing

【问题讨论】:

  • 第二个例子是使用ctx.globalAlpha。是我为了淡出整个画布而使用的。第一个示例是使用 rgba 和 hsla 颜色淡出 逐个粒子。您建议使用 canvas.getImageData() 和 canvas.putImageData()。这在效率方面是极其昂贵的。你也可以使用 css opacity
  • @enxaneta 我想使用 ctx.globalAlpha 淡出整个画布,但获取图像数据(我能找到)的唯一方法是先转换为 png。

标签: javascript animation canvas


【解决方案1】:

合成成功了。这是淡出阶段:

// painter = canvas.getContext("2d")
painter.save();
painter.globalAlpha = 1;
painter.globalCompositeOperation = "destination-in";
const fadeOutAmount = 0.99;
painter.fillStyle = "rgba(0, 0, 0, fadeOutAmount)";
painter.fillRect(0, 0, canvas.width, canvas.height);
painter.restore();

通过使用“destination-in”复合模式来绘制形状,新形状的不透明度将应用于背景。

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing

示例 (also on CodePen):

const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
canvas.width = 300;
canvas.height = 300;

ctx.fillStyle = "rgb(250, 0, 0)";
// rectangle is filled with solid red
ctx.fillRect(50, 50, 100, 100);

ctx.globalCompositeOperation = "destination-in";
ctx.fillStyle = "rgba(250, 250, 250, 0.5)";
ctx.fillRect(75, 75, 100, 100);
// after the line above, only the part where the two squares show is overlappped, and it only has the opacity of the latter square.  Doing this many frames in a row fully fades out the background.
ctx.globalCompositeOperation = "source-over"

document.getElementById("test").appendChild(canvas);
<div id="test"></div>

【讨论】:

  • 当我运行它时(无论是在 CodePen 上还是在 Stack Snippet 中,我将 CodePen 复制到其中的答案),我看到的只是一个矩形,没有淡入淡出操作......? (我也尝试在其他操作之前将画布放在 DOM 中,但这并没有改变任何东西。)
  • 尝试注释掉ctx.fillRect(75, 75, 100, 100);这一行。你会看到一个更大的不褪色的红色方块。我会添加一些cmets
  • 谢谢。不过,我很困惑。你不是说你想要褪色发生吗?上面一个没有。 (我真的很想看到这些事情发生,仅此而已。:-))
  • 这是褪色的一帧。这实际上只是证明它有效。如果完全淡出,加载页面后会很快消失,不再显示,看起来更混乱。
猜你喜欢
  • 2012-01-10
  • 2016-06-23
  • 2016-02-07
  • 2013-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
相关资源
最近更新 更多