Jak zapisać płótno jako obraz za pomocą canvas.toDataURL ()?

141

Obecnie tworzę aplikację internetową HTML5 / natywną aplikację Phonegap i nie wiem, jak zapisać płótno jako obraz canvas.toDataURL(). Czy ktoś może mi pomóc?

Oto kod, co jest z nim nie tak?

// Moje płótno nosiło nazwę „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
źródło
4
Nie udzielono odpowiedzi na pytanie OP. Wyraźnie powiedział, że dotyczy to Phonegap / iPad. Podane odpowiedzi służą do zapisania w przeglądarce na komputerze.
tshm001
1
Nie jestem pewien co do phonegap, ale zrobiłem to od zera w natywnym iOS, używając JavaScript na drugim końcu, przechwytuję dane .toDataURL(), a następnie używam window.location, aby wskazać przeglądarkę appname://[data url]. Na końcu aplikacji UIWebView ma metodę delegata, która mówi, czy powinna załadować stronę. Nasłuchuję appname://i rozbijam, gdy się pojawia, odmawiam ładowania strony i przechwytuję adres URL danych w natywnym ciągu ... jak dobrze znasz kod iOS / Objective C?
Doug

Odpowiedzi:

121

Oto kod. bez żadnego błędu.

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
źródło
1
Z wyjątkiem trybu standardowego IE9: „Niektóre treści lub pliki na tej stronie wymagają programu, którego nie masz zainstalowanego”. Internet Explorer 8 i nowsze obsługują tylko identyfikatory URI danych dla obrazów w CSS, <link> i <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman,
45
działa w porządku. jak mogę zmienić nazwę pobranego pliku? nadchodzi po prostu „pobierz” i bez rozszerzenia. dzięki!
Leabdalla
1
W Chrome powoduje to awarię przeglądarki. Jeśli wyświetlam obraz w tagu obrazu, działa, ale menu prawego przycisku myszy jest wyszarzone - więc nadal nie mogę zapisać obrazu.
Kokodoko
To działa świetnie ... Ale w Androidzie (domyślna przeglądarka w Galaxy S3) po prostu nie pobiera obrazu, ale na zawsze pojawia się komunikat „Pobieranie ...”.
Habrashat
Mam problem z zapisem, ktoś może mi pomóc zobaczyć ten link: stackoverflow.com/questions/25131763/…
Ramesh S
36

To rozwiązanie umożliwia zmianę nazwy pobranego pliku:

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.
źródło
Dziękuję za to, bardzo mi to pomogło!
Mike Moon
22

Możesz użyć canvas2image, aby poprosić o pobranie.

Miałem ten sam problem, oto prosty przykład, który zarówno dodaje obraz do strony, jak i zmusza przeglądarkę do pobrania go:

<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
źródło
2
Właśnie go wypróbowałem, zapisze plik bez nazwy ani rozszerzenia w Chrome.
Malber
jak wspomniano tutaj nihilogic.dk/labs/canvas2image, ustawienie nazwy pliku nie wydaje się możliwe: „Byłoby naprawdę fajnie, gdyby w jakiś sposób można było dołączyć nazwę pliku do danych, ale nie znalazłem sposobu, aby to zrobić. Na razie musisz samodzielnie określić nazwę pliku ”.
SColvin,
1
Link, który opublikowałeś jest uszkodzony
Oliver Nybroe
9

Możesz spróbować tego; utwórz fikcyjną kotwicę HTML i pobierz stamtąd obraz, taki jak ...

// 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
źródło
1
Podoba mi się fakt, że wszystko zostało zrobione w JS, łącznie ze stworzeniem elementu link. Działa świetnie do celów automatyzacji
Jeromy Adofo
Idealne rozwiązanie
Hidayt Rahman
8

Stworzyłem małą bibliotekę, która to robi (wraz z kilkoma innymi przydatnymi konwersjami). Nazywa się reimg i jest naprawdę prosty w użyciu.

ReImg.fromCanvas(yourCanvasElement).toPng()

gillyb
źródło
Fajna biblioteka. Dzięki. Jednak w przykładowej dokumentacji jest mały problem. Otworzyłem numer na Github, aby zwrócić na niego uwagę.
jmknoll
7

To działa dla mnie: (tylko 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
źródło
Może mógłbyś wyjaśnić część swojego kodu, która odpowiada na pytanie, zamiast po prostu wklejać ją bez żadnych komentarzy?
Gediminas Masaitis
6

Podobna do odpowiedzi 1000Bugy, ale prostsza, ponieważ nie musisz tworzyć kotwicy w locie i ręcznie wywoływać zdarzenia kliknięcia (plus poprawka IE).

Jeśli ustawisz przycisk pobierania jako kotwicę, możesz go skradać tuż przed uruchomieniem domyślnej funkcji kotwicy. onAnchorClickMożesz więc ustawić href kotwicy na obraz kanwy base64, a atrybut pobierania kotwicy na cokolwiek chcesz nazwać swój obraz.

Nie działa to w (bieżącej) przeglądarce IE, ponieważ nie implementuje atrybutu pobierania i zapobiega pobieraniu danych uris. Ale można to naprawić, używając window.navigator.msSaveBlobzamiast tego.

Więc kotwica obsługi zdarzenia kliknięcia będzie następująco (gdzie anchor, canvasi fileNamesą wyszukiwań zakres):

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

Oto skrzypce

Sjeiti
źródło
1

Zamiast tego imageElement.src = myImage;powinieneś użyćwindow.location = myImage;

I nawet po tym przeglądarka wyświetli sam obraz. Możesz kliknąć prawym przyciskiem myszy i użyć „Zapisz łącze”, aby pobrać obraz.

Sprawdź to łącze, aby uzyskać więcej informacji.

Hakan Serce
źródło
Wow, dzięki, to naprawdę bardzo pomogło :) Ale jak uzyskać wyskakujące okienko zapisu, aby ktoś mógł zapisać w określonym miejscu (np. W folderze z obrazami na Androida)?
Wardenclyffe
To zależy od konkretnej przeglądarki. Przeglądarka Androida zazwyczaj pobiera pliki bezpośrednio do określonego folderu, na przykład.
Hakan Serce
W Chrome to działa, ale menu prawego przycisku myszy jest wyszarzone. Podczas próby „przeciągnięcia” obrazu z przeglądarki Chrome ulega awarii.
Kokodoko
groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… Wygląda na to, że otwieranie adresu URL danych, takiego jak ten, zostanie zablokowane.
KeyOfJ
0

Nie możesz użyć wyżej wymienionych metod do pobrania obrazu podczas pracy w Cordova. Będziesz musiał użyć wtyczki Cordova File . Umożliwi to wybranie miejsca zapisania i wykorzystanie różnych ustawień trwałości. Szczegóły tutaj: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

Alternatywnie możesz przekonwertować obraz na base64, a następnie zapisać ciąg w localStorage, ale to dość szybko wypełni twój limit, jeśli masz wiele obrazów lub wysokiej rozdzielczości.

BigBalli
źródło
-9

@Wardenclyffe i @SColvin, oboje próbujesz zapisać obraz za pomocą płótna, a nie kontekstu płótna. w obu przypadkach należy spróbować ctx.toDataURL (); Spróbuj tego:

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>

Możesz również skorzystać z poniższych linków:

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
źródło
Uncaught TypeError: Object # <CanvasRenderingContext2D> nie ma metody „toDataURL”.
Brandon Aubie,
To jest złe, ponieważ element kontekstu nie ma toDataURLfunkcji: developer.mozilla.org/en-US/docs/Web/API/… . Chcesz wywołać toDataURLelement canvas: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot