¿Cómo guardar el lienzo como una imagen con canvas.toDataURL ()?

141

Actualmente estoy construyendo una aplicación web HTML5 / aplicación nativa Phonegap y parece que no puedo entender cómo guardar mi lienzo como una imagen canvas.toDataURL(). alguien me puede ayudar?

Aquí está el código, ¿qué tiene de malo?

// Mi lienzo se llamaba "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
fuente
44
La pregunta de OP no ha sido respondida. Él claramente dijo que esto es para Phonegap / iPad. Las respuestas dadas son para guardar en un navegador de escritorio.
tshm001
1
No estoy seguro acerca de phonegap, pero lo hice desde cero en iOS nativo usando JavaScript en el otro extremo, capturo los datos .toDataURL()y luego uso window.location para apuntar el navegador appname://[data url]. En el extremo de la aplicación, UIWebView tiene un método delegado que dice si debe cargar o no una página. Escucho appname://y lo desgloso cuando entra, niega la carga de la página y captura la URL de datos en una cadena nativa ... ¿qué tan familiarizado está con el código real de iOS / Objective C?
Doug

Respuestas:

121

Aquí hay un código. sin ningún error

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
usuario1874941
fuente
1
Excepto en el modo estándar IE9: "Algunos contenidos o archivos en esta página web requieren un programa que no haya instalado". Internet Explorer 8 y superior solo admite URI de datos para imágenes en CSS, <link> y <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman
45
funciona bien. ¿Cómo puedo cambiar el nombre del archivo descargado? solo viene "descargar" y sin extensión. ¡Gracias!
Leabdalla
1
En Chrome, esto bloquea el navegador. Si visualizo la imagen en una etiqueta de imagen, funciona pero el menú del botón derecho está atenuado, por lo que todavía no puedo guardar la imagen.
Kokodoko
Esto funciona muy bien ... Pero en Android (navegador predeterminado en Galaxy S3) simplemente no descarga la imagen, pero aparece el mensaje "Descargando ..." para siempre.
Habrashat
Tengo un problema de guardado, alguien puede ayudarme a ver este enlace: stackoverflow.com/questions/25131763/…
Ramesh S
36

Esta solución le permite cambiar el nombre del archivo descargado:

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
fuente
¡Gracias por esto, me ha ayudado mucho!
Mike Moon
22

Puede usar canvas2image para solicitar la descarga.

Tuve el mismo problema, aquí hay un ejemplo simple que agrega la imagen a la página y obliga al navegador a descargarla:

<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
fuente
2
Solo lo probé, guardará un archivo sin nombre ni extensión en Chrome.
malber
como se menciona aquí nihilogic.dk/labs/canvas2image , parece que no es posible establecer el nombre del archivo: "Sería genial si de alguna manera se pudiera adjuntar un nombre de archivo a los datos, pero no he encontrado la manera de hacerlo. Por ahora, debe especificar el nombre de archivo usted mismo ".
SColvin
1
El enlace que ha publicado está roto
Oliver Nybroe
9

Puedes probar esto; cree un ancla HTML ficticia y descargue la imagen desde allí como ...

// 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
fuente
1
Me gusta el hecho de que todo se hizo en JS, incluida la creación del elemento de enlace. Funciona muy bien para fines de automatización
Jeromy Adofo
Solución perfecta
Hidayt Rahman
8

Creé una pequeña biblioteca que hace esto (junto con algunas otras conversiones útiles). Se llama reimg , y es realmente fácil de usar.

ReImg.fromCanvas(yourCanvasElement).toPng()

gillyb
fuente
Biblioteca genial Gracias. Sin embargo, hay un pequeño problema en la documentación de ejemplo. Abrí un problema en Github para llamar su atención.
jmknoll
7

Esto funciona para mí: (solo 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
fuente
¿Quizás podría explicar la parte de su código que responde a la pregunta en lugar de simplemente pegarla sin ningún comentario?
Gediminas Masaitis
6

Similar a la respuesta de 1000Bugy pero más simple porque no tiene que hacer un ancla sobre la marcha y enviar un evento de clic manualmente (más una corrección de IE).

Si hace que su botón de descarga sea un ancla, puede hacer un jack directo justo antes de que se ejecute la funcionalidad de anclaje predeterminada. Por onAnchorClicklo tanto , puede establecer el href de anclaje en la imagen base64 del lienzo y el atributo de descarga de anclaje en el nombre que desee para su imagen.

Esto no funciona en (el actual) IE porque no implementa el atributo de descarga y evita la descarga de datos uris. Pero esto se puede solucionar usandowindow.navigator.msSaveBlob lugar.

Así que su ancla controlador de eventos click sería como sigue (donde anchor, canvasy fileNameson las búsquedas de alcance):

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

Aquí hay un violín

Sjeiti
fuente
1

En lugar de imageElement.src = myImage;usted debe usarwindow.location = myImage;

E incluso después de eso, el navegador mostrará la imagen en sí. Puede hacer clic derecho y usar "Guardar enlace" para descargar la imagen.

Consulte este enlace para más información.

Hakan Serce
fuente
Wow, gracias, eso realmente ayudó mucho :) Pero, ¿cómo se obtiene un cuadro emergente para guardar, para que alguien pueda guardar en un destino específico (como su carpeta de imágenes de Android)?
Wardenclyffe
Depende del navegador específico. El navegador de Android generalmente descarga archivos a una carpeta específica directamente, por ejemplo.
Hakan Serce
En Chrome esto funciona, pero el menú del botón derecho está atenuado. Al intentar 'arrastrar' la imagen fuera del navegador, Chrome se bloquea.
Kokodoko
groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… Parece que la URL de datos de apertura como esta se bloqueará.
KeyOfJ
0

No puede utilizar los métodos mencionados anteriormente para descargar una imagen cuando se ejecuta en Cordova. Necesitará usar el complemento de archivos Cordova . Esto le permitirá elegir dónde guardarlo y aprovechar diferentes configuraciones de persistencia. Detalles aquí: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Alternativamente, puede convertir la imagen a base64 y luego almacenar la cadena en localStorage, pero esto llenará su cuota bastante rápido si tiene muchas imágenes o alta resolución.

BigBalli
fuente
-9

@Wardenclyffe y @SColvin, ambos intentan guardar la imagen utilizando el lienzo, no utilizando el contexto del lienzo. ambos deberías intentar ctx.toDataURL (); Prueba esto:

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>

También puede consultar los siguientes enlaces:

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
fuente
TypeError no capturado: el objeto # <CanvasRenderingContext2D> no tiene el método 'toDataURL'.
Brandon Aubie
Esto es incorrecto ya que el elemento de contexto no tiene una toDataURLfunción: developer.mozilla.org/en-US/docs/Web/API/… . Desea llamar toDataURLal elemento de lienzo: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot