Three.js:如何将场景的 2D 快照制作为 JPG 图像?

2024-01-13

我有一个如下所示的 Three.js 场景:

            var scene = new THREE.Scene();
            var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);

            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            var geometry = new THREE.BoxGeometry(1,1,1);
            var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
            var cube = new THREE.Mesh(geometry, material);
            scene.add(cube);

            camera.position.z = 5;

            var render = function () {
                requestAnimationFrame(render);

                cube.rotation.x += 0.1;
                cube.rotation.y += 0.1;

                renderer.render(scene, camera);
            };

            render();

是否可以从场景中制作 2D 快照或屏幕截图并将其导出为 JPG 图像?


您需要执行一些操作才能将帧保存为 jpg 图像。

首先像这样初始化WebGL上下文

renderer = new THREE.WebGLRenderer({
    preserveDrawingBuffer: true
});

preserveDrawingBufferflag将帮助您获取当前帧的base64编码 其代码将是这样的

var strMime = "image/jpeg";
imgData = renderer.domElement.toDataURL(strMime);

其次,您可能想使用.jpg扩展名,但并非所有浏览器都允许您指定文件名。 我发现的最好的解决方案是这个所以线程 https://stackoverflow.com/questions/283956/is-there-any-way-to-specify-a-suggested-filename-when-using-data-uri.

所以我们的脚本将检查浏览器是否允许它将创建一个新的anchor元素并设置其download并单击它(这将以指定的文件名保存文件),否则它只会下载文件,但用户必须使用.jpg扩展名来打开它。

代码笔链接 http://codepen.io/shivasaxena/pen/QEzAAv

var camera, scene, renderer;
var mesh;
var strDownloadMime = "image/octet-stream";

init();
animate();

function init() {

    var saveLink = document.createElement('div');
    saveLink.style.position = 'absolute';
    saveLink.style.top = '10px';
    saveLink.style.width = '100%';
    saveLink.style.background = '#FFFFFF';
    saveLink.style.textAlign = 'center';
    saveLink.innerHTML =
        '<a href="#" id="saveLink">Save Frame</a>';
    document.body.appendChild(saveLink);
    document.getElementById("saveLink").addEventListener('click', saveAsImage);
    renderer = new THREE.WebGLRenderer({
        preserveDrawingBuffer: true
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 1000);
    camera.position.z = 400;

    scene = new THREE.Scene();

    var geometry = new THREE.BoxGeometry(200, 200, 200);


    var material = new THREE.MeshBasicMaterial({
        color: 0x00ff00
    });

    mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    window.addEventListener('resize', onWindowResize, false);
}

function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate() {
    requestAnimationFrame(animate);

    mesh.rotation.x += 0.005;
    mesh.rotation.y += 0.01;

    renderer.render(scene, camera);
}

function saveAsImage() {
    var imgData, imgNode;

    try {
        var strMime = "image/jpeg";
        var strDownloadMime = "image/octet-stream";

        imgData = renderer.domElement.toDataURL(strMime);

        saveFile(imgData.replace(strMime, strDownloadMime), "test.jpg");

    } catch (e) {
        console.log(e);
        return;
    }

}

var saveFile = function (strData, filename) {
    var link = document.createElement('a');
    if (typeof link.download === 'string') {
        document.body.appendChild(link); //Firefox requires the link to be in the body
        link.download = filename;
        link.href = strData;
        link.click();
        document.body.removeChild(link); //remove the link when done
    } else {
        location.replace(uri);
    }
}
html, body {
    padding:0px;
    margin:0px;
}
canvas {
    width: 100%;
    height: 100%
}
<script src="http://cdnjs.cloudflare.com/ajax/libs/three.js/r69/three.min.js"></script>
<script src="http://threejs.org/examples/js/libs/stats.min.js"></script>

2022 年 12 月编辑

正如 Mohammad Tbeishat 在评论中指出的那样,这是一个现在可用的更预格式的 APIcanvas.toBlob你可以参考

https://r105. Threejsfundamentals.org/ Threejs/lessons/ Threejs-tips.html https://r105.threejsfundamentals.org/threejs/lessons/threejs-tips.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Three.js:如何将场景的 2D 快照制作为 JPG 图像? 的相关文章

随机推荐

  • PHP 中的重音符号 (`)(不是单引号)代表什么?

    在下面的示例中 第二行中的重音符号是什么意思 cmd ffmpeg i video deinterlace an ss second t 00 00 01 r 1 y vcodec mjpeg f mjpeg image 2 gt 1 re
  • 将版本放入我的 java 应用程序 - Netbeans

    有什么方法可以在 netbeans 中为我的应用程序提供版本号 然后在我的代码中访问该版本号 类似于我们在 Net 中使用的程序集号 在 java 或 netbeans 中是否有类似的东西 定义一个Implementation Versio
  • 保留 Spark Streaming 输出

    我正在从消息传递应用程序收集数据 我目前正在使用 Flume 它每天发送大约 5000 万条记录 我想用卡夫卡 使用 Spark Streaming 从 Kafka 消费 并将其保存到 hadoop 并使用 impala 进行查询 我尝试过
  • Vue.js 组件渲染后是否会触发事件?

    我在 Vue js 中有一些自定义组件 在我拥有的一个组件中有一个选择列表 我想将其呈现为Chosen http harvesthq github io chosen 选择框 我将其与 jQuery 函数一起使用 select chosen
  • 如何在 Firefox 和 Opera 中缩放 HTML 元素?

    如何在 Firefox 和 Opera 中缩放 HTML 元素 The zoom该属性在 IE Google Chrome 和 Safari 中有效 但在 Firefox 和 Opera 中无效 有什么方法可以将这个属性添加到 Firefo
  • JaxB读取类层次结构

    只是延伸使用 JaxB 解析类层次结构 https stackoverflow com questions 15676401 parsing class hierarchy using jaxb问题 想要使用 JaxB 读取以下 xml 文
  • 我需要引用命令替换吗?

    根据Google Shell 风格指南 https google github io styleguide shell xml Quoting 我应该 始终引用包含变量 命令替换 空格或 shell 元字符的字符串 除非需要小心的不带引号的
  • 是否可以让 Azure Pipeline 在提交时修改 README.md?

    我正在尝试在 Azure DevOps Repo 中自动生成和更新代码文档 我已经配置了一个管道 以便在提交到 master 分支时运行 python 脚本 该脚本从存储库中的文件中提取相关信息并创建一个 markdown 文件并将输出存储
  • 直接以 PDF 格式打印通过 JSP 动态创建的输出

    我通过 JSP 通过访问数据库动态打印报告 我正在使用Struts 框架和Java代码位于Action类中 最后通过显示输出 JSP 页面 它在屏幕上显示得很好 但在打印时却无法正常显示 我只想以 PDF 格式显示报告 而不是 JSP gt
  • 各种切入点表达式作用域意外触发多个通知调用

    背景 使用方面记录项目 例如所有标有 Log注释将信息写入日志文件 Problem 方法似乎是递归调用一级深度的 但代码没有显示任何这样的递归关系 Actual 记录结果 2018 09 25 12 17 29 155 EmailNotif
  • jquery获取光标所在元素

    我正在使用 javascript 和 jquery 为我的网站构建一个分割测试工具 现在 当光标经过预览框中的元素时 我想为每个要拆分测试的元素显示一个小悬停菜单 有可能做这样的事情吗 我尝试过这样的事情 body hover functi
  • 如何将框架添加到Swift项目中?

    我想向我的 Swift 项目添加一个库 我发现了 3 个不同的地方需要添加 我想知道执行此操作的正确方法以及每种方法的目的 常规选项卡 选择目标 gt 常规 嵌入二进制文件 链接的框架和库 构建阶段 选择目标 gt 构建阶段 嵌入框架 将二
  • 在 C 中打印声明的 char 值

    我知道字符变量的范围是从 有符号 128 到 127 和 无符号 0 到 255 char x x 128 printf d n x 但它是如何运作的呢 为什么我得到 128 for x printf是一个可变参数函数 仅提供第一个参数的精
  • 初始化 char 和 char 指针

    这些有什么区别 这个有效 char pEmpty new char pEmpty x 但是 如果我尝试这样做 char pEmpty NULL pEmpty x lt doesn t work and char pEmpty x putti
  • 在 Visual Basic 中寻找权威的 ISO 周计算器(在 Visual Studio Express 2010 中)

    我正在寻找一个明确的标准 即经过认证是正确的或经过相当彻底的测试 用于在 Visual Basic 中计算某个日期的 ISO 周 即在 Visual Studio Express 2010 Visual Basic 项目中运行 不成功 到目
  • adb shell 命令:mkdir(用于创建目录)

    我正在尝试通过 adb shell 创建目录 我必须在 etc 文件夹中创建一个目录 但没有成功 我设法弄清楚它是链接到的 system etc并尝试创建 system etc 但在这两种情况下我都得到 只读文件系统 如何使其可读可写 我尝
  • if语句与if-else语句,哪个更快?

    前几天我和一个朋友争论了这两个片段 哪个更快 为什么 value 5 if condition value 6 and if condition value 6 else value 5 What if value是一个矩阵 注 我知道va
  • 如何在 Objective C 中编写正则表达式(NSRegularExpression)?

    当我在 PHP 中测试这个正则表达式时 它可以工作 但它在 Objective C 中不起作用 www a zA Z0 9 2 63
  • gnome 终端控制键上的 emacs

    I m running emacs on a terminal mode no window system emacs nw I ve few global keys defined in emacs like C C x C C etc
  • Three.js:如何将场景的 2D 快照制作为 JPG 图像?

    我有一个如下所示的 Three js 场景 var scene new THREE Scene var camera new THREE PerspectiveCamera 75 window innerWidth window inner