HTML5 Canvas to PNG File
Info: IE10+ doesn't support below method at all. Other people already did the work and implemented cross browser solutions.
This is one of them.
First, add the generated data URL to the href
attribute of an <a>
tag.
However on some browsers, this alone will not trigger a download. Instead it will open the linked image in a new page.
Download dialog for a base64 image:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...." class="image" />
Based on above example, convert the MIME type of the data URL to this:
<a href="data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUg....">Download</a>
By telling the browser that the data are application/octet-stream
, it will ask you to save it on your hard-disk.
Specifying a filename:
As Adi said in the comments below, there is no standard way to define a filename using this method. But, there are two approaches which might work in some browsers.
A) The download
attribute introduced by Google Crome
<a download="image.png" href="...">
B) Defining HTTP headers within the data URLheaders=Content-Disposition: attachment; filename=image.png
<a href="data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=image.png;base64,iVBORw0KGgoAAAA">
This worked at least in some older versions of Opera.
Here is some discussion about this.
Looking into the Bug/Feature-Tracking systems of the major browsers shows that defining a filename is quite a big wish of the community. Maybe we will see a cross-browser compatible solution in near future! ;)
Save RAM and CPU ressources:
If you don't want to bloat the RAM of your visitor's browser, you can also generate the data URL dynamically:
<a id="dl" download="Canvas.png">Download Canvas</a>
function dlCanvas() {
var dt = canvas.toDataURL('image/png');
this.href = dt;
};
dl.addEventListener('click', dlCanvas, false);
This way, your canvas may still be shown as an image file by your browser.
If you want to increase the probability to open a download dialog, you should extend the function above, so that it does the replacement as shown above:
function dlCanvas() {
var dt = canvas.toDataURL('image/png');
this.href = dt.replace(/^data:image\/[^;]/, 'data:application/octet-stream');
};
dl.addEventListener('click', dlCanvas, false);
Last, add the HTTP header to make extra sure that most browsers offer a valid filename to you! ;)
FULL EXAMPLE:
var canvas = document.getElementById("cnv");var ctx = canvas.getContext("2d");
/* FILL CANVAS WITH IMAGE DATA */function r(ctx, x, y, w, h, c) { ctx.beginPath(); ctx.rect(x, y, w, h); ctx.strokeStyle = c; ctx.stroke();}r(ctx, 0, 0, 32, 32, "black");r(ctx, 4, 4, 16, 16, "red");r(ctx, 8, 8, 16, 16, "green");r(ctx, 12, 12, 16, 16, "blue");
/* REGISTER DOWNLOAD HANDLER *//* Only convert the canvas to Data URL when the user clicks. This saves RAM and CPU ressources in case this feature is not required. */function dlCanvas() { var dt = canvas.toDataURL('image/png'); /* Change MIME type to trick the browser to downlaod the file instead of displaying it */ dt = dt.replace(/^data:image\/[^;]*/, 'data:application/octet-stream');
/* In addition to <a>'s "download" attribute, you can define HTTP-style headers */ dt = dt.replace(/^data:application\/octet-stream/, 'data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=Canvas.png');
this.href = dt;};document.getElementById("dl").addEventListener('click', dlCanvas, false);
<canvas id="cnv" width="32" height="32"></canvas><a id="dl" download="Canvas.png" href="#">Download Canvas</a>
How to save an HTML5 Canvas as an image on a server?
Here is an example of how to achieve what you need:
- Draw something (taken from canvas tutorial)
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
</script>
Capture HTML Canvas as gif/jpg/png/pdf?
Original answer was specific to a similar question. This has been revised:
const canvas = document.getElementById('mycanvas')
const img = canvas.toDataURL('image/png')
with the value in IMG you can write it out as a new Image like so:
document.getElementById('existing-image-id').src = img
or
document.write('<img src="'+img+'"/>');
HTML5 Save canvas to PNG
When you save the canvas in HTML5 you end up with a base64 string, at the start of this string is specific information about the image format. You will need to strip this off, if you wish to save the base64 for conversion to a hard file later. If you want to redraw the image onto a canvas (or some image control) you will need to prepend this information again.
Here's how you save your file:
var dataURL = document.getElementsByTagName("canvas")[0].toDataURL("image/png");
// strip off invalid data for saving
dataURL = dataURL.replace("data:image/png;base64,", "");
Now you can just convert your base64 string to an image and save to a hard file when you need to. If you want to display this image on a canvas again, here's how you do it:
function displayImage(base64string) {
var canvas = document.getElementsByTagName("canvas")[0];
var context = canvas.getContext("2d");
var image = new Image();
// prepend the required image info again
image.src = "data:image/png;base64," + base64string;
image.onload = function() {
context.drawImage(image, 0, 0);
}
}
Downloading Canvas element to an image
The one way to save is exporting as an image... You already found this solution, and it's the best one i think ;)
var canvas = document.getElementById("mycanvas");
var img = canvas.toDataURL("image/png");
document.write('<img src="'+img+'"/>');
You can use different image types. Change the mimetype in this function:
canvas.toDataURL("image/jpeg");
An other way to save canvas data (into a PDF) is using the wkhtmltopdf Library
Cheers. Frank
frankneff.ch / @frankneff
Convert HTML5 canvas to image link
Assuming that data = canvas.toDataURL("image/jpeg")
, you can specify a base64 link with the correct headers :
const canvas = document.querySelector('canvas')const button = document.querySelector('button')const ctx = canvas.getContext('2d')
canvas.width = window.innerWidthcanvas.height = window.innerHeight
ctx.fillStyle = 'red'ctx.fillRect(50, 50, 100, 100)
button.addEventListener('click', () => { let data = canvas.toDataURL("image/jpeg"); data = data.replace('data:image/jpeg;base64,', '') console.log(data) downloadImage(data);})
function downloadImage(data, filename = 'untitled.jpeg') { const a = document.createElement('a'); a.href = 'data:application/octet-stream;headers=Content-Disposition%3A%20attachment%3B%20filename=' + filename + ';base64,' + data; a.download = filename; document.body.appendChild(a); a.click();}
<button>Save</button><canvas></canvas>
Related Topics
How to Show Alternate Image If Source Image Is Not Found? (Onerror Working in Ie But Not in Mozilla)
Getting Value of HTML Checkbox from Onclick/Onchange Events
Retrieving Html5 Video Duration Separately from the File
How to Get the Background Color of an HTML Element
How to Get Element in User-Agent Shadow Root With JavaScript
Select All Div Text With Single Mouse Click
Submit Form Fields Inside Display:None Element
Styling ≪Input Type="File"≫
Why Is Using the JavaScript Eval Function a Bad Idea
Html "Overlay" Which Allows Clicks to Fall Through to Elements Behind It
How to Convert a Dom Node List to an Array in JavaScript
How to Escape Quotes in HTML Attribute Values
How to Get Nth-Child Selector to Skip Hidden Divs
How to Know If a Font (@Font-Face) Has Already Been Loaded
How to Have Content from an Iframe Overflow Onto the Parent Frame