我正在尝试转换 this page 上的 canvas 元素使用以下代码片段(例如,在 JavaScript 控制台中输入)到 png:
(function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
})($$('canvas')[0]);
不幸的是,我得到的 png 是完全空白的。另请注意,在调整页面大小后,原始 Canvas 变为空白。
为什么 canvas 变成空白?如何将此 canvas 转换为 png?
最佳答案
Kevin Reid 的preserveDrawingBuffer 建议是正确的,但(通常)有更好的选择。 tl;dr 是最后的代码。
将呈现的网页的最终像素放在一起,并将其与呈现的 WebGL 内容协调起来可能会很昂贵。通常的流程是:
请注意,这与大多数 OpenGL 应用程序不同。在那些情况下,呈现的内容通常直接显示,而不是与页面上的一堆其他内容合成,其中一些内容实际上可能位于 WebGL 内容之上并与 WebGL 内容混合。
WebGL 规范已更改为在第 3 步之后将绘图缓冲区视为基本为空。您在 devtools 中运行的代码在第 4 步之后出现,这就是您得到空缓冲区的原因。对规范的这一更改允许在平台上实现重大性能改进,在这些平台上,步骤 3 之后的消隐基本上是硬件中实际发生的事情(就像在许多移动 GPU 中一样)。如果你想解决这个问题,有时在第 3 步之后制作 WebGL 内容的副本,浏览器必须总是在第 3 步之前制作绘图缓冲区的副本,这将使你的帧率下降在某些平台上突然出现。
您完全可以这样做,通过将 preserveDrawingBuffer 设置为 true,强制浏览器制作副本并保持图像内容可访问。来自规范:
This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object. If this flag is true, the contents of the drawing buffer shall be preserved until the author either clears or overwrites them. If this flag is false, attempting to perform operations using this context as a source image after the rendering function has returned can lead to undefined behavior. This includes readPixels or toDataURL calls, or using this context as the source image of another context's texImage2D or drawImage call.
在您提供的示例中,代码只是更改上下文创建行:
gl = canvas.getContext("experimental-webgl", {preserveDrawingBuffer: true});
请记住,它会在某些浏览器中强制采用较慢的路径,并且性能会受到影响,具体取决于您渲染的内容和方式。您在大多数桌面浏览器中应该没问题,实际上不必制作副本,而且这些浏览器确实构成了绝大多数支持 WebGL 的浏览器……但仅限于现在。
但是,还有另一种选择(在规范的下一段中提到的有点令人困惑)。
本质上,您在第 2 步之前自己制作副本:在所有绘制调用完成之后但在您将控制权从代码返回给浏览器之前。这是 WebGL 绘图缓冲区仍然完好无损且可访问的时候,此时访问像素应该没有问题。您可以使用与其他方式相同的 toDataUrl 或 readPixels 调用,重要的只是时机。
在这里,您可以两全其美。您获得了绘图缓冲区的副本,但您不必在每一帧都为它付费,即使是那些您不需要副本的帧(可能是大部分帧),就像您对 preserveDrawingBuffer<> 设置为真。
在您提供的示例中,只需将您的代码添加到 drawScene 的底部,您应该会在下方看到 Canvas 的副本:
function drawScene() {
...
var webglImage = (function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL('image/png');
return image;
})(document.querySelectorAll('canvas')[0]);
window.document.body.appendChild(webglImage);
}
关于javascript - 为什么我的 Canvas 在转换为图像后变为空白?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12538193/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput