【问题标题】:Three.js: How can I make a 2D SnapShot of a Scene as a JPG Image?Three.js:如何将场景的 2D 快照制作为 JPG 图像?
【发布时间】:2014-11-29 09:11:28
【问题描述】:

我有一个像下面这样的 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 图像?

【问题讨论】:

标签: javascript html three.js webgl


【解决方案1】:

您需要做几件事,将框架保存为 jpg 图像。

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

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

preserveDrawingBuffer 标志会帮你获取当前帧的base64编码 代码是这样的

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

其次,您可能希望使用.jpg 扩展名保存文件,但并非所有浏览器都允许您指定文件名。 我找到的最佳解决方案是this SO thread

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

Codepen Link

 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";
            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>

【讨论】:

  • 如果我没听错的话,即使在不支持它的浏览器中,文件也总是保存为 .jpg?您知道如何在不降低浏览器质量的情况下优化导出的图像吗?在桌面上,我使用 imageoptim imageoptim.com,它在 MAC 上效果很好。导出的图像可以在不损失质量的情况下缩小 35%。您知道如何在浏览器中执行此操作吗?
  • @confile: 如果浏览器支持,那么文件将保存在给定的文件名中,如example.jpg,但如果浏览器不支持它,文件将保存为一些随机自动生成的文件名,如ac2wz43 ,没有 .jpg 扩展名,因此用户必须手动将其重命名为带有 .jpg 扩展名的内容才能打开它。您可以在此处检查下载属性的兼容性caniuse.com/#feat=download
  • @confile:我不确定我们如何在客户端完全优化图像,但您可以搜索其他可能能够做到这一点的 javascript 库。
  • @shiva: JS Fiddle Link 无法正常工作,请您更正。我需要看一下工作示例。谢谢。
  • @Shiva - 你的回答很好,非常感谢!希望我能给 +5 而不是 +1!
猜你喜欢
  • 2016-12-18
  • 2013-10-07
  • 1970-01-01
  • 2020-02-04
  • 2016-10-27
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
相关资源
最近更新 更多