Como salvar a tela como uma imagem com canvas.toDataURL ()?

141

No momento, estou criando um aplicativo nativo HTML5 da Web / Phonegap e não consigo descobrir como salvar minha tela como uma imagem canvas.toDataURL(). Alguém pode me ajudar?

Aqui está o código, o que há de errado com isso?

// Minha tela foi nomeada "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
fonte
4
A pergunta do OP não foi respondida. Ele disse claramente que isso é para o Phonegap / iPad. As respostas dadas são para salvar em um navegador de desktop.
Tshm001
1
Não tenho certeza sobre o phonegap, mas já fiz isso do zero no iOS nativo usando JavaScript na outra extremidade, .toDataURL()capturo os dados com e uso window.location para apontar o navegador appname://[data url]. No final do aplicativo, o UIWebView possui um método delegado que diz se deve ou não carregar uma página. Eu escuto appname://e decompô-lo quando ele entra, negar o carregamento da página e capturar o URL de dados em uma string nativa ... quão familiarizado você está com o código iOS / Objective C real?
Doug

Respostas:

121

Aqui está um código. sem nenhum erro.

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
fonte
1
Exceto no modo de padrões do IE9: "Alguns conteúdos ou arquivos desta página exigem um programa que você não instalou". Internet Explorer 8 e acima suporta apenas URIs de dados para imagens em CSS, <link> e <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman
45
funciona bem. como posso alterar o nome do arquivo baixado? está chegando apenas "download" e sem extensão. obrigado!
Leabdalla
1
No Chrome, isso trava o navegador. Se eu exibir a imagem em uma tag de imagem, ele funcionará, mas o menu do botão direito será acinzentado - então ainda não consigo salvar a imagem.
Kokodoko 15/05
Isso funciona muito bem ... Mas no Android (navegador padrão no Galaxy S3) ele simplesmente não baixa a imagem, mas recebo a mensagem "Baixando ..." para sempre.
Habrashat
Eu tenho save questão alguém pode me ajudar a ver este link: stackoverflow.com/questions/25131763/...
Ramesh S
36

Esta solução permite alterar o nome do arquivo baixado:

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
fonte
Obrigado por isso, isso me ajudou muito!
Mike Moon
22

Você pode usar o canvas2image para solicitar o download.

Eu tive o mesmo problema, aqui está um exemplo simples que adiciona a imagem à página e força o navegador a fazer o download:

<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
fonte
2
Apenas tentei, ele salvará um arquivo sem nome nem extensão no Chrome.
malber
como mencionado aqui, nihilogic.dk/labs/canvas2image definindo o nome do arquivo não parece possível: "Seria muito legal se, de alguma forma, um nome de arquivo pudesse ser anexado aos dados, mas não encontrei nenhuma maneira de fazer isso. Por enquanto, você deve especificar o nome do arquivo. "
SColvin
1
O link que você postou está quebrado
Oliver Nybroe 16/11
9

Você pode tentar isso; crie uma âncora fictícia em HTML e baixe a imagem de lá 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
fonte
1
Eu gosto do fato de que tudo foi feito em JS, incluindo a criação do elemento link. Funciona muito bem para fins de automação
Jeromy Adofo
Solução perfeita
Hidayt Rahman
8

Eu criei uma pequena biblioteca que faz isso (junto com algumas outras conversões úteis). Chama-se reimg e é realmente simples de usar.

ReImg.fromCanvas(yourCanvasElement).toPng()

gillyb
fonte
Biblioteca legal. Obrigado. Há um pequeno problema na documentação de exemplo. Abri um problema no Github para chamar sua atenção.
jmknoll
7

Este trabalho para mim: (apenas o 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
fonte
Talvez você possa explicar a parte do seu código que responde à pergunta em vez de apenas colá-la sem nenhum comentário?
Gediminas Masaitis 03/03
6

Semelhante à resposta do 1000Bugy, mas mais simples, porque você não precisa fazer uma âncora instantaneamente e despachar um evento de clique manualmente (mais uma correção do IE).

Se você transformar o botão de download em uma âncora, poderá executá-lo rapidamente antes que a funcionalidade padrão da âncora seja executada. Assim, onAnchorClickvocê pode definir o href da âncora para a imagem base64 da tela e o atributo de download da âncora para o nome que desejar.

Isso não funciona no IE (atual) porque não implementa o atributo de download e impede o download de uris de dados. Mas isso pode ser corrigido usando em window.navigator.msSaveBlobvez disso.

Portanto, o seu manipulador de eventos clique âncora seria como seguido (onde anchor, canvase fileNamesão pesquisas de escopo):

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

Aqui está um violino

Sjeiti
fonte
1

Em vez de imageElement.src = myImage;você deve usarwindow.location = myImage;

E mesmo depois disso, o navegador exibirá a própria imagem. Você pode clicar com o botão direito e usar "Salvar link" para baixar a imagem.

Verifique este link para mais informações.

Hakan Serce
fonte
Uau, obrigado, isso realmente ajudou muito :) Mas como você obtém uma caixa de salvamento pop-up, para que alguém possa salvar em um destino específico (como a pasta de imagens do Android)?
Wardenclyffe
Depende do navegador específico. O navegador Android geralmente baixa arquivos diretamente para uma pasta específica, por exemplo.
Hakan Serce
No Chrome, isso funciona, mas o menu do botão direito está acinzentado. Ao tentar 'arrastar' a imagem para fora do navegador, o Chrome trava.
Kokodoko 15/05
groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… A abertura de um URL de dados como esse será bloqueada.
KeyOfJ
0

Você não pode usar os métodos mencionados anteriormente para baixar uma imagem ao executar no Cordova. Você precisará usar o Cordova File Plugin . Isso permitirá que você escolha onde salvá-lo e aproveite diferentes configurações de persistência. Detalhes aqui: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Como alternativa, você pode converter a imagem em base64 e armazenar a sequência no localStorage, mas isso preencherá sua cota rapidamente, se você tiver muitas imagens ou alta resolução.

BigBalli
fonte
-9

@Wardenclyffe e @SColvin, vocês estão tentando salvar uma imagem usando a tela, não usando o contexto da tela. você deve tentar ctx.toDataURL (); Tente isto:

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>

Você também pode consultar os seguintes links:

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
fonte
TypeError não capturado: o objeto # <CanvasRenderingContext2D> não tem método 'toDataURL'.
precisa
Isso está errado, pois o elemento de contexto não tem uma toDataURLfunção: developer.mozilla.org/en-US/docs/Web/API/… . Você deseja chamar toDataURLo elemento canvas: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot