Wie speichere ich Canvas als Bild mit canvas.toDataURL ()?

141

Ich erstelle gerade eine HTML5-Web-App / Phonegap-native App und kann anscheinend nicht herausfinden, wie ich meine Leinwand als Bild speichern kann canvas.toDataURL(). Kann mir jemand helfen?

Hier ist der Code, was ist daran falsch?

// Meine Leinwand wurde "canvasSignature" genannt

JavaScript:


function putImage()
{
  var canvas1 = document.getElementById("canvasSignature");        
  if (canvas1.getContext) {
     var ctx = canvas1.getContext("2d");                
     var myImage = canvas1.toDataURL("image/png");      
  }
  var imageElement = document.getElementById("MyPix");  
  imageElement.src = myImage;                           

}  

HTML5:


<div id="createPNGButton">
    <button onclick="putImage()">Save as Image</button>        
</div>
Wardenclyffe
quelle
4
Die Frage von OP wurde nicht beantwortet. Er sagte klar, dass dies für Phonegap / iPad ist. Die angegebenen Antworten dienen zum Speichern in einem Desktop-Browser.
Tshm001
1
Ich bin mir nicht sicher über Phonegap, aber ich habe dies in nativem iOS mit JavaScript am anderen Ende von Grund auf neu gemacht. Ich .toDataURL()erfasse die Daten mit und verwende dann window.location, um den Browser darauf zu verweisen appname://[data url]. Auf der App-Seite verfügt UIWebView über eine Delegate-Methode, die angibt, ob eine Seite geladen werden soll oder nicht. Ich höre zu appname://und zerlege es, wenn es eingeht, verweigere das Laden der Seite und erfasse die Daten-URL in einer nativen Zeichenfolge. Wie vertraut sind Sie mit dem tatsächlichen iOS / Objective C-Code?
Doug

Antworten:

121

Hier ist ein Code. ohne Fehler.

var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");  // here is the most important part because if you dont replace you will get a DOM 18 exception.


window.location.href=image; // it will save locally
user1874941
quelle
1
Außer im IE9-Standardmodus: "Für einige Inhalte oder Dateien auf dieser Webseite ist ein Programm erforderlich, das Sie nicht installiert haben." Internet Explorer 8 und höher unterstützt nur Daten-URIs für Bilder in CSS, <link> und <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman
45
funktioniert gut. Wie kann ich den Namen der heruntergeladenen Datei ändern? Es kommt nur "Download" und ohne Erweiterung. Vielen Dank!
Leabdalla
1
In Chrome stürzt der Browser ab. Wenn ich das Bild in einem Bild-Tag anzeige, funktioniert es, aber das Kontextmenü ist ausgegraut, sodass ich das Bild immer noch nicht speichern kann.
Kokodoko
Das funktioniert großartig ... Aber in Android (Standardbrowser in Galaxy S3) wird das Bild einfach nicht heruntergeladen, aber ich erhalte für immer die Meldung "Herunterladen ...".
Habrashat
Ich habe ein Problem gespeichert. Jemand
Ramesh S
36

Mit dieser Lösung können Sie den Namen der heruntergeladenen Datei ändern:

HTML:

<a id="link"></a>

JAVASCRIPT:

  var link = document.getElementById('link');
  link.setAttribute('download', 'MintyPaper.png');
  link.setAttribute('href', canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"));
  link.click();
Thomas W.
quelle
Danke dafür, es hat mir sehr geholfen!
Mike Moon
21

Sie können canvas2image verwenden , um zum Herunterladen aufzufordern .

Ich hatte das gleiche Problem. Hier ist ein einfaches Beispiel, bei dem beide das Bild zur Seite hinzufügen und den Browser zum Herunterladen zwingen:

<html>
    <head>
        <script src="http://hongru.github.io/proj/canvas2image/canvas2image.js"></script>
        <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100); 
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function to_image(){
                var canvas = document.getElementById("thecanvas");
                document.getElementById("theimage").src = canvas.toDataURL();
                Canvas2Image.saveAsPNG(canvas);
            }
        </script>
    </head>
    <body onload="draw()">
        <canvas width=200 height=200 id="thecanvas"></canvas>
        <div><button onclick="to_image()">Draw to Image</button></div>
        <image id="theimage"></image>
    </body>
