Reputation: 81
I have one problem with HTML5 Canvas. I have one image. On this image I want to put text and display/save this as an image.
I have this code:
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function(){
context.drawImage(imageObj, 10, 10);
context.font = "20px Calibri";
context.fillText("My TEXT!", 50, 200);
};
imageObj.src = "mail-image.jpg";
};
This works fine. There is my image and the text on it. But it is still a canvas and no image. Can anybody help me?
Upvotes: 8
Views: 23710
Reputation:
Browsers are sand-boxed when it deals with saving content to user's hard disk. This is for security (you don't want a bad hacker (or spy) to overwrite system files or plant a virus or a backdoor etc.). So direct access is prevented and local storage is isolated.
You always need to "bridge" the content by an user interaction that approves the operation and therefor the browser will request you to choose a location for the file by popping up a dialog to make the user aware of that the browser tries to deliver content to be saved (see demo below).
Here are a couple of other possibilities to enable download.
If a link for example under the image is ok then you can do:
/// create an anchor/link (or use an existing)
var lnk = document.createElement('a');
/// set your image as data-uri link
lnk.href = canvas.toDataURL();
/// and the key, when user click image will be downloaded
lnk.download = 'filename.png';
/// add lnk to DOM, here after the canvas
canvas.parentElement.appendChild(lnk);
The download attribute is a new HTML5 feature. Instead of "navigating" to this location the browser will show a save dialog instead and let the user save its content to disk.
You can also automate the whole clicking feature by generating an event for it.
For example:
function download(canvas, filename) {
if (typeof filename !== 'string' || filename.trim().length === 0)
filename = 'Untitled';
var lnk = document.createElement('a'),
e;
lnk.download = filename;
lnk.href = canvas.toDataURL();
if (document.createEvent) {
e = document.createEvent("MouseEvents");
e.initMouseEvent('click', true, true, window,
0, 0, 0, 0, 0, false, false,
false, false, 0, null);
/// send event
lnk.dispatchEvent(e);
} else if (lnk.fireEvent) {
lnk.fireEvent("onclick");
}
}
You can always go by the step of saving the file to a server. However, you will also have to go through the save dialog step when retrieving the file from server (the dialog).
If you want to store the file only to be shown in the browser this is perfect.
There are various ways to do this (there are many solutions on SO for this).
And a different option is to store the file in the browser's local storage. You have Web Storage, however this is very limited (typically between 2.5 - 5 mb) and considering that each char stored takes two bytes the actual storage is just half of that (it can only store strings such as the data-uri and data-uris is about 33% larger than the original file). But if you save small icons, sprites etc. this might do.
In addition you can use Indexed DB (and the now deprectaed Web SQL) which can store larger data and you can also request user's permission to store x mb of dat.
The same goes with File API (which is currently only implemented in Chrome). This acts more like a file system and is intended to store huge files.
These might seem more complex if you are not familiar with them, but I mention them as possible options as these also saves you bandwidth communicating with a server and you move the "burden" to the client instead of the server.
Upvotes: 6
Reputation: 105035
For security reasons, there's no convenient way of saving a canvas drawing to a user's local drive.
As a workaround, go "old school": Convert the canvas to an image and display it in a new window.
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function(){
context.drawImage(imageObj, 10, 10);
context.font = "20px Calibri";
context.fillText("My TEXT!", 50, 200);
// open the image in a new browser tab
// the user can right-click and save that image
var win=window.open();
win.document.write("<img src='"+canvas.toDataURL()+"'/>");
};
imageObj.src = "mail-image.jpg";
};
Upvotes: 15