I have created a D3 hierarchical edge bundling visualization.When i download this visualization as PNG,the links in downloaded image are filled with dark color which is not displayed in actual visualization.
Downloaded image is
Actual visualization being displayed is
How to get the same visualization in downloaded image. My current code is:
<html>
<head>
<style>
.node {
font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.link {
stroke: steelblue;
stroke-opacity: .4;
fill: none;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
var classes=[
{"name":"a","size":3938,"imports":["b","f"]},
{"name":"b","size":3938,"imports":[]},
{"name":"c","size":3938,"imports":["a"]},
{"name":"d","size":3938,"imports":[]},
{"name":"e","size":3938,"imports":[]},
{"name":"f","size":3938,"imports":[]}
];
var diameter = 700,
radius = diameter / 2,
innerRadius = radius - 120;
var cluster = d3.layout.cluster()
.size([360, innerRadius]);
var bundle = d3.layout.bundle();
var line = d3.svg.line.radial()
.interpolate("bundle")
.tension(.85)
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
var svg = d3.select("body").append("svg")
.attr("id","networkSvg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(" + radius + "," + radius + ")");
var nodes = cluster.nodes(packageHierarchy(classes)),
links = packageImports(nodes);
svg.selectAll(".link")
.data(bundle(links))
.enter().append("path")
.attr("class", "link")
.attr("d", line);
svg.selectAll(".node")
.data(nodes.filter(function(n) { return !n.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
.on("mouseover", function(d){
d3.selectAll(".node").style("fill", "black");
d3.selectAll(".link").style("stroke", "steelblue");
colorSource(d.name);
d.imports.forEach(function(name){
colorTarget(name);
colorOutgoingLink(d.name, name);
});
d.parent.children.forEach(function(data){
if(data.imports.indexOf(d.name)>-1)
{
colorTarget(data.name);
colorIncomingLink(data.name, d.name);
}
});
})
.on("mouseout",function(d)
{
d3.selectAll(".node").style("fill", "black");
d3.selectAll(".link").style("stroke", "steelblue");
})
.append("text")
.attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
.attr("dy", ".31em")
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
.text(function(d) { return d.key; });
// Lazily construct the package hierarchy from class names.
function packageHierarchy(classes) {
var map = {};
function find(name, data) {
var node = map[name], i;
if (!node) {
node = map[name] = data || {name: name, children: []};
if (name.length) {
node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
node.parent.children.push(node);
node.key = name.substring(i + 1);
}
}
return node;
}
classes.forEach(function(d) {
find(d.name, d);
});
return map[""];
}
// Return a list of imports for the given array of nodes.
function packageImports(nodes) {
var map = {},
imports = [];
// Compute a map from name to node.
nodes.forEach(function(d) {
map[d.name] = d;
});
// For each import, construct a link from the source to target node.
nodes.forEach(function(d) {
if (d.imports) d.imports.forEach(function(i) {
imports.push({source: map[d.name], target: map[i]});
});
});
return imports;
}
function colorIncomingLink(src,tgt){
var link = d3.selectAll(".link")[0].filter(function(d){
return (d3.select(d).data()[0][0].name == src && d3.select(d).data()[0][2].name == tgt);
});
d3.selectAll(link).style("stroke", "green");
}
function colorOutgoingLink(src,tgt){
var link = d3.selectAll(".link")[0].filter(function(d){
return (d3.select(d).data()[0][0].name == src && d3.select(d).data()[0][2].name == tgt);
});
d3.selectAll(link).style("stroke", "red");
}
function colorTarget(name){
//iterate through all teh dom and get the DOM which has the data
var node = d3.selectAll(".node")[0].filter(function(d){
return d3.select(d).data()[0].name == name;
});
d3.selectAll(node).style("fill", "red");
}
function colorSource(name){
//iterate through all teh dom and get teh DOM which has the data
var node = d3.selectAll(".node")[0].filter(function(d){
return d3.select(d).data()[0].name == name;
});
d3.selectAll(node).style("fill", "green");
}
function download()
{
img = new Image(),
serializer = new XMLSerializer(),
svgStr = serializer.serializeToString(document.getElementById('networkSvg'));
img.src = 'data:image/svg+xml;base64,'+window.btoa(svgStr);
// You could also use the actual string without base64 encoding it:
//img.src = "data:image/svg+xml;utf8," + svgStr;
var canvas = document.createElement("canvas");
var w=2000;
var h=2000;
canvas.width = w;
canvas.height = h;
canvas.getContext("2d").drawImage(img,0,0,w,h);
var imgURL = canvas.toDataURL("image/png");
var dlLink = document.createElement('a');
dlLink.download = "down";
dlLink.href = imgURL;
dlLink.dataset.downloadurl = ["image/png", dlLink.download, dlLink.href].join(':');
document.body.appendChild(dlLink);
dlLink.click();
document.body.removeChild(dlLink);
}
</script>
<button onclick="download()">Download</button>
</body>
</html>