如何在使用Three.js渲染的Canvas中添加闭合标签?

4
三维JavaScript库three.js总是向页面添加没有结束标签的canvas元素,这背后有什么特殊的原因吗?
我想在这个canvas元素上添加一个结束标签。
查看示例页面,检查页面显示一些类似于这样的内容。 enter image description here 为什么我想要这个结束标签或许很愚蠢,但我正试图使用它来获取上下文。
context = canvas.getContext('2d');

但它返回null,因此我尝试了一些解决方案,但都没有起作用,并且看到了这个答案,因此我怀疑缺少的闭合标签可能是问题所在。

实际上,我想做的事情是使用这个方法将画布保存为图像。

3个回答

3

@K3N的答案中提到的一点是正确的:您的问题不是来自检查器中未显示的</canvas>闭合标签,而是因为您试图从已经初始化了webgl的画布中获取2D上下文。


但是,

虽然在HTML5中某些元素不需要闭合标签,但对于画布(canvas)来说:

在text/html中标签不能省略:
      两个标签都不能省略。

这里有一个小的反例另一个代码片段,因为是的,<script>内容应该在遇到时直接执行,并且现代浏览器在遇到结束标签之前就会将canvas元素放入DOM中,这些浏览器能够执行这个简单的脚本(IE9不能),但这绝对是你要避免的事情:

canvas{border: 1px solid}
<canvas>
<p>I'm not there</p>

所以只是你的检查器,或者可能是你的浏览器内部没有显示它,但是你必须在你的标记中写下它
(实际上,如果我们谈论的是Chrome,只有检查器不显示它,您可以通过调用canvas元素的outerHTML属性来看到它,关闭标签将会出现。)

至于解决方案,

你想做的是将canvas导出为静态图像。
对于这个问题,由于toBlob是HTMLCanvasElement的方法,你不需要当前的上下文,你只需要最后一部分答案中的代码,并进行小的调整:

此答案所述,WebGL画布是双缓冲的。绘制缓冲区将在浏览器尽快清除,除非上下文是使用getContext()方法的preserveDrawingBuffer: true参数创建的。
但这个参数会严重影响性能,最好的建议是在渲染时同步调用toBlob()方法。

由于这已经在此答案中得到很好的解释,因此我不会在这个主题上过多扩展,但请注意,它也涉及toDataURL()some2dCanvas.drawImage(yourWebglCanvas,x,y)


是的,我更关注检查器显然对标签所做的操作,但你是对的,无论如何都需要它(我的半睡状态回答已更新)。我回答的第二部分关注的是在使用WebGL时如何获得2D上下文。 - user1693593

2

在这种情况下,canvas的结束标签不是你面临的问题。

Three.js使用webgl上下文(如果可以的话)与canvas一起使用,这意味着无法获得2d上下文。 规范确实说明了,如果已经获得了一个上下文,在这种情况下是webgl,则如果请求2d,则应该:

返回null。

(jsfiddle)

table snapshot

这意味着您将需要创建一个新的canvas(不需要插入到DOM中),然后从其中获取2D上下文。 然后使用drawImage()将webgl canvas元素作为图像源绘制到新的canvas上的2D上下文中。 然后,您就可以从中提取位图/图像。


嗯...如果OP只想从他的WebGL上下文中获取一个Blob,为什么要使用2D上下文?toBlobtoDataURL是HTMLCanvasElement的方法,并不特定于某种类型的上下文。此外,如果上下文没有使用getContext()方法的preserveDrawingBuffer: true参数创建,并且在渲染循环之后调用了drawImage(也适用于toXXX),则只会得到一张黑色图片。有关更多信息,请参见此答案 - Kaiido
1
@ K3N 感谢您的时间,我会尝试并向您更新。@Kaiido 我会检查那些答案 :) - Arun Xavier
2
很棒的回答K3N。我有一个截图示例可能会对你有兴趣JAYV。 - 2pha

1

我刚刚也在尝试做类似的事情。

首先有几点需要注意:

  1. Elements标签可能会错误地省略闭合标签(我知道这一点是因为我有一个正确关闭的画布,但Elements显示它是开放的)。
  2. 你所指的示例有一个损坏的标签,而不是缺少的标签。
  3. 当canvas标签被关闭时,你的jsfiddle仍然无法正常工作 - 实验表明,你不能为已经具有webgl上下文和反之亦然的canvas获取2D上下文(尽管对于具有2D上下文的canvas以及反之亦然的webgl可以获得2D上下文)。

一些建议:

你可以使用getElementsByTagName('canvas')。如果只有一个canvas,问题解决了,否则只需搜索所需的canvas结果即可。

或者,你可以尝试以下方法(改编自如何将一个Canvas的内容复制到另一个Canvas):

//Append the renderer to a div
div.appendChild(renderer.domElement);
div.id = "renderTarget";

// first child element of div will be canvas
var canvas = div.firstElementChild;

// draw webgl canvas to 2d canvas
var destCtx = document.getElementById("copy").getContext('2d');
destCtx.canvas.height = canvas.height;
destCtx.canvas.width = canvas.width;
destCtx.drawImage(canvas, 0, 0, canvas.width, canvas.height);

// now do what you like with the 2d canvas destCtx

HTH


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接