Beschmutzte Leinwände dürfen nicht exportiert werden

185

Ich möchte meine Leinwand in einem Bild speichern. Ich habe diese Funktion:

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

Es gibt mir Fehler:

Nicht erfasster Sicherheitsfehler: Fehler beim Ausführen von 'toDataURL' auf 'HTMLCanvasElement': Beschmutzte Leinwände können möglicherweise nicht exportiert werden.

Was soll ich machen?

user3465096
quelle
In welchem ​​Browser? stackoverflow.com/a/21362569/476716 behauptet, dies sei ein Fehler.
OrangeDog
1
auf Chrom und auf Firefox
user3465096

Antworten:

177

Aus Sicherheitsgründen wird Ihr lokales Laufwerk als "andere Domäne" deklariert und beschädigt die Zeichenfläche.

(Das liegt daran, dass sich Ihre vertraulichsten Informationen wahrscheinlich auf Ihrem lokalen Laufwerk befinden!).

Versuchen Sie beim Testen die folgenden Problemumgehungen:

  • Legen Sie alle seitenbezogenen Dateien (.html, .jpg, .js, .css usw.) auf Ihrem Desktop ab (nicht in Unterordnern).

  • Veröffentlichen Sie Ihre Bilder auf einer Website, die die domänenübergreifende Freigabe unterstützt (z. B. dropbox.com). Stellen Sie sicher, dass Sie Ihre Bilder im öffentlichen Ordner der Dropbox ablegen und beim Herunterladen des Bildes auch das Cross-Origin-Flag setzen (var img = new Image (); img.crossOrigin = "anonym" ...)

  • Installieren Sie einen Webserver auf Ihrem Entwicklungscomputer (IIS- und PHP-Webserver verfügen beide über kostenlose Editionen, die auf einem lokalen Computer problemlos funktionieren).

markE
quelle
15
Vielen Dank, das Festlegen der Eigenschaft img.crossOrigin hat mir geholfen!
Zumek
5
@markE - Ich habe Bilddaten von localStorage geladen, anstatt sie aus einer Datei oder einer URL zu laden, und dann einige Manipulationen vorgenommen, z. B. das Hinzufügen eines Textes. Dann wurde versucht, es mit toDataURL () auf localStorage zurückzusetzen. Es wird jedoch "Fehler beim Ausführen von 'toDataURL' auf 'HTMLCanvasElement' angezeigt: Beschmutzte Leinwände dürfen nicht exportiert werden". In diesem Fall verwende ich keine externe Datei oder URL, um ein domänenübergreifendes Problem zu erhalten. Warum führt es dann zu diesem Fehler?
Sajith
2
@Saijth - Möglicherweise möchten Sie den für die Bilder verwendeten Pfad überprüfen. Ich hatte dieses Problem auch, weil ich den direkten Zugriff auf meinen lokalen virtuellen Server über seine IP-Adresse (127.0.xx /) getestet habe, aber einige der Bilder über die Domäne (localhost /) verlinkt waren. Sobald ich stattdessen den localhost verwendet habe, hat es geklappt. Stellen Sie also sicher, dass Sie nicht auf so etwas stoßen.
Victor D.
1
(1) Zeigen Sie es auf dem xampp-Webserver localhost / file anstelle von c: / localdisk / file an. dann beschwert sich Chrome nicht über Sicherheitsfehler. (2) Oder verwenden Sie dieses Flag, wenn Sie Chrome starten: --allow-file-access-from-files
mosh
1
Fügen Sie einfach ein weiteres mögliches Problem hinzu: Wenn Sie versuchen, eine Zeichenfläche zu exportieren, die ein SVG mit einem ForeignObject enthält, wird es von einigen Browsern als fehlerhaft markiert.
HairyFotr
128

Setzen Sie im img-Tag crossorigin auf Anonymous.

<img crossorigin="anonymous"></img>
Annia Martinez
quelle
60
Aber was im Fall von html5 Leinwand zu tun, nicht img Elemente
graphics123
11
Im Fall eines Canvas-Elements liegt die Ursache des Problems immer in einem Bild (oder Bildern), das Sie darauf zeichnen. Sie müssen also nur das Bild aufspüren und sein crossOrigin-Attribut wie angegeben festlegen, bevor Sie es laden.
Fernando Echeverria
3
Das hat mir den Tag gerettet!
Chang
1
Gerne helfen :)
Annia Martinez
9
Es ist 12 Uhr im Amt und ich finde diese einfache Antwort, das ist reines Glück
Dheeraj
26

Wenn jemand meine Antwort sieht, sind Sie vielleicht in diesem Zustand:

1. Der Versuch, mit Openlayern einen Karten-Screenshot auf Leinwand zu erstellen (Version> = 3)
2. Und das Beispiel des Exportierens einer Karte
angezeigt 3. Mit ol.source.XYZ den Karten-Layer rendern

Bingo!

Verwenden Sie ol.source.XYZ.crossOrigin = 'Anonymous' , um Ihre Verwirrung zu lösen. Oder wie folgt Code:

     var baseLayer = new ol.layer.Tile({
         name: 'basic',
         source: new ol.source.XYZ({
             url: options.baseMap.basic,
             crossOrigin: "Anonymous"
         })
     });
Sknight
quelle
1
Fantastisch. Nützlich für alle Quellen wie TileImage und dergleichen.
Phil
Fatastic! Genau das, wonach ich gesucht habe, einfache Lösung für eine OpenLayers-Demo, die ich mache.
Marc
Ich verwende Vektor-Kachelebenen und füge diese Eigenschaft der Quelle hinzu, aber es funktioniert auch nicht!
Mahdi N75
Genau das, was ich brauchte :)
Ray
16

Wenn Sie die ctx.drawImage()Funktion verwenden, können Sie Folgendes tun:

var img = loadImage('../yourimage.png', callback);

function loadImage(src, callback) {
    var img = new Image();

    img.onload = callback;
    img.setAttribute('crossorigin', 'anonymous'); // works for me

    img.src = src;

    return img;
}

Und in Ihrem Rückruf können Sie es jetzt verwenden ctx.drawImageund exportieren mittoDataURL

mehulmpt
quelle
6
Das hat bei mir nicht funktioniert. Immer noch die Tainted canvases may not be exported.Fehlermeldung.
Sam Sverko
1
Für mich geht das. Vielen Dank. @SamSverko Stellen Sie sicher, dass das Attribut vor img.src festgelegt ist.
Aijogja
14

In meinem Fall habe ich aus einem Video auf ein Canvas-Tag gezeichnet. Um den fehlerhaften Canvas-Fehler zu beheben, musste ich zwei Dinge tun:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Stellen Sie sicher, dass der Header "Access-Control-Allow-Origin" in der Videoquellenantwort festgelegt ist (ordnungsgemäße Einrichtung von crossdomain.example.com).
  • Stellen Sie das Video-Tag auf crossorigin = "anonym" ein.
jdramer
quelle
5

Scheint, als würden Sie ein Bild von einer URL verwenden, für die der korrekte Access-Control-Allow-Origin-Header und damit das Problem nicht festgelegt wurden. Sie können dieses Bild von Ihrem Server abrufen und von Ihrem Server abrufen, um CORS-Probleme zu vermeiden.

Prasanna Aarthi
quelle
Könnten Sie Ihre Antwort genauer formulieren, weil ich das ganze Konzept nicht wirklich kenne? Wie rufe ich das Bild von meinem Server ab?
user3465096
Woher holen Sie das Bild, von Ihrem Server oder von einem anderen?
Prasanna Aarthi
Es geht so: loadImage ("example.jpg", 0, 0, 500, 300); Ich kann zufällige Bild-URL oder Bild in den gleichen Ordner auf meinem Computer
legen
Ja, aber ich habe gerade ein Bild auf Farbe erstellt und es ist immer noch dasselbe
user3465096
1
Ich gab Access-Control-Allow-Origin: * für die Datei, aber es zeigt immer noch den Fehler
Harikrishnan
4

Ich habe das Problem mit der useCORS: trueOption gelöst

 html2canvas(document.getElementsByClassName("droppable-area")[0], { useCORS:true}).then(function (canvas){
        var imgBase64 = canvas.toDataURL();
        // console.log("imgBase64:", imgBase64);
        var imgURL = "data:image/" + imgBase64;
        var triggerDownload = $("<a>").attr("href", imgURL).attr("download", "layout_"+new Date().getTime()+".jpeg").appendTo("body");
        triggerDownload[0].click();
        triggerDownload.remove();
    });
Ahmad Zahabi
quelle
3

Überprüfen Sie [CORS-fähiges Bild] [1] von MDN. Grundsätzlich müssen Sie einen Server haben, auf dem Images mit dem entsprechenden Access-Control-Allow-Origin-Header gehostet werden.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

Sie können diese Bilder im DOM-Speicher speichern, als ob sie von Ihrer Domain bereitgestellt würden. Andernfalls treten Sicherheitsprobleme auf.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}

BerlinaLi
quelle
Während dieser Link die Frage beantworten kann, ist es besser, die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen. Nur-Link-Antworten können ungültig werden, wenn sich die verknüpfte Seite ändert. - Von der Überprüfung
Gowtham Shiva
Danke für die Anmerkung. Ich füge gerade den Inhalt vom MDN-Link hinzu :)
BerlinaLi
1

Nur als Antwort auf die Antwort von @ markE - wenn Sie einen lokalen Server erstellen möchten. Dieser Fehler wird auf einem lokalen Server nicht angezeigt.

Wenn Sie PHP auf Ihrem Computer installiert haben:

  1. Öffnen Sie Ihr Terminal / cmd
  2. Navigieren Sie in den Ordner, in dem sich Ihre Website-Dateien befinden
  3. Führen Sie in diesem Ordner den Befehl php -S localhost:3000← Beachten Sie das Großbuchstaben 'S'.
  4. Öffnen Sie Ihren Browser und gehen Sie in der URL-Leiste zu localhost: 3000 . Ihre Website sollte dort laufen.

oder

Wenn Sie Node.js auf Ihrem Computer installiert haben:

  1. Öffnen Sie Ihr Terminal / cmd
  2. Navigieren Sie in den Ordner, in dem sich Ihre Website-Dateien befinden
  3. Führen Sie den Befehl in diesem Ordner aus npm init -y
  4. Laufen npm install live-server -goder sudo npm install live-server -gauf einem Mac
  5. Führen Sie es aus live-serverund es sollte automatisch ein neuer Tab im Browser mit geöffneter Website geöffnet werden.

Hinweis: Denken Sie daran, eine index.html-Datei im Stammverzeichnis Ihres Ordners zu haben, da sonst Probleme auftreten können.

Ludolfyn
quelle
0

Ich habe diesen Fehler auch behoben, indem ich useCORS : true,meinen Code wie - hinzugefügt habe.

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Jeet
quelle