Jump To …

THREEx.screenshot.js

/** @namespace */
var THREEx	= THREEx 		|| {};

TODO http://29a.ch/2011/9/11/uploading-from-html5-canvas-to-imgur-data-uri able to upload your screenshot without running servers

forced closure

(function(){

	/**
	 * Take a screenshot of a renderer
	 * - require WebGLRenderer to have "preserveDrawingBuffer: true" to be set
	 * - TODO is it possible to check if this variable is set ? if so check it
	 *   and make advice in the console.log
	 *   - maybe with direct access to the gl context...
	 * 
	 * @param {Object} renderer to use
	 * @param {String} mimetype of the output image. default to "image/png"
	 * @param {String} dataUrl of the image
	*/
	var toDataURL	= function(renderer, mimetype)
	{
		mimetype	= mimetype	|| "image/png";
		var dataUrl	= renderer.domElement.toDataURL(mimetype);
		return dataUrl;
	}

	/**
	 * resize an image to another resolution while preserving aspect
	 *
	 * @param {String} srcUrl the url of the image to resize
	 * @param {Number} dstWidth the destination width of the image
	 * @param {Number} dstHeight the destination height of the image
	 * @param {Number} callback the callback to notify once completed with callback(newImageUrl)
	*/
	var _aspectResize	= function(srcUrl, dstW, dstH, callback){

to compute the width/height while keeping aspect

		var cpuScaleAspect	= function(maxW, maxH, curW, curH){
			var ratio	= curH / curW;
			if( curW >= maxW && ratio <= 1 ){ 
				curW	= maxW;
				curH	= maxW * ratio;
			}else if(curH >= maxH){
				curH	= maxH;
				curW	= maxH / ratio;
			}
			return { width: curW, height: curH };
		}

callback once the image is loaded

		var onLoad	= function(){

init the canvas

			var canvas	= document.createElement('canvas');
			canvas.width	= dstW;	canvas.height	= dstH;
			var ctx		= canvas.getContext('2d');

TODO is this needed

			ctx.fillStyle	= "black";
			ctx.fillRect(0, 0, canvas.width, canvas.height);

scale the image while preserving the aspect

			var scaled	= cpuScaleAspect(canvas.width, canvas.height, image.width, image.height);

actually draw the image on canvas

			var offsetX	= (canvas.width  - scaled.width )/2;
			var offsetY	= (canvas.height - scaled.height)/2;
			ctx.drawImage(image, offsetX, offsetY, scaled.width, scaled.height);

dump the canvas to an URL

			var mimetype	= "image/png";
			var newDataUrl	= canvas.toDataURL(mimetype);

notify the url to the caller

			callback && callback(newDataUrl)
		}.bind(this);

Create new Image object

		var image 	= new Image();
		image.onload	= onLoad;
		image.src	= srcUrl;
	}
	

Super cooked function: THREEx.Screenshot.bindKey(renderer) and you are done to get screenshot on your demo

	/**
	 * Bind a key to renderer screenshot
	*/
	var bindKey	= function(renderer, opts){

handle parameters

		opts		= opts		|| {};

FIXME this modification of opts parameters is a bug. remove it

		opts.charCode	= opts.charCode	|| 'p'.charCodeAt(0);
		opts.width	= opts.width	|| 640;
		opts.height	= opts.height	|| 480;
		opts.callback	= opts.callback	|| function(url){
			window.open(url);
		};

callback to handle keypress

		var onKeyPress	= function(event){

return now if the KeyPress isnt for the proper charCode

			if( event.which !== opts.charCode )	return;

get the renderer output

			var dataUrl	= this.toDataURL(renderer);

FIXME dont resize if not explicitly asked * resize == async so if callback is a window open, it triggers the pop blocker resize it and notify the callback

			_aspectResize(dataUrl, opts.width, opts.height, opts.callback);
		}.bind(this);

listen to keypress NOTE: for firefox it seems mandatory to listen to document directly

		document.addEventListener('keypress', onKeyPress, false);

		return {
			unbind	: function(){
				document.removeEventListener('keypress', onKeyPress, false);
			}
		};
	}

export it

	THREEx.Screenshot	= {
		toDataURL	: toDataURL,
		bindKey		: bindKey
	};
})();