canvas.toDataURL() not working properly except mozilla firefox - javascript

I have developed a coupon generator module in the site I create a coupon in the html format and fill that html value in canvas by using JavaScript function which is
function checkcanvas(id) {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var data = "<svg xmlns='http://www.w3.org/2000/svg' width='437' height='262'>"
+ "<foreignObject width='100%' height='100%'>"
+ "<div xmlns='http://www.w3.org/1999/xhtml' style='font-size:40px'>"
+ $("#coupon_td").html()
+ "</div>"
+ "</foreignObject>"
+ "</svg>";
var DOMURL = self.URL || self.webkitURL || self;
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;
if(id == 2) {
document.getElementById('base_64_img').value = canvas.toDataURL();
}
}
base_64_img is just a hidden element so I can post the data into my php code and create a image using base64 code.
The biggest issue I am facing that this code perfectly worked in Mozilla Firefox almost every version but not working in Google chrome.

In your code you are generating an "SVG IMAGE" and trying to convert into toDataURL().
var svg = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
This is the problem, from this URL toDataURL :
If the type requested is not image/png, and the returned value starts
with data:image/png, then the requested type is not supported.
In this fiddlecode if you see the printed output , "data:image/png;base64". its supposed to be "data:image/svg;base64".
Instead of creating svg image, use canvas element and javascript to draw the related banner image and if you take the output then try copy & paste in your browser. ( it may work ).
Check this js plugin called SVG.toDataURL
Hope this helps.

Related

How to download an image object from webgl/javascript

I have a directory with 100 images. I need a copy of them in various folders along with other information that I download from webgl. Hence I want to upload them onto the browser and download them again (hope that isn't stupid)
Here is my code:
var imagefile = model.features[cIndex].imageName.substring(model.features[cIndex].imageName.lastIndexOf('/')+1);
var image = new Image();
image.src = model.imageDirectory + imagefile;
image.onload = function() {
console.info("Read \""+image.src + "\"...Done");
}
image.onerror = function() {
var message = "Unable to open \"" + image.src + "\".";
console.error(message);
alert(message);
}
var data = image.src;
zip.file('image_RH_Original' + cIndex +'.png', data , {base64: true});
Is this wrong? How to I do something similar to "toDataURL" for the image object?
toDataURL is a method of canvas, and webgl draws to a canvas. So just call canvas.toDataURL(). Probably need to set preserveDrawingBuffer to true as well.

How do I save/export an SVG file after creating an SVG with D3.js (IE, safari and chrome)?

I currently have a website using D3 and I'd like the user to have the option to save the SVG as an SVG file. I'm using crowbar.js to do this, but it only works on chrome. Nothing happens of safari and IE gives an access denied on the click() method used in crowbar.js to download the file.
var e = document.createElement('script');
if (window.location.protocol === 'https:') {
e.setAttribute('src', 'https://raw.github.com/NYTimes/svg-crowbar/gh-pages/svg-crowbar.js');
} else {
e.setAttribute('src', 'http://nytimes.github.com/svg-crowbar/svg-crowbar.js');
}
e.setAttribute('class', 'svg-crowbar');
document.body.appendChild(e);
How do I download an SVG file based on the SVG element on my website in safari, IE and chrome?
There are 5 steps. I often use this method to output inline svg.
get inline svg element to output.
get svg source by XMLSerializer.
add name spaces of svg and xlink.
construct url data scheme of svg by encodeURIComponent method.
set this url to href attribute of some "a" element, and right click this link to download svg file.
//get svg element.
var svg = document.getElementById("svg");
//get svg source.
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);
//add name spaces.
if(!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)){
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if(!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)){
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}
//add xml declaration
source = '<?xml version="1.0" standalone="no"?>\r\n' + source;
//convert svg source to URI data scheme.
var url = "data:image/svg+xml;charset=utf-8,"+encodeURIComponent(source);
//set url value to a element's href attribute.
document.getElementById("link").href = url;
//you can download svg file by right click menu.
I know this has already been answered, and that answer works well most of the time. However I found that it failed on Chrome (but not Firefox) if the svg image was large-ish (about 1MB). It works if you go back to using a Blob construct, as described here and here. The only difference is the type argument. In my code I wanted a single button press to download the svg for the user, which I accomplished with:
var svgData = $("#figureSvg")[0].outerHTML;
var svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = "newesttree.svg";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
October 2019 edit:
Comments have indicated that this code will work even without appending downloadLink to document.body and subsequently removing it after click(). I believe that used to work on Firefox, but as of now it no longer does (Firefox requires that you append and then remove downloadLink). The code works on Chrome either way.
Combining Dave's and defghi1977 answers. Here is a reusable function:
function saveSvg(svgEl, name) {
svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
var svgData = svgEl.outerHTML;
var preface = '<?xml version="1.0" standalone="no"?>\r\n';
var svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"});
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
Invocation example:
saveSvg(svg, 'test.svg')
For this snippet to work you need FileSaver.js.
function save_as_svg(){
var svg_data = document.getElementById("svg").innerHTML //put id of your svg element here
var head = '<svg title="graph" version="1.1" xmlns="http://www.w3.org/2000/svg">'
//if you have some additional styling like graph edges put them inside <style> tag
var style = '<style>circle {cursor: pointer;stroke-width: 1.5px;}text {font: 10px arial;}path {stroke: DimGrey;stroke-width: 1.5px;}</style>'
var full_svg = head + style + svg_data + "</svg>"
var blob = new Blob([full_svg], {type: "image/svg+xml"});
saveAs(blob, "graph.svg");
};
I tryed every solution here and nothing worked for me. My picture was always smaller than my d3.js canvas.
I had to set the canvas width, height then do a clearRect on the context to make it works. Here is my working version
Export function:
var svgHtml = document.getElementById("d3-canvas"),
svgData = new XMLSerializer().serializeToString(svgHtml),
svgBlob = new Blob([svgData], {type:"image/svg+xml;charset=utf-8"}),
bounding = svgHtml.getBoundingClientRect(),
width = bounding.width * 2,
height = bounding.height * 2,
canvas = document.createElement("canvas"),
context = canvas.getContext("2d"),
exportFileName = 'd3-graph-image.png';
//Set the canvas width and height before loading the new Image
canvas.width = width;
canvas.height = height;
var image = new Image();
image.onload = function() {
//Clear the context
context.clearRect(0, 0, width, height);
context.drawImage(image, 0, 0, width, height);
//Create blob and save if with FileSaver.js
canvas.toBlob(function(blob) {
saveAs(blob, exportFileName);
});
};
var svgUrl = URL.createObjectURL(svgBlob);
image.src = svgUrl;
It use FileSaver.js to save the file.
This is my canvas creation, note that i solve the namespace issue here
d3.js canvas creation:
var canvas = d3.select("body")
.insert("svg")
.attr('id', 'd3-canvas')
//Solve the namespace issue (xmlns and xlink)
.attr("xmlns", "http://www.w3.org/2000/svg")
.attr("xmlns:xlink", "http://www.w3.org/1999/xlink")
.attr("width", width)
.attr("height", height);
While this question has been answered, I created a small library called SaveSVG which can help save D3.js generated SVG which use external stylesheets or external definition files (using <use> and def) tags.
Based on #vasyl-vaskivskyi 's answer.
<script src="../../assets/FileSaver.js"></script>
<script>
function save_as_svg(){
fetch('path/../assets/chart.css')
.then(response => response.text())
.then(text => {
var svg_data = document.getElementById("svg").innerHTML
var head = '<svg title="graph" version="1.1" xmlns="http://www.w3.org/2000/svg">'
var style = "<style>" + text + "</style>"
var full_svg = head + style + svg_data + "</svg>"
var blob = new Blob([full_svg], {type: "image/svg+xml"});
saveAs(blob, "graph.svg");
})
};
save_as_svg();
</script>
The above code read your chart.css and then embed the css code to your svg file.
I try this and worked for me.
function downloadSvg() {
var svg = document.getElementById("svg");
var serializer = new XMLSerializer();
var source = serializer.serializeToString(svg);
source = source.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
source = source.replace(/ns\d+:href/g, 'xlink:href'); // Safari NS namespace fix.
if (!source.match(/^<svg[^>]+xmlns="http\:\/\/www\.w3\.org\/2000\/svg"/)) {
source = source.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
}
if (!source.match(/^<svg[^>]+"http\:\/\/www\.w3\.org\/1999\/xlink"/)) {
source = source.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
}
var preface = '<?xml version="1.0" standalone="no"?>\r\n';
var svgBlob = new Blob([preface, source], { type: "image/svg+xml;charset=utf-8" });
var svgUrl = URL.createObjectURL(svgBlob);
var downloadLink = document.createElement("a");
downloadLink.href = svgUrl;
downloadLink.download = name;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
In my scenario, I had to use some svg images created using D3.js in other projects. So I opened dev tools and inspected those svg and copied their content. Then created a new blank svg file and pasted the copied content there. Then I used those new svg files in other areas.
And if you want to do it programmatically, then we can use document.getElementById('svgId')
I know this is a basic approach but in case anyone find it useful.

Convert Svg to Png on Client Side

I am working on a Web based application where user can create designs in Svg. i want to convert the svg design into png image file on client side. i found a solution of using canvas, this works well in firefox, but in chrome it generate security error.
check the code below thanks:-
var mainsvg=document.getElementById('svgforImg');
var canvas=document.getElementById('canvas');
var ctx = canvas.getContext("2d");
var data=mainsvg.innerHTML;
var DOMURL = self.URL || self.webkitURL || self;
var svg = new Blob([data], {
type: "image/svg+xml;charset=utf-8"
});
var url = DOMURL.createObjectURL(svg);
var img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
var imageurl = canvas.toDataURL("image/png");
}
Now my variable imageurl contains 'base64 png' image. this works in Firefox. But in chrome line
var imageurl = canvas.toDataURL("image/png");
generate security error.
Any help would be highly appreciated.
I think this is related to this question. From which server does the SVG originate? If it is a different one than the one your application is coming from (remember: sub-domains matter!), you could add the desired http-headers in the originating server.

HTML5 Canvas Drag out from browser to desktop

I'm trying to create a little image manipulation web app as a project. I'm trying to implement a Drag canvas image out of the browser to the desktop. I have done some digging and found
http://www.thecssninja.com/javascript/gmail-dragout and http://jsfiddle.net/bgrins/xgdSC/ (courtesy of TheCssNinja & Brian Grinstead)
function dragoutImages() {
if (!document.addEventListener) {
return;
}
document.addEventListener("dragstart", function(e) {
var element = e.target;
var src;
if (element.tagName === "IMG" && element.src.indexOf("data:") === 0) {
src = element.src;
}
if (element.tagName === "CANVAS") {
try {
src = element.toDataURL();
}
catch(e) { }
}
if (src) {
var name = element.getAttribute("alt") || "download";
var mime = src.split(";")[0].split("data:")[1];
var ext = mime.split("/")[1] || "png";
var download = mime + ":" + name + "." + ext + ":" + src;
e.dataTransfer.setData("DownloadURL", download);
}
}, false);
}
function drawCanvas(){
var canvas = document.getElementById('mycanvas');
var ctx = canvas.getContext('2d');
var lingrad = ctx.createLinearGradient(0,0,0,150);
lingrad.addColorStop(0, '#000');
lingrad.addColorStop(0.5, '#669');
lingrad.addColorStop(1, '#fff');
ctx.fillStyle = lingrad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
var img = new Image();
img.src = canvas.toDataURL("image/png");
img.alt = 'downloaded-from-image';
$(img).appendTo("body");
}
dragoutImages();
drawCanvas();
This works for files which are elements of the HTML but I am unable to grab the canvas image and download it using the theory. Has anyone implemented such a feature?
I have used the canvas.toDataURL to get the image data, if I do an alert I see the encoded image data my canvas drag begins but when outside the browser the icon changes back to the stop symbol.
Looking for approaches and ideas on how to implement this.
This is what I've managed to implement and works pretty well,
function download(e){
downloadImageData = eCanv.getImageData(750 - (scaledWidth / 2), 250 - (scaledHeight / 2), scaledWidth, scaledHeight);
dlcanvas = document.createElement('canvas');
dlcanvas.setAttribute('width',scaledWidth);
dlcanvas.setAttribute('height',scaledHeight);
dlcontext = dlcanvas.getContext("2d");
dlcontext.putImageData(downloadImageData, 0,0);
url = dlcanvas.toDataURL('image/jpg');
//name = document.getElementById("filename").value;
var mime = url.split(";")[0].split("data:")[1];
var name = mime.split("/")[0];
var ext = mime.split("/")[1] || "jpg";
var download = mime + ":" + name + "." + ext + ":" + url;
e.dataTransfer.setData("DownloadURL", download);
}
Adapted code from cssninja and Brian Grinstead.
No.
For security reasons, Javascript cannot write to the local file system.
Javascript can read from the local file system with the filereader: http://www.html5rocks.com/en/tutorials/file/dndfiles/
It can even write to a sandboxed browser file (localstorage): http://www.w3schools.com/html/html5_webstorage.asp
You could even bounce it off your server and then ask the user if they want to download the image off the server.
For local web based applications you can use or write a local webserver or service and or utilzize for example php to add the functionality to interact with the local filesystem from javascript. Seems this is forgotten that it is not forbidden to install a webserver on the same machine like the browser :)

Display Image using canvas in JavaScript/jQuery

I have the following code :
function createImage(source) {
var pastedImage = new Image();
pastedImage.onload = function() {
document.write('<br><br><br>Image: <img src="'+pastedImage.src+'" height="700" width="700"/>');
}
pastedImage.src = source;
}
Here I am displaying the image through html image tag which I wrote in document.write and provide appropriate height and width to image.
My question is can it possible to displaying image into the canvas instead of html img tag? So that I can drag and crop that image as I want?
But how can I display it in canvas?
Further I want to implement save that image using PHP but for now let me know about previous issue.
Try This
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image(); // Create new img element
img.onload = function(){
// execute drawImage statements here This is essential as it waits till image is loaded before drawing it.
ctx.drawImage(img , 0, 0);
};
img.src = 'myImage.png'; // Set source path
Make sure the image is hosted in same domain as your site. Read this for Javascript Security Restrictions Same Origin Policy.
E.g. If your site is http://example.com/
then the Image should be hosted on http://example.com/../myImage.png
if you try http://facebook.com/..image/ or something then it will throw security error.
Use
CanvasRenderingContext2D.drawImage.
function createImage(source) {
var ctx = document.getElementById('canvas').getContext('2d');
var pastedImage = new Image();
pastedImage.onload = function(){
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage = source;
}
Also MDN seems to be have nice examples.

Categories