Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I let user paste image data from the clipboard into a canvas element in Firefox in pure Javascript?

I have done my best to find a simple, relevant, and up-to-date example that works for the latest version of Firefox and I'm really struggling.

Titles says it all really. I want the user to able to copy part of an image from an editor such as Windows Paint or use the Print Screen button and then paste that into a canvas element. Bonus points if the canvas resizes to fit exactly the pasted image (literally).

Want to avoid Flash or Java based solutions if reasonable.

I'm half-decent at Javascript but relatively inexperienced with the latest HTML5 features and totally new to the Canvas element. Please help!

like image 846
DG. Avatar asked Aug 22 '13 10:08

DG.


People also ask

How do you paste a picture onto a canvas?

Ctrl + V (for Windows) or Cmd + V (for Mac) for pasting content. You can use this keyboard shortcut for text, images, files, folders, and links.

Can JavaScript access clipboard?

Accessing the OS clipboard using browser JavaScript has been possible for several years using document. execCommand() .


1 Answers

Version 2.0: Smaller, cleaner code works on Chrome, Firefox, Edge, Opera. No more hacks. But if you need support IE and Safari, check v1 version.

http://jsfiddle.net/viliusl/xq2aLj4b/5/


Version 1.0 Chrome implementation is simple. Firefox (and IE) has restrictions that user must give command to do paste like keyboard event and editable input must be focused, so we do tricks here - on ctrl down we focusthat input field, on release unfocus.

Browser support (image data):

  • Firefox
  • Chrome
  • Edge
  • IE-11
  • Opera

var CLIPBOARD = new CLIPBOARD_CLASS("my_canvas", true);    /**   * image pasting into canvas   *    * @param {string} canvas_id - canvas id   * @param {boolean} autoresize - if canvas will be resized   */  function CLIPBOARD_CLASS(canvas_id, autoresize) {  	var _self = this;  	var canvas = document.getElementById(canvas_id);  	var ctx = document.getElementById(canvas_id).getContext("2d");  	var ctrl_pressed = false;  	var command_pressed = false;  	var paste_event_support;  	var pasteCatcher;    	//handlers  	document.addEventListener('keydown', function (e) {  		_self.on_keyboard_action(e);  	}, false); //firefox fix  	document.addEventListener('keyup', function (e) {  		_self.on_keyboardup_action(e);  	}, false); //firefox fix  	document.addEventListener('paste', function (e) {  		_self.paste_auto(e);  	}, false); //official paste handler    	//constructor - we ignore security checks here  	this.init = function () {  		pasteCatcher = document.createElement("div");  		pasteCatcher.setAttribute("id", "paste_ff");  		pasteCatcher.setAttribute("contenteditable", "");  		pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;width:10px;margin-left:-20px;';  		document.body.appendChild(pasteCatcher);    		// create an observer instance  		var observer = new MutationObserver(function(mutations) {  			mutations.forEach(function(mutation) {  				if (paste_event_support === true || ctrl_pressed == false || mutation.type != 'childList'){  					//we already got data in paste_auto()  					return true;  				}    				//if paste handle failed - capture pasted object manually  				if(mutation.addedNodes.length == 1) {  					if (mutation.addedNodes[0].src != undefined) {  						//image  						_self.paste_createImage(mutation.addedNodes[0].src);  					}  					//register cleanup after some time.  					setTimeout(function () {  						pasteCatcher.innerHTML = '';  					}, 20);  				}  			});  		});  		var target = document.getElementById('paste_ff');  		var config = { attributes: true, childList: true, characterData: true };  		observer.observe(target, config);  	}();  	//default paste action  	this.paste_auto = function (e) {  		paste_event_support = false;  		if(pasteCatcher != undefined){  			pasteCatcher.innerHTML = '';  		}  		if (e.clipboardData) {  			var items = e.clipboardData.items;  			if (items) {  				paste_event_support = true;  				//access data directly  				for (var i = 0; i < items.length; i++) {  					if (items[i].type.indexOf("image") !== -1) {  						//image  						var blob = items[i].getAsFile();  						var URLObj = window.URL || window.webkitURL;  						var source = URLObj.createObjectURL(blob);  						this.paste_createImage(source);  					}  				}  				e.preventDefault();  			}  			else {  				//wait for DOMSubtreeModified event  				//https://bugzilla.mozilla.org/show_bug.cgi?id=891247  			}  		}  	};  	//on keyboard press  	this.on_keyboard_action = function (event) {  		k = event.keyCode;  		//ctrl  		if (k == 17 || event.metaKey || event.ctrlKey) {  			if (ctrl_pressed == false)  				ctrl_pressed = true;  		}  		//v  		if (k == 86) {  			if (document.activeElement != undefined && document.activeElement.type == 'text') {  				//let user paste into some input  				return false;  			}    			if (ctrl_pressed == true && pasteCatcher != undefined){  				pasteCatcher.focus();  			}  		}  	};  	//on kaybord release  	this.on_keyboardup_action = function (event) {  		//ctrl  		if (event.ctrlKey == false && ctrl_pressed == true) {  			ctrl_pressed = false;  		}  		//command  		else if(event.metaKey == false && command_pressed == true){  			command_pressed = false;  			ctrl_pressed = false;  		}  	};  	//draw pasted image to canvas  	this.paste_createImage = function (source) {  		var pastedImage = new Image();  		pastedImage.onload = function () {  			if(autoresize == true){  				//resize  				canvas.width = pastedImage.width;  				canvas.height = pastedImage.height;  			}  			else{  				//clear canvas  				ctx.clearRect(0, 0, canvas.width, canvas.height);  			}  			ctx.drawImage(pastedImage, 0, 0);  		};  		pastedImage.src = source;  	};  }
1. Copy image data into clipboard or press Print Screen <br>  2. Press Ctrl+V (page/iframe must be focused):  <br /><br />  <canvas style="border:1px solid grey;" id="my_canvas" width="300" height="300"></canvas>
like image 167
ViliusL Avatar answered Sep 25 '22 19:09

ViliusL