Как сохранить холст как изображение с помощью canvas.toDataURL ()?


150

В настоящее время я создаю веб-приложение HTML5 / собственное приложение Phonegap, и я не могу понять, как сохранить свой холст в виде изображения с помощью canvas.toDataURL(). Кто-нибудь может мне помочь?

Вот код, что с ним не так?

// Мой холст был назван "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>

5
Вопрос ОП не получил ответа. Он четко сказал, что это для Phonegap / iPad. Приведенные ответы предназначены для сохранения в настольном браузере.
tshm001

1
Не уверен насчет телефонного разговора, но я сделал это с нуля в родном iOS, используя JavaScript на другом конце, я захватываю данные .toDataURL(), а затем использую window.location, чтобы указать браузер appname://[data url]. В конце приложения UIWebView имеет метод делегата, который сообщает, следует ли загружать страницу. Я слушаю appname://и разбиваю его, когда он приходит, запрещаю загрузку страницы и фиксирую URL-адрес данных в собственной строке ... насколько вы знакомы с реальным кодом iOS / Objective C?
Дуг,

Ответы:


133

Вот код. без ошибок.

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

1
За исключением стандартного режима IE9: «Некоторое содержимое или файлы на этой веб-странице требуют программы, которую вы не установили». Internet Explorer 8 и выше поддерживает только URI данных для изображений в CSS, <link> и <img>: developer.mozilla.org/en-US/docs/data_URIs
Cees Timmerman

45
работает отлично. как я могу изменить имя загруженного файла? идет просто «скачать» и без расширения. Благодарность!
Leabdalla

1
В Chrome это приводит к сбою браузера. Если я показываю изображение в теге изображения, оно работает, но контекстное меню отображается серым цветом, поэтому я все еще не могу сохранить изображение.
Кокодоко

Это прекрасно работает ... Но в Android (браузер по умолчанию в Galaxy S3) он просто не загружает изображение, но я получаю сообщение «Загрузка ...» навсегда.
Хабрашат

У меня есть проблема с сохранением, кто-то может помочь мне увидеть эту ссылку: stackoverflow.com/questions/25131763/…
Рамеш С.

42

Это решение позволяет изменить имя загруженного файла:

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

Спасибо за это, мне это очень помогло!
Майк Мун,

23

Вы можете использовать canvas2image для запроса загрузки.

У меня была такая же проблема, вот простой пример, который добавляет изображение на страницу и заставляет браузер загружать его:

<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>

2
Просто попробовал, он сохранит файл без имени и расширения в Chrome.
malber

как упоминалось здесь nihilogic.dk/labs/canvas2image, установка имени файла кажется невозможной: «Было бы здорово, если бы каким-то образом имя файла могло быть прикреплено к данным, но я не нашел способа сделать это. На данный момент вам нужно указать имя файла самостоятельно. "
SColvin

1
Отправленная вами ссылка не работает
Оливер Нибро

13

Вы можете попробовать это; создать фиктивный HTML-якорь и загрузить изображение оттуда, например ...

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

2
Мне нравится, что все было сделано на JS, включая создание элемента ссылки. Он отлично работает в целях автоматизации
Джероми Адофо

1
Идеальное решение
Хидайт Рахман

10

Я создал небольшую библиотеку, которая делает это (вместе с некоторыми другими удобными преобразованиями). Это называется reimg , и им очень просто пользоваться.

ReImg.fromCanvas(yourCanvasElement).toPng()


Классная библиотека. Спасибо. Однако в документации к примеру есть небольшая проблема. Я открыл проблему на Github, чтобы довести ее до вашего сведения.
jmknoll

8

Эта работа для меня: (Только 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>

Возможно, вы могли бы объяснить ту часть кода, которая отвечает на вопрос, вместо того, чтобы просто вставлять ее без комментариев?
Гедиминас Масайтис 03

7

Подобен ответу 1000Bugy, но проще, потому что вам не нужно делать якорь на лету и отправлять событие щелчка вручную (плюс исправление IE).

Если вы сделаете свою кнопку загрузки якорем, вы можете взломать ее прямо перед запуском функции привязки по умолчанию. Таким образом, onAnchorClickвы можете установить привязку href к изображению base64 холста, а атрибут загрузки привязки - к тому, что вы хотите назвать своим изображением.

Это не работает в (текущем) IE, потому что он не реализует атрибут загрузки и предотвращает загрузку uris данных. Но это можно исправить, используя window.navigator.msSaveBlobвместо этого.

Таким образом , ваш якорь обработчик события клика будет как следует (где anchor, canvasи fileNameесть область применения средства поиска):

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

Вот скрипка


2

Вместо imageElement.src = myImage;вас следует использоватьwindow.location = myImage;

И даже после этого браузер отобразит само изображение. Вы можете щелкнуть правой кнопкой мыши и использовать «Сохранить ссылку» для загрузки изображения.

Проверьте эту ссылку для получения дополнительной информации.


Вау, спасибо, это действительно очень помогло :) Но как получить всплывающее окно для сохранения, чтобы кто-то мог сохранять в определенном месте (например, в папке с изображениями Android)?
Wardenclyffe

Это зависит от конкретного браузера. Браузер Android обычно загружает файлы напрямую в определенную папку.
Hakan Serce

В Chrome это работает, но контекстное меню отображается серым цветом. При попытке «перетащить» изображение из браузера Chrome вылетает.
Кокодоко

groups.google.com/a/chromium.org/forum/#!topic/blink-dev/… Открывающий URL-адрес данных, как это, похоже, будет заблокирован.
KeyOfJ

0

Вы не можете использовать ранее упомянутые методы для загрузки изображения при работе в Кордове. Вам нужно будет использовать плагин Cordova File . Это позволит вам выбрать, где его сохранить, и использовать различные параметры сохранения. Подробности здесь: https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-file/

В качестве альтернативы вы можете преобразовать изображение в base64, а затем сохранить строку в localStorage, но это довольно быстро заполнит вашу квоту, если у вас много изображений или в высоком разрешении.


-9

@Wardenclyffe и @SColvin, вы оба пытаетесь сохранить изображение, используя холст, а не контекст холста. оба вы должны попробовать ctx.toDataURL (); Попробуй это:

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>

Также вы можете воспользоваться следующими ссылками:

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


Uncaught TypeError: объект № <CanvasRenderingContext2D> не имеет метода toDataURL.
Брэндон Оби,

1
Это неверно, поскольку у элемента контекста нет toDataURLфункции: developer.mozilla.org/en-US/docs/Web/API/… . Вы хотите вызвать toDataURLэлемент холста: developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/…
Crashalot
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.