I am wondering if it is possible to add a download function to a click event purely in Javascript, for example, when a user clicks on an image, it gets automatically downloaded. For example I have an image tag <img src="filelocation" id="img"/> and want it to be downloaded on click. (I can't use "download="myfile.png".
Is there something like
$('#img').on('click',function(e){
img.download="myfile.png";
});
All the answers online suggest adding the download="..." into my tag
Thanks!
Maybe something like this:
document.getElementById('download').click();
<a id="download" href="https://assets.entrepreneur.com/content/16x9/822/20150721193719-solshero3.jpeg" download hidden></a>
Play with it: here
But if you really can't have the download attribute: Play this then.
Good luck!!
You can create a anchor element on click of the image and use .click() to trigger the click on that anchor even if its not attach to your page.
And if this still violate the requirement, then you may have to achieve it with server-side works.
See Change name of download in javascript
window.onload = function() {
// Fake image for testment
var canvas = document.createElement('canvas');
canvas.width = 300;
canvas.height = 200;
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 200, 100);
ctx.fillStyle = 'cyan';
ctx.fillText('test', 50, 50);
var makeImageDownloadable = function(image, name) {
image.addEventListener('click', function() {
var a = document.createElement('a');
a.href = image.src;
// may need to check the datatype, or just write image to another tmp canvas first.
a.download = name + '.png';
a.click();
});
};
var image = new Image();
image.onload = function() {
document.querySelector('#holder').appendChild(image);
makeImageDownloadable(image, 'testimage');
};
image.src = canvas.toDataURL('image/png');
};
<div id="holder"></div>
You can use the HTML5 download attribute.
<a href="http://www.hdwallpapersimages.com/wp-content/uploads/2014/01/Winter-Tiger-Wild-Cat-Images.jpg" download="my_download.png"><img src="http://www.hdwallpapersimages.com/wp-content/uploads/2014/01/Winter-Tiger-Wild-Cat-Images.jpg">
</a>
I am unsure of browser compatibility in this,better soultion would be to include server side scripts too.
JSFiddle: http://jsfiddle.net/k2rear94/
if u want this to be dynamic, try this.
$("SomeElement").onclick = function(){
$("<a id='tmp' href='link' download ></a>).appendTo("body");
$("#tmp").click();
$("#tmp").remove();
}
But remember, download attribute is not supported in IE.
Related
I'm still new to this whole canvas things and there's something I have a problem with, namely, saving the content inside the canvas as image. Here's my fiddle
var img = new Image();
img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
};
var link = document.createElement('a');
link.innerHTML = 'Save';
link.href = document.getElementById('canvas').toDataURL();
link.addEventListener('click', function(e) {
link.download = "imagename.png";
}, false);
document.body.appendChild(link);
<canvas id="canvas" width="300" height="300"></canvas>
While the save dialog appears just fine, the saved image is empty, like it doesn't capture the content at all.
Any help is appreciated, moreso if it's accompanied by on how/why my code doesn't work and your code will. Thanks.
Edit: Forgot to link the fiddle I base my code from here The difference is that that fiddle saves the drawing in the canvas while what I wrote is merely saving a static image from another source.
You need to set image href inside of onload and use img.crossOrigin = "anonymous" just to avoid cross origin error.
var img = new Image();
img.crossOrigin = "anonymous";
img.src = 'http://farm5.static.flickr.com/4005/4706825697_c0367e6dee_b.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
img.onload = function() {
ctx.drawImage(img, 0, 0, 300, 300);
link.href = document.getElementById('canvas').toDataURL();
};
var link = document.createElement('a');
link.innerHTML = 'Save';
//link.href = document.getElementById('canvas').toDataURL();
link.addEventListener('click', function(e) {
link.download = "imagename.png";
}, false);
document.body.appendChild(link);
<canvas id="canvas" width="300" height="300"></canvas>
There are two issues.
The first is the image's origin. On JSFiddle you'll get an Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
As mentioned in another answer, Base64 encoding the image then setting img.src = 'data:image/jpeg;base64,/...'; resolves this problem.
Another solution: run a web server locally, and source the image by its location on the server, e.g. img.src = './rhino.jpg';.
Even after that's handled, the downloaded image will be "empty," as before. This is because of the order of execution of your code. link.href = canvas.toDataURL(); executes before the image's 'load' event fires, so the canvas is empty at the point you're setting the data.
Placing that line inside the img.onload function ensures that the link's download data is set only after the image has loaded. This approach is convenient, because it allows for the <a> tag to behave with default behavior once the href attribute is set (e.g. pointer on hover, underlined text by default).
Placing that line, instead, inside the link's 'click' event handler incidentally works, but you lose the default link behavior mentioned above.
Here's an example of the working JS, assuming the image file is on the server:
var img = new Image();
img.src = './rhino.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var link = document.createElement('a');
link.innerHTML = 'Save';
img.onload = function() {
ctx.drawImage(img, 0, 0);
img.style.display = 'none';
link.href = canvas.toDataURL();
};
link.addEventListener('click', function(e) {
link.download = "imagename.png";
}, false);
document.body.appendChild(link);
And a JSFiddle, using the Base-64 encoded image.
I'm using a plugin (dom-to-image) to generate a SVG content from a div.
It returns me a dataURL like this:
data image/xml, charset utf-8, <svg...
If a put this on a <img src the image is shown to normally.
The intent is to grab this dataURL, convert it to base64 so I can save it as an image.png on a mobile app.
Is it possible?
I tryied this solution https://stackoverflow.com/a/28450879/1691609
But coudn't get to work.
The console fire an error about the dataUrl
TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
==== UPDATE :: PROBLEM EXPLANATION/HISTORY ====
I'm using Ionic Framework, so my project is an mobile app.
The dom-to-image is already working cause right now, its rendering a PNG through toPng function.
The problem is the raster PNG is a blurry.
So I thought: Maybe the SVG will have better quality.
And it IS!! Its 100% perfect, actually.
On Ionic, I'm using 2 step procedure to save the image.
After get the PNG generated by the dom-to-img(base64) dataURL, I convert it to a Blob and then save into device.
This is working, but the final result, as I said, is blurry.
Then with SVG maybe it will be more "high quality" per say.
So, in order to do "minimal" change on a process that s already working :D I just need to convert an SVG into base64 dataURL....
Or, as some of you explained to me, into something else, like canvas...
I don't know any much :/
===
Sorry for the long post, and I really, really thank your help guys!!
EDIT COUPLE OF YARS LATER
Use JS fiddle for a working example: https://jsfiddle.net/msb42ojx/
Note, if you don't own DOM content (images), and those images don't have CORS enabled for everyone (Access-Control-Allow-Origin header), canvas cant render those images
I'm not trying to find out why is your case not working, here is how I did when I had something similar to do:
get the image sourcce (dom-to-image result)
set up a canvas with that image inside (using the image source)
download the image from canvas in whatever image you like: png, jpeg whatever
by the way you can resize the image to a standard format
document.getElementById('mydownload').onclick= function(){
var wrapper = document.getElementById('wrapper');
//dom to image
domtoimage.toSvg(wrapper).then(function (svgDataUrl) {
//download function
downloadPNGFromAnyImageSrc(svgDataUrl);
});
}
function downloadPNGFromAnyImageSrc(src)
{
//recreate the image with src recieved
var img = new Image;
//when image loaded (to know width and height)
img.onload = function(){
//drow image inside a canvas
var canvas = convertImageToCanvas(img);
//get image/png from convas
var pngImage = convertCanvasToImage(canvas);
//download
var anchor = document.createElement('a');
anchor.setAttribute('href', pngImage.src);
anchor.setAttribute('download', 'image.png');
anchor.click();
};
img.src = src;
// Converts image to canvas; returns new canvas element
function convertImageToCanvas(image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
}
}
#wrapper{
background: red;
color: blue;
}
<script src="https://rawgit.com/tsayen/dom-to-image/master/src/dom-to-image.js"></script>
<button id='mydownload'>Download DomToImage</button>
<div id="wrapper">
<img src="http://i.imgur.com/6GvKdxY.jpg"/>
<div> DUDE IS WORKING</div>
<img src="http://i.imgur.com/6GvKdxY.jpg"/>
</div>
I translated #SilentTremor's solution into React/JS-Class:
class SVGToPNG {
static convert = function (src) {
var img = new Image();
img.onload = function () {
var canvas = SVGToPNG.#convertImageToCanvas(img);
var pngImage = SVGToPNG.#convertCanvasToImage(canvas);
var anchor = document.createElement("a");
anchor.setAttribute("href", pngImage.src);
anchor.setAttribute("download", "image.png");
anchor.click();
};
img.src = src;
};
static #convertImageToCanvas = function (image) {
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.getContext("2d").drawImage(image, 0, 0);
return canvas;
};
static #convertCanvasToImage = function (canvas) {
var image = new Image();
image.src = canvas.toDataURL("image/png");
return image;
};
}
export default SVGToPNG;
Usage:
let dataUrl = someCanvas.toDataURL("image/svg+xml");
SVGToPNG.convert(dataUrl);
I'm converting an HTML canvas into a jpg when a save button is clicked. I use the code below:
$('#save').click(function(e){
var canvas = $('#myCanvas')[0];
var image = canvas.toDataURL("image/png").replace("image/png","image/octet-stream");
window.location.href=image; // it will save locally
});
Unfortunately, I download file without any extension. What I want is when I click the download button, The browser must download file from the page with a file extension.
Thanks
#K3N's answer didn't work for me because as mentioned:
Ideally you set the href before the click somehow.
I built on top of it and did this and it works great.
var btnSave = document.getElementById('btnSave');
btnSave.addEventListener('click', function() {
var image = photo.toDataURL("image/png");
var anchor = document.createElement('a');
anchor.setAttribute('download', 'myFilename.png');
anchor.setAttribute('href', image);
anchor.click();
});
Assuming your #save element is an anchor tag (<a ...></a>) you can do this:
$('#save').click(function(e){
var canvas = $('#myCanvas')[0];
var image = canvas.toDataURL("image/png");
$('#save').attr({
'download': 'myFilename.png', /// set filename
'href' : image /// set data-uri
});
});
Ideally you set the href before the click somehow.
You should use:
var canvas = document.getElementById("mycanvas");
var img = canvas.toDataURL("image/png");
for loading,you need to use:
document.write('<img src="'+img+'"/>');
Can we save the image in canvas. Like as shown in the JSFiddle.
I want to save the image in such a way the balloon should come over the image
$(document).ready(function() {
var d_canvas = document.getElementById('canvas');
var context = d_canvas.getContext('2d');
var background = document.getElementById('background');
var ballon = document.getElementById('ballon')
context.drawImage(background, 0, 0);
$('#ballon').draggable();
$('#draw').click(function() {
var $ballon = $('#ballon'),
$canvas = $('#canvas');
var ballon_x = $ballon.offset().left - $canvas.offset().left,
ballon_y = $ballon.offset().top - $canvas.offset().top;
context.drawImage(ballon, ballon_x, ballon_y);
$ballon.hide();
$(this).attr('disabled', 'disabled');
});
});
There are generally two ways to get an image from a canvas:
using getImageData() to get the rgba value for every pixel for a given rectangle of the canvas.
using toDataURL() to get a Base64 string of the entire canvas.
The second method is probably most useful, and combined with some HTML5 magic, and the download attribute, we can create a downloadable image or send the string to the server and save it as an image :
var base64 = d_canvas.toDataURL("image/png");
var a = document.createElement('a');
a.href = base64,
a.target = '_blank';
a.download = 'myImage.png';
document.body.appendChild(a);
a.click();
If you need the baloon to be in a specific place, moving that should be trivial.
Here's a
FIDDLE
Note that I had to remove the external images and use base64 to avoid cross-origin images in the canvas.
It would be incredibly useful to be able to temporarily convert a regular element into a canvas. For example, say I have a styled div that I want to flip. I want to dynamically create a canvas, "render" the HTMLElement into the canvas, hide the original element and animate the canvas.
Can it be done?
There is a library that try to do what you say.
See this examples and get the code
http://hertzen.com/experiments/jsfeedback/
http://html2canvas.hertzen.com/
Reads the DOM, from the html and render it to a canvas, fail on some, but in general works.
Take a look at this tutorial on MDN: https://developer.mozilla.org/en/HTML/Canvas/Drawing_DOM_objects_into_a_canvas (archived)
Its key trick was:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var data = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">' +
'<foreignObject width="100%" height="100%">' +
'<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">' +
'<em>I</em> like ' +
'<span style="color:white; text-shadow:0 0 2px blue;">' +
'cheese</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var DOMURL = window.URL || window.webkitURL || window;
var img = new Image();
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
}
img.src = url;
That is, it used a temporary SVG image to include the HTML content as a "foreign element", then renders said SVG image into a canvas element. There are significant restrictions on what you can include in an SVG image in this way, however. (See the "Security" section for details — basically it's a lot more limited than an iframe or AJAX due to privacy and cross-domain concerns.)
Sorry, the browser won't render HTML into a canvas.
It would be a potential security risk if you could, as HTML can include content (in particular images and iframes) from third-party sites. If canvas could turn HTML content into an image and then you read the image data, you could potentially extract privileged content from other sites.
To get a canvas from HTML, you'd have to basically write your own HTML renderer from scratch using drawImage and fillText, which is a potentially huge task. There's one such attempt here but it's a bit dodgy and a long way from complete. (It even attempts to parse the HTML/CSS from scratch, which I think is crazy! It'd be easier to start from a real DOM node with styles applied, and read the styling using getComputedStyle and relative positions of parts of it using offsetTop et al.)
You can use dom-to-image library (I'm the maintainer).
Here's how you could approach your problem:
var parent = document.getElementById('my-node-parent');
var node = document.getElementById('my-node');
var canvas = document.createElement('canvas');
canvas.width = node.scrollWidth;
canvas.height = node.scrollHeight;
domtoimage.toPng(node).then(function (pngDataUrl) {
var img = new Image();
img.onload = function () {
var context = canvas.getContext('2d');
context.translate(canvas.width, 0);
context.scale(-1, 1);
context.drawImage(img, 0, 0);
parent.removeChild(node);
parent.appendChild(canvas);
};
img.src = pngDataUrl;
});
And here is jsfiddle
Building on top of the Mozdev post that natevw references I've started a small project to render HTML to canvas in Firefox, Chrome & Safari. So for example you can simply do:
rasterizeHTML.drawHTML('<span class="color: green">This is HTML</span>'
+ '<img src="local_img.png"/>', canvas);
Source code and a more extensive example is here.
No such thing, sorry.
Though the spec states:
A future version of the 2D context API may provide a way to render fragments of documents, rendered using CSS, straight to the canvas.
Which may be as close as you'll get.
A lot of people want a ctx.drawArbitraryHTML/Element kind of deal but there's nothing built in like that.
The only exception is Mozilla's exclusive drawWindow, which draws a snapshot of the contents of a DOM window into the canvas. This feature is only available for code running with Chrome ("local only") privileges. It is not allowed in normal HTML pages. So you can use it for writing FireFox extensions like this one does but that's it.
You could spare yourself the transformations, you could use CSS3 Transitions to flip <div>'s and <ol>'s and any HTML tag you want. Here are some demos with source code explain to see and learn: http://www.webdesignerwall.com/trends/47-amazing-css3-animation-demos/
the next code can be used in 2 modes, mode 1 save the html code to a image, mode 2 save the html code to a canvas.
this code work with the library: https://github.com/tsayen/dom-to-image
*the "id_div" is the id of the element html that you want to transform.
**the "canvas_out" is the id of the div that will contain the canvas
so try this code.
:
function Guardardiv(id_div){
var mode = 2 // default 1 (save to image), mode 2 = save to canvas
console.log("Process start");
var node = document.getElementById(id_div);
// get the div that will contain the canvas
var canvas_out = document.getElementById('canvas_out');
var canvas = document.createElement('canvas');
canvas.width = node.scrollWidth;
canvas.height = node.scrollHeight;
domtoimage.toPng(node).then(function (pngDataUrl) {
var img = new Image();
img.onload = function () {
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
};
if (mode == 1){ // save to image
downloadURI(pngDataUrl, "salida.png");
}else if (mode == 2){ // save to canvas
img.src = pngDataUrl;
canvas_out.appendChild(img);
}
console.log("Process finish");
});
}
so, if you want to save to image just add this function:
function downloadURI(uri, name) {
var link = document.createElement("a");
link.download = name;
link.href = uri;
document.body.appendChild(link);
link.click();
}
Example of use:
<html>
<head>
</script src="/dom-to-image.js"></script>
</head>
<body>
<div id="container">
All content that want to transform
</div>
<button onclick="Guardardiv('container');">Convert<button>
<!-- if use mode 2 -->
<div id="canvas_out"></div>
</html>
Comment if that work.
Comenten si les sirvio :)
The easiest solution to animate the DOM elements is using CSS transitions/animations but I think you already know that and you try to use canvas to do stuff CSS doesn't let you to do. What about CSS custom filters? you can transform your elements in any imaginable way if you know how to write shaders. Some other link and don't forget to check the CSS filter lab.
Note: As you can probably imagine browser support is bad.
function convert() {
dom = document.getElementById('divname');
var script,
$this = this,
options = this.options,
runH2c = function(){
try {
var canvas = window.html2canvas([ document.getElementById('divname') ], {
onrendered: function( canvas ) {
window.open(canvas.toDataURL());
}
});
} catch( e ) {
$this.h2cDone = true;
log("Error in html2canvas: " + e.message);
}
};
if ( window.html2canvas === undefined && script === undefined ) {
} else {.
// html2canvas already loaded, just run it then
runH2c();
}
}