I am trying to convert my nvd3.js
charts into canvas
drawings in my web app. There is a good stackoverflow
thread about it: How to convert/save d3.js graph to pdf/jpeg
I decided to use Simg
library and it is working good except that it generates me black and white images, the colors are lost. The code for the Simg
library is small and can be found here: https://raw.githubusercontent.com/krunkosaurus/simg/v1.1.0/src/simg.js
As I understand the main function that is actually doing the convertion is the following one:
toCanvas: function(cb){
this.toSvgImage(function(img){
var canvas = document.createElement('canvas');
var context = canvas.getContext("2d");
canvas.width = img.width;
canvas.height = img.height;
context.drawImage(img, 0, 0);
cb(canvas);
});
},
So, what should I modify there to avoid losing colors of my charts? They are drawn using nvd3
and look like that:
The output of Simg
library is the following image:
As you can see, the color and axes are lost. Any suggestions would be greatly appreciated.
Update
I tried using canvg()
but the output that I got is the following:
I just ran two lines of code:
let svg = d3.select("div#main svg").html();
canvg('canvas', svg);
I like that the axes are not lost but obviously it is unacceptable.
Update
I tried using the code from the duplicate
suggested link but it is not working for me. Here is the code that I am using:
let svg = d3.select("div#main svg").node();
console.log(svg);
var sheets = document.styleSheets;
var styleStr = '';
Array.prototype.forEach.call(sheets, function(sheet){
try{ // we need a try-catch block for external stylesheets that could be there...
styleStr += Array.prototype.reduce.call(sheet.cssRules, function(a, b){
return a + b.cssText; // just concatenate all our cssRules' text
}, "");
}
catch(e){console.log(e);}
});
// create our svg nodes that will hold all these rules
var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
style.innerHTML = styleStr;
defs.appendChild(style);
// now append it in your svg node
svg.insertBefore(defs, svg.firstElementChild);
let xml = xmlserializer.serializeToString(svg);
// Removing the name space as IE throws an error
//xml = xml.replace(/xmlns=\"http:\/\/www\.w3\.org\/2000\/svg\"/, '');
canvg('canvas', xml);
It throws an error:
Uncaught DOMException: Failed to execute 'matches' on 'Element': '38%' is not a valid selector. at matchesSelector (http://canvg.github.io/canvg/canvg.js:72:16) at svg.Element.g.addStylesFromStyleDefinition (http://canvg.github.io/canvg/canvg.js:838:32) at svg.Element.g.svg.Element.ElementBase (http://canvg.github.io/canvg/canvg.js:864:10) at svg.Element.g.svg.Element.RenderedElementBase (http://canvg.github.io/canvg/canvg.js:902:9) at new svg.Element.g (http://canvg.github.io/canvg/canvg.js:2430:9) at Object.svg.CreateElement (http://canvg.github.io/canvg/canvg.js:2832:9) at svg.Element.svg.addChild (http://canvg.github.io/canvg/canvg.js:830:29) at svg.Element.svg.svg.Element.ElementBase (http://canvg.github.io/canvg/canvg.js:889:40) at svg.Element.svg.svg.Element.RenderedElementBase (http://canvg.github.io/canvg/canvg.js:902:9) at new svg.Element.svg (http://canvg.github.io/canvg/canvg.js:1035:9)
If I avoid using xmlserializer
and instead do the following: canvg('canvas', d3.select(svg).html());
, then no errors are thrown, except some 404
s and nothing is drawn on the page, canvas
element just stays empty. The only errors that I see in that case are:
Update
I tried to use Simg.js
to download the modified svg
with the styles, but it is not working, nothing is just happening, no errors (I eliminated the errors in the previous update):
var simg = new Simg(svg);
simg.download();