javascript - 如何从不属于我的 Canvas 中获取像素数据?

标签 javascript html canvas webgl webgl2

我正在尝试从 Canvas 中获取像素 RGBA 数据以进行进一步处理。我认为 Canvas 实际上是一个 Unity 游戏,如果它有所作为的话。

我正在尝试用游戏的 Canvas 来做到这一点 Shakes and Fidget .我用 readPixels来自 context 的方法.

这是我尝试过的:

var example = document.getElementById('#canvas');
var context = example.getContext('webgl2');      // Also doesn't work with: ', {preserveDrawingBuffer: true}'
var pixels = new Uint8Array(context.drawingBufferWidth * context.drawingBufferHeight * 4); 
context.readPixels(0, 0, context.drawingBufferWidth, context.drawingBufferHeight, context.RGBA, context.UNSIGNED_BYTE, pixels);

但显然所有像素都是黑色的(显然这不是真的)。​​

编辑:另外,我想多次读取像素。 谢谢大家的回答。 @Kaiido提供的答案对我来说很完美:)

最佳答案

您只能要求一个 Canvas 上下文一次。如果您将相同的选项传递给 getContext(),则以下所有请求将返回 null,或者返回之前创建的相同上下文。

现在,您链接到的页面在创建其上下文时未通过 preserveDrawingBuffer 选项,这意味着要能够从那里获取像素信息,您必须连接在与游戏循环发生的事件循环相同的事件循环中。
幸运的是,这个游戏确实使用了一个简单的 requestAnimationFrame 循环,所以要连接到相同的事件循环,我们需要做的就是将我们的代码也包装在 requestAnimationFrame 中称呼。

由于回调是堆叠的,并且它们确实需要此类回调的下一帧来创建循环,因此我们可以确定我们的调用将在它们之后堆叠。

我现在意识到这可能并不明显,所以我将尝试进一步解释 requestAnimationFrame 的作用,以及我们如何确保我们的回调将在 Unity 的回调之后被调用。

requestAnimationFrame(fn)fn 回调推送到回调堆栈中,这些回调将按照先进先出的顺序同时调用,就在之前浏览器将执行其绘制到屏幕 操作。这种情况偶尔发生一次(通常每秒 60 次),发生在最近的事件循环结束时。
可以将其理解为一种setTimeout(fn , time_remaining_until_next_paint),主要区别是保证requestAnimationFrame 回调执行器将在事件结束时被调用循环,因此在其他 js 执行此事件循环之后。
因此,如果我们在调用回调的同一事件循环中调用 requestAnimationFrame(fn),我们的假 time_remaining_until_next_paint 将是 0fn 将被压入堆栈底部(后进后出)。
当从回调执行器内部调用 requestAnimationFrame(fn) 时,time_remaining_until_next_paint 大约是 16,而 fn 将在下一帧的第一批中被调用。

因此,从 requestAnimationFrame 的回调执行器外部对 requestAnimationFrame(fn) 的任何调用都保证在与 相同的事件循环中被调用requestAnimationFrame 供电循环,并在之后调用。

所以我们需要获取这些像素,就是将对 readPixels 的调用包装在 requestAnimationFrame 调用中,并在之后调用它Unity 的循环开始了。

var example = document.getElementById('#canvas');
var context = example.getContext('webgl2') || example.getContext('webgl');
var pixels = new Uint8Array(context.drawingBufferWidth * context.drawingBufferHeight * 4);
requestAnimationFrame(() => {
  context.readPixels(0, 0, context.drawingBufferWidth, context.drawingBufferHeight, context.RGBA, context.UNSIGNED_BYTE, pixels);
  // here `pixels` has the correct data
});

关于javascript - 如何从不属于我的 Canvas 中获取像素数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54047609/

相关文章:

c# - 无法将类型为 'Windows.UI.Xaml.Controls.Canvas' 的对象转换为类型 'Canvas'

javascript - HTML Canvas : Replace the Shapes with Numbers (ctx)

javascript - 如何从 View 中的 javascript 函数更改模型属性?

javascript - 使用变量调整 div 边距顶部 - jquery

javascript - 我怎样才能生成颜色(不是偶然的)并且使它们具有不同的颜色,而不是阴影?

javascript - 如何在 Swig 模板中调用标准的 javascript 函数?

javascript - 单击 <select> 但未选择任何选项后会触发什么事件?

javascript - 如何获取网站的背景颜色?

html - CSS 在图像的右上角定位一个图标

javascript - 使用 Javascript 创建一个非常大的可滚动(通过按住鼠标右键) Canvas