Wie kann ich Benutzer Bilddaten aus der Zwischenablage in Firefox in reinem Javascript in ein Canvas-Element einfügen lassen?

Lesezeit: 5 Minuten

Benutzeravatar von DG
DG.

Ich habe mein Bestes getan, um ein einfaches, relevantes und aktuelles Beispiel zu finden, das für die neueste Version von Firefox funktioniert, und ich habe wirklich Probleme.

Titel sagt eigentlich alles. Ich möchte, dass der Benutzer einen Teil eines Bildes aus einem Editor wie Windows Paint kopieren oder die Schaltfläche „Drucken“ verwenden und dann in ein Canvas-Element einfügen kann. Bonuspunkte, wenn die Größe der Leinwand genau an das eingefügte Bild angepasst wird (buchstäblich).

Flash- oder Java-basierte Lösungen vermeiden möchten, wenn dies sinnvoll ist.

Ich bin halbwegs anständig in Javascript, aber relativ unerfahren mit den neuesten HTML5-Funktionen und völlig neu im Canvas-Element. Bitte helfen Sie!

  • Wie verwaltet man das Einfügen von Bildern aus der Zwischenablage in HTML5?

    –Andreas

    22. August 2013 um 10:34 Uhr


Benutzeravatar von ViliusL
ViliusL

Version 2.0: Kleinerer, saubererer Code funktioniert auf Chrome, Firefox, Edge, Opera. Keine Hacks mehr. Wenn Sie jedoch Unterstützung für IE und Safari benötigen, überprüfen Sie die v1-Version.

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


Version 1.0
Die Chrome-Implementierung ist einfach. Firefox (und IE) hat Einschränkungen, dass der Benutzer den Befehl zum Einfügen geben muss, wie ein Tastaturereignis, und bearbeitbare Eingaben müssen fokussiert sein, also machen wir hier Tricks – bei gedrückter Strg-Taste fokussieren wir das Eingabefeld, bei Freigabe wird der Fokus aufgehoben.

Browserunterstützung (Bilddaten):

  • Feuerfuchs
  • Chrom
  • Rand
  • IE-11
  • Oper
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>

  • Vielen Dank! Was für eine Erleichterung!

    – DG.

    23. August 2013 um 2:48 Uhr

  • Gibt es eine einfachere Lösung im April 2014? ohne Browser zu unterscheiden?

    – Iwan Kuckir

    4. April 2014 um 19:20 Uhr


  • Es sollte einfach sein: jsfiddle.net/KJW4E/222 – vorerst nur Chrom. In Zukunft besteht die Möglichkeit, dass dieses Beispiel auf allen Browsern funktioniert. Leider haben andere Browser einige Einschränkungen, die umgangen werden müssen.

    – ViliusL

    29. April 2014 um 12:09 Uhr


  • Strg + v funktioniert manchmal nicht im Firefox v-29-Browser. Wenn ich die Größe des Browserfensters verändere, kann ich einfügen. (Paste-Ereignis wird ausgelöst). Gibt es ein Problem mit Firefox 29 Browser mit Contenteditable oder Paste Event mit Tastaturkürzeln?

    – Jak

    15. Mai 2014 um 20:13 Uhr

  • @Jak, ich konnte deine Situation auf Firefox v29 nicht reproduzieren. Plugins, viele HTML-Elemente oder vielleicht ungültiger Code?

    – ViliusL

    20. Mai 2014 um 12:42 Uhr

Die Antwort von ViliusL ist großartig, aber für diejenigen, die nach einer einfachen browserübergreifenden Möglichkeit suchen, ein eingefügtes Bild zu erfassen:

window.addEventListener("paste", async function(e) {
  e.preventDefault();
  e.stopPropagation();
  let file = e.clipboardData.items[0].getAsFile();
  let objectUrl = URL.createObjectURL(file);
  // do something with url here
});

Wahrscheinlich möchten Sie eine Fehlerprüfung durchführen (wie in ViliusLs Antwort), falls sie etwas einfügen, das kein Bild ist. Laut MDN, ZwischenablageDaten funktioniert in allen modernen Browsern. Ich habe auf Chrome und Firefox getestet, und sie funktionieren gut.

1406270cookie-checkWie kann ich Benutzer Bilddaten aus der Zwischenablage in Firefox in reinem Javascript in ein Canvas-Element einfügen lassen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy