Wie speichere ich Leinwand als PNG-Bild?

80

Ich habe ein Canvas-Element mit einer Zeichnung und möchte eine Schaltfläche erstellen, die beim Klicken das Bild als PNG-Datei speichert. Es sollte also das Dialogfeld Speichern, Öffnen, Schließen öffnen ...

Ich mache es mit diesem Code

var canvas = document.getElementById("myCanvas");
window.open(canvas.toDataURL("image/png"));

Aber wenn ich es in IE9 teste, öffnet sich ein neues Fenster mit der Meldung "Die Webseite kann nicht angezeigt werden" und die URL lautet:

Daten: image / png; base64,iVBORw0KGgoAAAANSUhEUgAAAmAAAABpCAYAAACd + 58xAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAADRwSURBVHhe7V0HgBVF0q7ZJSlJwRxAPUFRD39RFLN34qGnnomoqIjhzBlFPROIgsoZzogR5AQEzJ4BPFAUEUwgJjgQkCQKooggaf / 6el6 / 6ZnpSW / zUn237u5MdXX1172 + z6rqaqeEG6VsJet + pDW / vkdrfx3H3yfT2tVzaP26X6hkw1q / boei / 280 / 29JwznZxJPUyXtBQBAQBAQBQaBcECjefmi56BWlZYtAeqajx / WokfrJYEqOIikOFRfXoVq161PtOk2odu0t + ectqKiojnrntWhC46QhYOtXfUarl79Ivy9 / ldau + h + tX / 8b2SbjJ07pWFQy2Uqnp2yXSrQJAoKAICAICALJCAgBS8ao8iTi / UvpSZlBxiwqwWOKimsxCWtEdettR3XqbEfFtRonkrBYArZh3fe0 + senadWyEbRm1UzasP53K45ZiFc84RKyVXkbVUYWBAQBQUAQyIqAELCsiFW2fDQpSyZk8UQMMysqKmaPWCOqt8mOVK / eTuQU1YuccCQBW7dyIq38 / J5A / fN / ad3a5QGXmqsvLfGKJl0ZCFdONEOPyl5lGV8QEAQEAUGghiMgBKzqLHCeHqVOrILtduF4MpZExEqoVq167A3bmjap34J / bmoFqcj2dM3Pr9GK + b1p5bJXmXz9nEC + 3FiorYF4hcmXlo + gUrk + um / + e + QoVWfxxRJBQBAQBAQBQUAQqBwE8uzCwiMiaEqOWYR5jJ2 / 6Hl58nYHk0Pr1v1Ov62cTytXfE5r1yyyc6RgDj16 + L + tLqFZ9xnteGUKc0Xi876YpYkFDCfpqFEz9YGpRERhAQBAQBQaB8ERAPWPnim157JreX6 / eK7eJ / Ge0RS8oPc9gT1pTqN2jFocltfdPxecBU2HHxgBTky + 71CjPGCO + YyU4j0TU9ZcGf0y + JSAoCgoAgIAgIAoJATUcgG2dQ0jpKZ / Xp + PlLtEcs3huGQhO / r17K3rBvuGrEUt8i5HPAkHC / Yt6lKuwYKiuRM9TtGbY0rcerTBLwC / KY1fSNJ / MTBAQBQUAQqAwExANWGaiHx0z2aJl9CknET + MRc2XsVSKKaNP6O1CDhvtwYn5dJZf3gOG0IxLuS0e + LB4vw9sVhiwmHywmF6xqLLdYIQgIAoKAICAICAJVAQHTo2XmkNtzv6K5R7RXLOwRs3MaW + 47SNkG9oRxZQmun6qbImCo84VSE + 5pR3 / zvFZJni / 7e8tTHiCeqCkAqsKKig2CgCAgCAgCgoAgUG0RCBKzMLmwkzHdL4pk4XlUAn7Uu3XrVtPqVfO4lurPSq0KQa5cdAv9snBgqM5XFPlKSsSPM8o3mcxES2hZtf0rEMMFAUFAEKiBCEgIsqotavpk / OiwZViHPQk / LgHfHo5EnbCGjVpxeYo9yNmw9oeSn2YeTatWTPNzozzX8ZOeWPJlJVRJnrOoxUtJtmLEUmqoartH7BEEBAFBQBCoJggIASu / hUqkUokC2rZkwSSCBU12wpadhNXbpAk13vwwKlJ3O / L1QmYrxPNlDxuGyVtyIn6K8KSZHwY3XsRX + W0L0VyTEPjwM6KuFxN1uiB6Vkv48MpdjxLt9ieieQvscuvWE13eh2jnQ9zv + F2aICAICAKCQGEIRH22559H5IqnDTMGeU / SgUJ7WNLjOVH9g8 / Xrv2Fa4P9SM6K7y4t + WXRw76sfVc42fPV936iJ5 + LKrbqTU0P3rA + 0dZbEh20L9HJHYj23I2oVrHFT5U5NFnY4m6svUA0Pvo8efbvjCBqtr0nN + IVot4Dkvv1v5aoy / HJcpUpsfI3olffdknV0uWuJfv9kWjkw55VIFAfM073PE4EkqZbEBf9HMTs8C6e3KhHiPbdqzJnKWMLAoJAeSMgHrDyRrj0 + rOEGvVoYY9Y0inIeE + YQQ + cqGGj3dgDtvJjC / mKm7BHmG68lGjO + 0T

Weiß jemand, wie man das behebt?

hinterhältig
quelle
Mögliches Duplikat von So speichern Sie
Philipp

Antworten:

65

Versuche dies:

var c=document.getElementById("alpha");
var d=c.toDataURL("image/png");
var w=window.open('about:blank','image from canvas');
w.document.write("<img src='"+d+"' alt='from canvas'/>");

Dies zeigt das Bild von der Leinwand auf einer neuen Seite, aber wenn Sie es eingestellt haben open popup in new tab, wird es about:blankin der Adressleiste angezeigt.

BEARBEITEN: - Obwohl window.open("<img src='"+ c.toDataURL('image/png') +"'/>")dies in FF oder Chrome nicht funktioniert, funktioniert das Rendern nach dem Rendern etwas anders als auf der Leinwand. Ich denke, Transparenz ist das Problem:

window.open(c.toDataURL('image/png'));
TheVillageIdiot
quelle
es stürzt bei diesem Befehl ab: var w = window.open ('about: blank', 'image from canvas');
hinterhältig
4
Ich habe es in folgendes geändert: var w = window.open ('about: blank'); und jetzt wird das Bild in einem neuen Fenster geöffnet, aber wie bekomme ich es so, dass es ein Schließfeld zum Speichern ist, ich nicht Ich möchte mit der rechten Maustaste auf das Bild klicken und auf Speichern unter ... klicken
hinterhältiger
31

FileSaver.js sollte Ihnen hier helfen können.

var canvas = document.getElementById("my-canvas");
// draw to canvas...
canvas.toBlob(function(blob) {
    saveAs(blob, "pretty image.png");
});
Maurice
quelle
13
Es gibt eine Menge, die in IE9 nicht funktioniert :-( Mit Polyfills kann einiges behoben werden, aber ich befürchte, dass dies darüber hinausgeht. Wenn Sie können, schlage ich vor, Google Chrome Frame für Benutzer zu verwenden, die IE verwenden.
Maurice
@VagueExplanation toBlob () wird in Safari nicht unterstützt. Eine einfache Polyfüllung finden Sie hier: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Maurice
18

Ich habe diese Lösung verwendet, um den Dateinamen festzulegen :

HTML:

<a href="#" id="downloader" onclick="download()" download="image.png">Download!</a>
<canvas id="canvas"></canvas>

JavaScript:

function download(){
    document.getElementById("downloader").download = "image.png";
    document.getElementById("downloader").href = document.getElementById("canvas").toDataURL("image/png").replace(/^data:image\/[^;]/, 'data:application/octet-stream');
}
Tovask
quelle
11

Ich hatte dieses Problem und dies ist die beste Lösung ohne externe oder zusätzliche Skriptbibliotheken: Erstellen Sie in Javascript-Tags oder -Dateien diese Funktion: Wir gehen hier davon aus, dass Canvas Ihre Canvas ist:

function download(){
        var download = document.getElementById("download");
        var image = document.getElementById("canvas").toDataURL("image/png")
                    .replace("image/png", "image/octet-stream");
        download.setAttribute("href", image);

    }

Geben Sie im Hauptteil Ihres HTML die Schaltfläche an:

<a id="download" download="image.png"><button type="button" onClick="download()">Download</button></a>

Dies funktioniert und der Download-Link sieht aus wie eine Schaltfläche. Getestet in Firefox und Chrome.

Plcode
quelle
1
Leider löscht es in IE 11 den Bildschirm und ändert die URL in: data: image / octet-stream; base64, iVBORw
Mike
10

Um alle drei Punkte zu berücksichtigen:

  • Taste
  • Speichern Sie das Bild als PNG-Datei
  • Öffnen Sie das Dialogfeld Speichern, Öffnen, Schließen

Der Dateidialog ist eine Einstellung im Browser.

Weisen Sie Ihren Schaltflächen für den Button / Save-Teil die folgende Funktion zu, die aus anderen Antworten zusammengesetzt wurde: Klicken Sie auf:

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    let dataURL = canvas.toDataURL('image/png');
    let url = dataURL.replace(/^data:image\/png/,'data:application/octet-stream');
    downloadLink.setAttribute('href', url);
    downloadLink.click();
}

Beispiel für Codepen

Ein anderer, etwas saubererer Ansatz ist die Verwendung von Canvas.toBlob () :

function DownloadCanvasAsImage(){
    let downloadLink = document.createElement('a');
    downloadLink.setAttribute('download', 'CanvasAsImage.png');
    let canvas = document.getElementById('myCanvas');
    canvas.toBlob(function(blob) {
      let url = URL.createObjectURL(blob);
      downloadLink.setAttribute('href', url);
      downloadLink.click();
    });
}

Beispiel für Codepen

Keine der beiden Lösungen ist zu 100% browserübergreifend kompatibel. Überprüfen Sie daher den Client

noontz
quelle
Nachdem ich so lange nach einer Lösung gesucht habe, hat DIESES für mich funktioniert. Unter Firefox 76.0.1 (64-Bit) verwende ich das. Ich sollte andere Browser überprüfen, hoffe aber, dass alles, was aktuell ist, noch funktioniert.
Alan Stewart
4

Ich habe vielleicht einen besseren Weg gefunden, um den Benutzer nicht zu zwingen, mit der rechten Maustaste zu klicken und "Bild speichern unter". Zeichnen Sie live den Canvas Base64-Code in den hrefLink und ändern Sie ihn so, dass der Download automatisch gestartet wird. Ich weiß nicht, ob es universell browserfähig ist, aber es sollte mit den Haupt- / neuen Browsern funktionieren .

var canvas = document.getElementById('your-canvas');
    if (canvas.getContext) {
        var C = canvas.getContext('2d');
    }

$('#your-canvas').mousedown(function(event) {
    // feel free to choose your event ;) 

    // just for example
    // var OFFSET = $(this).offset();
    // var x = event.pageX - OFFSET.left;
    // var y = event.pageY - OFFSET.top;

    // standard data to url
    var imgdata = canvas.toDataURL('image/png');
    // modify the dataUrl so the browser starts downloading it instead of just showing it
    var newdata = imgdata.replace(/^data:image\/png/,'data:application/octet-stream');
    // give the link the values it needs
    $('a.linkwithnewattr').attr('download','your_pic_name.png').attr('href',newdata);

});

Sie können <a>alles umwickeln, was Sie wollen.

Bill Bronson
quelle
0

Versuche dies:

jQuery('body').after('<a id="Download" target="_blank">Click Here</a>');

var canvas = document.getElementById('canvasID');
var ctx = canvas.getContext('2d');

document.getElementById('Download').addEventListener('click', function() {
    downloadCanvas(this, 'canvas', 'test.png');
}, false);

function downloadCanvas(link, canvasId, filename) {
    link.href = document.getElementById(canvasId).toDataURL();
    link.Download = filename;
}

Sie können diesen Code einfach in Firefox oder Chrom in die Konsole einfügen und nach dem Ändern Ihrer Canvas-Tag-ID in diesem obigen Skript dieses Skript in der Konsole ausführen.

Nach dem Ausführen dieses Codes sehen Sie den Link als Text "hier klicken" unten auf der HTML-Seite. Klicken Sie auf diesen Link und öffnen Sie die Leinwandzeichnung als PNG-Bild in einem neuen Fenster. Speichern Sie das Bild.

Chintan Kotadiya
quelle
0

Senden Sie ein Formular, das eine Eingabe mit dem Wert canvas enthält, an DataURL ('image / png'), z

// JAVASCRIPT

    var canvas = document.getElementById("canvas");
    var url = canvas.toDataUrl('image/png');

Fügen Sie den Wert der URL in Ihre versteckte Eingabe im Formularelement ein.

// PHP

    $data = $_POST['photo'];
    $data = str_replace('data:image/png;base64,', '', $data);
    $data = base64_decode($data);
    file_put_contents("i".  rand(0, 50).".png", $data);
Kehinde Omotoso
quelle
Dies funktioniert gut, außer die JavaScript-Funktion canvas.toDataUrl(...)sollte sein canvas.toDataURL(...).
Brannon
0

Voll funktionsfähiger HTML-Code . Ausschneiden + Einfügen in neue HTML-Datei:

Enthält zwei Beispiele:

  1. Canvas in HTML-Datei.
  2. Mit Javascript dynamisch erstellte Leinwand.

Getestet in:

  1. Chrom
  2. Internet Explorer
  3. * Kante (Titelname wird nicht angezeigt)
  4. Feuerfuchs
  5. Oper

<!DOCTYPE HTML >
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> #SAVE_CANVAS_TEST# </title>
    <meta 
        name   ="author" 
        content="John Mark Isaac Madison"
    >
    <!-- EMAIL: J4M4I5M7 -[AT]- Hotmail.com -->
</head>
<body>