</html>
SColvin
quelle
2
Einfach ausprobiert, wird eine Datei ohne Namen oder Erweiterung in Chrome gespeichert.
Malber
Wie hier erwähnt, scheint es nihilogic.dk/labs/canvas2image nicht möglich zu sein, den Dateinamen festzulegen : "Es wäre wirklich ordentlich, wenn irgendwie ein Dateiname an die Daten angehängt werden könnte, aber ich habe keine Möglichkeit gefunden, dies zu tun." Vorerst müssen Sie den Dateinamen selbst angeben. "
SColvin
1
Der Link, den Sie gepostet haben, ist defekt
Oliver Nybroe
9

Sie können dies versuchen; Erstellen Sie einen Dummy-HTML-Anker und laden Sie das Bild von dort herunter, wie ...

// Convert canvas to image
document.getElementById('btn-download').addEventListener("click", function(e) {
    var canvas = document.querySelector('#my-canvas');

    var dataURL = canvas.toDataURL("image/jpeg", 1.0);

    downloadImage(dataURL, 'my-canvas.jpeg');
});

// Save | Download image
function downloadImage(data, filename = 'untitled.jpeg') {
    var a = document.createElement('a');
    a.href = data;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
}
bmatovu
quelle
1
Ich mag die Tatsache, dass alles in JS gemacht wurde, einschließlich der Erstellung des Link-Elements. Es funktioniert hervorragend für Automatisierungszwecke
Jeromy Adofo
Perfekte Lösung
Hidayt Rahman
8

Ich habe eine kleine Bibliothek erstellt, die dies tut (zusammen mit einigen anderen praktischen Konvertierungen). Es heißt reimg und ist sehr einfach zu bedienen.

ReImg.fromCanvas(yourCanvasElement).toPng()

gillyb
quelle
Coole Bibliothek. Vielen Dank. In der Beispieldokumentation gibt es jedoch ein kleines Problem. Ich habe eine Ausgabe auf Github eröffnet, um Sie darauf aufmerksam zu machen.
jmknoll
7

Diese Arbeit für mich: (Nur Google Chrome)

<html>
<head>
    <script>
            function draw(){
                var canvas = document.getElementById("thecanvas");
                var ctx = canvas.getContext("2d");
                ctx.fillStyle = "rgba(125, 46, 138, 0.5)";
                ctx.fillRect(25,25,100,100);
                ctx.fillStyle = "rgba( 0, 146, 38, 0.5)";
                ctx.fillRect(58, 74, 125, 100);
            }

            function downloadImage()
            {
                var canvas = document.getElementById("thecanvas");
                var image = canvas.toDataURL();

                var aLink = document.createElement('a');
                var evt = document.createEvent("HTMLEvents");
                evt.initEvent("click");
                aLink.download = 'image.png';
                aLink.href = image;
                aLink.dispatchEvent(evt);
            }
    </script>
</head>
<body onload="draw()">
    <canvas width=200 height=200 id="thecanvas"></canvas>
    <div><button onclick="downloadImage()">Download</button></div>
    <image id="theimage"></image>
</body>
</html>
1000Bugy
quelle
Vielleicht könnten Sie den Teil Ihres Codes erklären, der die Frage beantwortet, anstatt ihn nur ohne Kommentare einzufügen?
Gediminas Masaitis
6

Ähnlich wie die Antwort von 1000Bugy, aber einfacher, da Sie nicht sofort einen Anker machen und ein Klickereignis manuell auslösen müssen (plus einen IE-Fix).

