I would like to modify the three.js editor to add a button to take screenshots of the scene.
Basically I want to emulate what has been implemented here, where you can see “Capture Image” option at the bottom of the “File” menu: http://editor.xtra-d.co.uk/standalone-editor/
I also found a tool named “Online 3D Viewer” live here: (https://3dviewer.net)
Source code here: GitHub - kovacsv/Online3DViewer: A solution to visualize and explore 3D models in your browser. which is based on three.js an has functionality for taking a screenshot/snapshot.
What I have managed to do so far is to overlay a button with an image on top of the three.js scene. And this button listens to click events:
By googling I found out that the canvas element can be used to take a screenshot of a three.js scene. In the bellow example this works fine since the renderer object is in the same file where the function for taking the screenshot is defined:
Original question here: javascript - Three.js: How can I make a 2D SnapShot of a Scene as a JPG Image? - Stack Overflow
Full working example code here: https://codepen.io/shivasaxena/pen/QEzrrv
[code shortened]
renderer = new THREE.WebGLRenderer({
preserveDrawingBuffer: true
});
[code shortened]
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);
}
}
The problem I am facing is that I don’t know how to access the canvas or the renderer object from inside my file (which I named Screenshot.js
) where I have the code to take the screenshot.
What I have done so far is create a Screenshot.js
file:
import { UIPanel, UIButton } from './libs/ui.js';
function Screenshot( editor ) {
const strings = editor.strings;
const container = new UIPanel();
container.setId( 'screenshot' );
container.setPosition( 'absolute' );
container.setRight( '620px' );
container.setTop( '40px' );
// screenshot
const screenshotIcon = document.createElement( 'img' );
screenshotIcon.title = strings.getKey( 'screenshot' );
screenshotIcon.src = 'images/screenshot.svg';
const screenshotButton = new UIButton();
screenshotButton.dom.appendChild( screenshotIcon );
screenshotButton.onClick( function () {
console.log("Screenshot from Screenshot,js");
const canvas = document.getElementById("myCanvas");
if (canvas) {
console.log('Debug click screenshot');
canvas.toBlob(function (blob) {
// Create a link for downloading the Blob
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'image.png';
// Programmatically trigger a click event to initiate the download
a.click();
}, 'image/png');
} else {
console.error("Canvas element not found.");
}
}
);
container.add( screenshotButton );
return container;
}
export { Screenshot };
And I modified the original index.html file to assign an id to the canvas element:
[code shortened]
<body ontouchstart="">
<script type="module">
import * as THREE from './js/three.module.js';
import { APP } from './js/app.js';
import { VRButton } from './js/VRButton.js';
window.THREE = THREE; // Used by APP Scripts.
window.VRButton = VRButton; // Used by APP Scripts.
var loader = new THREE.FileLoader();
loader.load( 'app.json', function ( text ) {
var player = new APP.Player();
player.load( JSON.parse( text ) );
player.setSize( window.innerWidth, window.innerHeight );
player.play();
// Here I assign an id to the canvas element
player.dom.id = "myCanvas";
document.body.appendChild( player.dom );
window.addEventListener( 'resize', function () {
player.setSize( window.innerWidth, window.innerHeight );
} );
} );
/* edit button */
</script>
</body>
[code shortened]
Unfortunetely the above method for assigning the “myCanvas” ID to the player.dom canvas element results in the “Canvas element not found.” message displayed to the console.
Can anyone help? Greatly appreciate any hints or insights you can provide. Thanks in advance!