<div id="about_the_code">
    Illustrates:
    <ol>
    <li>How to save a canvas from HTML page.     </li>
    <li>How to save a dynamically created canvas.</li>
    </ol>
</div>

<canvas id="DOM_CANVAS" 
        width ="300" 
        height="300"
></canvas>

<div id="controls">
    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS()">
        SAVE_CANVAS ( Dynamically Made Canvas )
    </button>

    <button type="button" style="width:300px;"
            onclick="obj.SAVE_CANVAS('DOM_CANVAS')">
        SAVE_CANVAS ( Canvas In HTML Code )
    </button>
</div>

<script>
var obj = new MyTestCodeClass();
function MyTestCodeClass(){

    //Publically exposed functions:
    this.SAVE_CANVAS = SAVE_CANVAS;

    //:Private:
    var _canvas;
    var _canvas_id = "ID_OF_DYNAMIC_CANVAS";
    var _name_hash_counter = 0;

    //:Create Canvas:
    (function _constructor(){
        var D   = document;
        var CE  = D.createElement.bind(D);
        _canvas = CE("canvas");
        _canvas.width = 300;
        _canvas.height= 300;
        _canvas.id    = _canvas_id;
    })();

    //:Before saving the canvas, fill it so
    //:we can see it. For demonstration of code.
    function _fillCanvas(input_canvas, r,g,b){
        var ctx = input_canvas.getContext("2d");
        var c   = input_canvas;

        ctx.fillStyle = "rgb("+r+","+g+","+b+")";
        ctx.fillRect(0, 0, c.width, c.height);
    }

    //:Saves canvas. If optional_id supplied,
    //:will save canvas off the DOM. If not,
    //:will save the dynamically created canvas.
    function SAVE_CANVAS(optional_id){

        var c = _getCanvas( optional_id );

        //:Debug Code: Color canvas from DOM
        //:green, internal canvas red.
        if( optional_id ){
            _fillCanvas(c,0,255,0);
        }else{
            _fillCanvas(c,255,0,0);
        }

        _saveCanvas( c );
    }

    //:If optional_id supplied, get canvas
    //:from DOM. Else, get internal dynamically
    //:created canvas.
    function _getCanvas( optional_id ){
        var c = null; //:canvas.
        if( typeof optional_id == "string"){
            var id = optional_id;
            var  d = document;
            var c  = d.getElementById( id );
        }else{
            c = _canvas; 
        }
        return c;
    }

    function _saveCanvas( canvas ){
        if(!window){ alert("[WINDOW_IS_NULL]"); }

        //:We want to give the window a unique
        //:name so that we can save multiple times
        //:without having to close previous
        //:windows.
        _name_hash_counter++              ; 
        var NHC = _name_hash_counter      ;
        var URL = 'about:blank'           ;
        var name= 'UNIQUE_WINDOW_ID' + NHC;
        var w=window.open( URL, name )    ;

        if(!w){ alert("[W_IS_NULL]");}

        //:Create the page contents,
        //:THEN set the tile. Order Matters.
        var DW = ""                        ;
        DW += "<img src='"                 ;
        DW += canvas.toDataURL("image/png");
        DW += "' alt='from canvas'/>"      ;
        w.document.write(DW)               ;
        w.document.title = "NHC"+NHC       ;

    }

}//:end class

</script>

</body>
<!-- In IE: Script cannot be outside of body.  -->
</html>
JMI MADISON
quelle
0

Ich mag die Antwort von Tovask sehr, aber sie funktioniert nicht, weil die Funktion den Namen hat download( diese Antwort erklärt, warum). Ich sehe auch keinen Sinn darin, "data: image / ..." durch "data: application / ..." zu ersetzen.

Der folgende Code wurde in Chrome und Firefox getestet und scheint in beiden Fällen einwandfrei zu funktionieren.

JavaScript:

function prepDownload(a, canvas, name) {
    a.download = name
    a.href = canvas.toDataURL()
}

HTML:

<a href="#" onclick="prepDownload(this, document.getElementById('canvasId'), 'imgName.png')">Download</a>
<canvas id="canvasId"></canvas>
user204677
quelle
-1
var canvasId = chart.id + '-canvas';
var canvasDownloadId = chart.id + '-download-canvas';
var canvasHtml = Ext.String.format('<canvas id="{0}" width="{1}" height="{2}"></canvas><a id="{3}"/>',
canvasId,
chart.getWidth(),
chart.getHeight(),
canvasDownloadId);
var canvasElement = reportBuilder.add({ html: canvasHtml });

var canvas = document.getElementById(canvasId);

var canvasDownload = document.getElementById(canvasDownloadId);
canvasDownload.href = chart.getImage().data;
canvasDownload.download = 'chart';

canvasDownload.click();
Vũ Duy Thành
quelle