Comment enregistrer le canevas en tant qu'image avec canvas.toDataURL ()?

141

Je suis en train de créer une application Web HTML5 / une application native Phonegap et je n'arrive pas à comprendre comment enregistrer ma toile en tant qu'image avec canvas.toDataURL(). Quelqu'un peut-il m'aider?

Voici le code, quel est le problème?

// Mon canevas a été nommé "canvasSignature"

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
la source
4
La question de OP n'a pas reçu de réponse. Il a clairement dit que c'était pour Phonegap / iPad. Les réponses données concernent l'enregistrement sur un navigateur de bureau.
tshm001
1
Je ne suis pas sûr de phonegap, mais je l'ai fait à partir de zéro dans iOS natif en utilisant JavaScript à l'autre extrémité, je capture les données avec .toDataURL(), puis j'utilise window.location pour pointer le navigateur vers appname://[data url]. Du côté de l'application, UIWebView a une méthode de délégué qui indique s'il doit ou non charger une page. J'écoute appname://et je le décompose quand il arrive, je refuse le chargement de la page et je capture l'URL des données dans une chaîne native ... dans quelle mesure êtes-vous familier avec le code iOS / Objective C?
Doug

Réponses:

121

Voici du code. sans aucune erreur.

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
la source
1
Sauf en mode standard IE9: "Certains contenus ou fichiers de cette page Web nécessitent un programme que vous n'avez pas installé." Internet Explorer 8 et supérieur ne prend en charge que les URI de données pour les images en CSS, <link> et <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman
45
fonctionne très bien. comment puis-je changer le nom du fichier téléchargé? ça vient juste "télécharger" et sans extension. Merci!
Leabdalla
1
Dans Chrome, cela plante le navigateur. Si j'affiche l'image dans une balise d'image, cela fonctionne mais le menu contextuel est grisé - donc je ne peux toujours pas enregistrer l'image.
Kokodoko
Cela fonctionne très bien ... Mais sous Android (navigateur par défaut dans Galaxy S3), il ne télécharge tout simplement pas l'image, mais je reçois le message "Téléchargement ..." pour toujours.
Habrashat
J'ai un problème de sauvegarde, quelqu'un peut m'aider à voir ce lien: stackoverflow.com/questions/25131763/…
Ramesh S
36

Cette solution vous permet de changer le nom du fichier téléchargé:

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
la source
Merci pour cela, cela m'a beaucoup aidé!
Mike Moon
22

Vous pouvez utiliser canvas2image pour demander le téléchargement.

J'ai eu le même problème, voici un exemple simple qui ajoute à la fois l'image à la page et oblige le navigateur à la télécharger:

<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
la source
2
Juste essayé, il enregistrera un fichier sans nom ni extension dans Chrome.
malber
comme mentionné ici nihilogic.dk/labs/canvas2image définir le nom du fichier ne semble pas possible: "Ce serait vraiment bien si un nom de fichier pouvait être attaché aux données, mais je n'ai trouvé aucun moyen de le faire. Pour l'instant, vous devez spécifier vous-même le nom du fichier. "
SColvin
1
Le lien que vous avez posté est rompu
Oliver Nybroe
9

Vous pouvez essayer ceci; créer une ancre HTML factice et télécharger l'image à partir de là comme ...

// 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
la source
1
J'aime le fait que tout ait été fait en JS, y compris la création de l'élément lien. Cela fonctionne très bien à des fins d'automatisation
Jeromy Adofo
Solution parfaite
Hidayt Rahman
8

J'ai créé une petite bibliothèque qui fait cela (avec quelques autres conversions pratiques). Il s'appelle reimg , et c'est vraiment simple à utiliser.

ReImg.fromCanvas(yourCanvasElement).toPng()

gillyb
la source
Bibliothèque cool. Merci. Il y a cependant un petit problème dans la documentation de l'exemple. J'ai ouvert un numéro sur Github pour le porter à votre attention.
jmknoll
7

Ce travail pour moi: (Seulement 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
la source
Peut-être pourriez-vous expliquer la partie de votre code qui répond à la question au lieu de simplement la coller sans aucun commentaire?
Gediminas Masaitis
6

Similaire à la réponse de 1000Bugy mais plus simple car vous n'avez pas à créer une ancre à la volée et à envoyer un événement de clic manuellement (plus un correctif IE).

Si vous faites de votre bouton de téléchargement une ancre, vous pouvez le détourner juste avant que la fonctionnalité d'ancrage par défaut ne soit exécutée. Donc , onAnchorClickvous pouvez définir le href d'ancrage à l'image toile base64 et l'attribut de téléchargement d'ancrage pour tout ce que vous voulez nommer votre image.

Cela ne fonctionne pas dans (l'actuel) IE car il n'implémente pas l'attribut de téléchargement et empêche le téléchargement des uris de données. Mais cela peut être résolu en utilisant à la window.navigator.msSaveBlobplace.

Ainsi, votre gestionnaire d'événements de clic d'ancrage serait comme suit (où anchor, canvaset fileNamesont des recherches de portée):

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

Voici un violon

Sjeiti
la source
1

Au lieu de imageElement.src = myImage;vous devriez utiliserwindow.location = myImage;

Et même après cela, le navigateur affichera l'image elle-même. Vous pouvez faire un clic droit et utiliser "Enregistrer le lien" pour télécharger l'image.

Consultez ce lien pour plus d'informations.

Hakan Serce
la source
Wow, merci, cela a vraiment beaucoup aidé :) Mais comment obtenir une boîte de sauvegarde contextuelle, afin que quelqu'un puisse enregistrer dans une destination spécifique (comme son dossier d'images Android)?
Wardenclyffe
Cela dépend du navigateur spécifique. Le navigateur Android télécharge généralement des fichiers dans un dossier spécifique directement, par exemple.
Hakan Serce
Dans Chrome, cela fonctionne, mais le menu contextuel est grisé. Lorsque vous essayez de «faire glisser» l'image hors du navigateur, Chrome se bloque.
Kokodoko
groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… L' URL d'ouverture des données comme celle-ci va être bloquée, il semble.
KeyOfJ
0

Vous ne pouvez pas utiliser les méthodes mentionnées précédemment pour télécharger une image lors de l'exécution dans Cordova. Vous devrez utiliser le plug-in de fichier Cordova . Cela vous permettra de choisir où l'enregistrer et d'exploiter différents paramètres de persistance. Détails ici: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Vous pouvez également convertir l'image en base64 puis stocker la chaîne dans localStorage, mais cela remplira votre quota assez rapidement si vous avez de nombreuses images ou en haute résolution.

BigBalli
la source
-9

@Wardenclyffe et @SColvin, vous essayez tous les deux d'enregistrer l'image en utilisant le canevas, pas en utilisant le contexte du canevas. les deux vous devriez essayer de ctx.toDataURL (); Essaye ça:

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>

Vous pouvez également vous référer aux liens suivants:

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
la source
Uncaught TypeError: Object # <CanvasRenderingContext2D> n'a pas de méthode 'toDataURL'.
Brandon Aubie
C'est faux car l'élément de contexte n'a pas de toDataURLfonction: developer.mozilla.org/en-US/docs/Web/API/… . Vous souhaitez appeler toDataURLl'élément canvas: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot le