如何从 Three.js 画布中保存图像?

Posted

技术标签:

【中文标题】如何从 Three.js 画布中保存图像?【英文标题】:How do you save an image from a Three.js canvas? 【发布时间】:2013-03-11 14:32:20 【问题描述】:

如何保存 Thr​​ee.js 画布中的图像?

我正在尝试使用 Canvas2Image,但它不喜欢使用 Threejs。因为画布只有在有一个 div 可以将画布对象附加到时才被定义。

http://ajaxian.com/archives/canvas2image-save-out-your-canvas-data-to-images

【问题讨论】:

我不确定你可以。 2D 画布支持这一点,但我相信 WebGL 画布不支持。 【参考方案1】:

由于 toDataURL 是 canvas html 元素的一种方法,它也适用于 3d 上下文。但是你必须注意几件事。

    确保在初始化 3D 上下文时将 preserveDrawingBuffer 标志设置为 true,如下所示:

    var context = canvas.getContext("experimental-webgl", preserveDrawingBuffer: true);
    

    然后用户canvas.toDataURL()获取图片

在threejs中,当渲染器被实例化时,您必须执行以下操作:

new THREE.WebGLRenderer(
    preserveDrawingBuffer: true 
);

另外,请记住,这可能会对性能产生影响。 (阅读:https://github.com/mrdoob/three.js/pull/421#issuecomment-1792008)

只适用于webgl渲染器,不过如果是threejs canvasRenderer,你可以直接做renderer.domElement.toDataURL();,不需要初始化参数。

我的 webgl 实验:http://jsfiddle.net/TxcTr/3/ 按 'p' 截屏。

支持gaitat,我只是按照他评论中的链接来得到这个答案。

【讨论】:

Dinesh,你知道这是否也适用于 nodejs 吗?【参考方案2】:

我阅读了 Dinesh (https://github.com/mrdoob/three.js/pull/421#issuecomment-1792008) 发布的对话,并提出了一个不会降低您的应用程序速度的解决方案。

    function render()  
        requestAnimationFrame(render);
        renderer.render(scene, camera);
        if(getImageData == true)
            imgData = renderer.domElement.toDataURL();
            getImageData = false;
        
     

有了这个,您可以将 preserveDrawingBuffer-Flag 保留为 false,仍然可以从 THREE.js 获取图像。只需将 getImageData 设置为 true 并调用 render() 即可。

getImageData = true;
render();
console.debug(imgData);

希望这可以帮助像我这样需要高 fps 的人:)

【讨论】:

基本上事实证明,对于threejs,您需要一个接一个地调用2个:renderer.render(scene, camera); renderer.domElement.toDataURL();在许多情况下,最简单的方法可能只是将它们放在正常渲染循环之外的某个单独的函数中。 使用这些设置来防止内存使用过多 .toDataURL( 'image/jpeg', 1.0 ); 否则 imgData 包含原始图像。它为我节省了 12MB 到 400Kb 的空间 我正在尝试这个版本,但不幸的是我得到了一个黑色的图像。 requestAnimationFrame中的render函数是调用了它所在的函数,还是这是三个提供的render函数(所以renderer.render)? @DSz 已经 6 年了,但如果我没记错的话,渲染函数会不断地调用自己来重绘(例如游戏),所以动画对象或相机运动会出现在屏幕上。这个循环将检查它是否需要每次都生成一个“截图”。再调用一次 render() 应该不会对这个循环产生任何影响。但又是6年。您使用更新版本的 three.js 的可能性很高,但情况可能会有所不同。 感谢您回来回答。我会尝试探索更多的解决方法!【参考方案3】:

用canvas创建url,然后就可以下载了

function createImage(saveAsFileName) 

    var canvas = document.getElementById("canvas");

    var url = canvas.toDataURL();

    var link = document.createElement('a');

    link.setAttribute('href', url);
    link.setAttribute('target', '_blank');
    link.setAttribute('download', saveAsFileName);

    link.click();

【讨论】:

在 vanilla three.js 上,这段代码实际上只返回一个黑色 png 图像

以上是关于如何从 Three.js 画布中保存图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何将图像和纹理添加到 Three.js JSON 对象文件

将画布作为 jpg 文件保存到服务器时如何增加 DPI?

如何禁用three.js以以2的幂调整图像大小?

如何使用 CSS 过滤器从画布中保存图像

Three.js 调整画布大小

Three.js地球开发—4.Three.js渲染场景保存成贴图