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>

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

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();

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>

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();
}

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()


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>

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


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.


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.


-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


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.