Wenn Sie Ihren Download-Button zu einem Anker machen, können Sie ihn direkt vor der Ausführung der Standard-Ankerfunktion hochziehen. So onAnchorClickkönnen Sie den Anker href auf die Leinwand base64 Bild gesetzt und der Anker - Download - Attribut zu , was auch immer Sie Ihr Bild nennen wollen.

Dies funktioniert im (aktuellen) IE nicht, da das Download-Attribut nicht implementiert wird und das Herunterladen von Daten verhindert wird. Dies kann jedoch behoben werden, indem window.navigator.msSaveBlobstattdessen verwendet wird.

So Handler Click - Ereignis Anker würde wie folgt sein (wo anchor, canvasund fileNameist Umfang Lookups):

function onClickAnchor(e) {
  if (window.navigator.msSaveBlob) {
    window.navigator.msSaveBlob(canvas.msToBlob(), fileName);
    e.preventDefault();
  } else {
    anchor.setAttribute('download', fileName);
    anchor.setAttribute('href', canvas.toDataURL());
  }
}

Hier ist eine Geige

Sjeiti
quelle
1

Anstelle von imageElement.src = myImage;sollten Sie verwendenwindow.location = myImage;

Und auch danach zeigt der Browser das Bild selbst an. Sie können mit der rechten Maustaste klicken und "Link speichern" verwenden, um das Bild herunterzuladen.

Überprüfen Sie diesen Link für weitere Informationen.

Hakan Serce
quelle
Wow, danke, das hat wirklich sehr geholfen :) Aber wie bekommt man eine Popup-Speicherbox, damit jemand an einem bestimmten Ziel (wie seinem Android-Bilderordner) speichern kann?
Wardenclyffe
Dies hängt vom jeweiligen Browser ab. Der Android-Browser lädt normalerweise Dateien direkt in einen bestimmten Ordner herunter.
Hakan Serce
In Chrome funktioniert dies, aber das Kontextmenü ist ausgegraut. Beim Versuch, das Bild aus dem Browser zu ziehen, stürzt Chrome ab.
Kokodoko
groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… Das Öffnen einer solchen Daten-URL wird blockiert, wie es aussieht.
KeyOfJ
0

Sie können die zuvor genannten Methoden nicht verwenden, um ein Bild herunterzuladen, wenn Sie in Cordova ausgeführt werden. Sie müssen das Cordova File Plugin verwenden . Auf diese Weise können Sie auswählen, wo es gespeichert werden soll, und verschiedene Persistenzeinstellungen nutzen. Details hier: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Alternativ können Sie das Bild in base64 konvertieren und dann die Zeichenfolge in localStorage speichern. Dies füllt Ihr Kontingent jedoch ziemlich schnell, wenn Sie viele Bilder oder hochauflösende Bilder haben.

BigBalli
quelle
-9

@Wardenclyffe und @SColvin, Sie versuchen beide, Bilder über die Leinwand zu speichern, nicht über den Kontext der Leinwand. beide sollten Sie versuchen, ctx.toDataURL (); Versuche dies:

var canvas1 = document.getElementById("yourCanvasId");  <br>
var ctx = canvas1.getContext("2d");<br>
var img = new Image();<br>
img.src = ctx.toDataURL('image/png');<br>
ctx.drawImage(img,200,150);<br>

Sie können auch auf folgende Links verweisen:

http://tutorials.jenkov.com/html5-canvas/todataurl.html

http://www.w3.org/TR/2012/WD-html5-author-20120329/the-canvas-element.html#the-canvas-element

Vinay Chandra
quelle
Nicht erfasster TypeError: Objekt # <CanvasRenderingContext2D> hat keine Methode 'toDataURL'.
Brandon Aubie
Dies ist falsch, da das Kontextelement keine toDataURLFunktion hat: developer.mozilla.org/en-US/docs/Web/API/… . Sie möchten toDataURLdas Canvas-Element aufrufen : developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot