2

I used the D3 chart for display the tree chart so it's works fine now but i need to download this svg chat as image.

Chart html like:

<svg width="960" height="30000">
    <g transform="translate(120,20)">
        <path>......</path>
        <path>......</path>
        <path>......</path>
         ......
         ...... 
    </g>
</svg>

My svg html is much longer so i put the code structure only.

I used this code for download :

d3.select('#saveButton').on('click', function(){
        // alert('test');
        var svgString = getSVGString(svg.node());
        // console.log(svgString);
        svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback

        function save( dataBlob, filesize ){
            saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js function
        }
    });

So would you please let me know how i can download the svg chart as image.

Dhaval
  • 89
  • 2
  • 11
  • Possible duplicate of [Convert SVG to image (JPEG, PNG, etc.) in the browser](https://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser) – Gerardo BLANCO Jun 09 '18 at 16:11
  • No please check i used d3 chart and i need to download this svg file as PNG image – Dhaval Jun 09 '18 at 16:14

1 Answers1

1

The next link has a great way of solving your problem. Solution

It contains two main function.

  1. SVG String
  2. String to Image

I think you are using the same code i just added, as you count with the save download function. The thing here is what else you have on your code. As you can see, this code actually downloads the png end result. Lets work from here and find you a solution.

// Let's create a mock visualization
var width = 300, height = 300;
var circleSizeMax = 15;
var rMax = Math.min(width,height)/2 - circleSizeMax;

var radius  = d3.scale.linear().range([0,rMax]);
var angle  = d3.scale.linear().range([0,2*Math.PI]);
var size  = d3.scale.linear().range([0,circleSizeMax]);
var color  = d3.scale.ordinal().range(['#fcfb3c','#fcf900','#ff825a','#ffd2cb','#71d362','#ffd16f','#ff3d5d','#ff7218','#04b3f3','#bce5ac','#6e0215','#69D2E7','#A7DBDB','#E0E4CC','#F38630','#E94C6F','#542733','#5A6A62','#C6D5CD','#DB3340','#E8B71A','#F7EAC8','#1FDA9A','#588C73','#F2E394','#F2AE72','#D96459','#D0C91F','#85C4B9','#008BBA','#DF514C','#00C8F8','#59C4C5','#FFC33C','#FBE2B4','#5E412F','#FCEBB6','#78C0A8','#F07818','#DE4D4E','#DA4624','#DE593A','#FFD041','#B1EB00','#53BBF4','#FF85CB','#FF432E','#354458','#3A9AD9','#29ABA4','#E9E0D6','#4298B5','#ADC4CC','#92B06A','#E19D29','#BCCF02','#5BB12F','#73C5E1','#9B539C','#FFA200','#00A03E','#24A8AC','#0087CB','#260126','#59323C','#F2EEB3','#BFAF80','#BFF073','#0DC9F7','#7F7F7F','#F05B47','#3B3A35','#20457C','#5E3448','#FB6648','#E45F56','#A3D39C','#7ACCC8','#4AAAA5','#DC2742','#AFA577','#ABA918','#8BAD39','#F2671F','#C91B26','#9C0F5F','#60047A','#0F5959','#17A697','#638CA6','#8FD4D9','#83AA30','#1499D3','#4D6684','#3D3D3D','#333333','#424242','#00CCD6','#EFEFEF','#CCC51C','#FFE600','#F05A28','#B9006E','#F17D80','#737495','#68A8AD','#C4D4AF']);
var x = function(d) { return radius( d.r ) * Math.cos( angle( d.angle ) ); };
var y = function(d) { return radius( d.r ) * Math.sin( angle( d.angle ) ); };

var svg = d3.select('body').append('svg')
 .attr('width', width)
 .attr('height',height);

var chart = svg.append('g').attr('transform','translate('+[width/2,height/2]+')');

var data = d3.range(150).map( function(d) { return {r: Math.random(), angle: Math.random(), size: Math.random() }; });

chart.selectAll('cirle')
 .data(data).enter()
 .append('circle')
 .attr('class','blendCircle')
 .attr({
  cx: x,
  cy: y,
  r: function(d) { return size(d.size); },
  fill: function(d,i) { return color(i); }
 });


// Set-up the export button
d3.select('#saveButton').on('click', function(){
 var svgString = getSVGString(svg.node());
 svgString2Image( svgString, 2*width, 2*height, 'png', save ); // passes Blob and filesize String to the callback

 function save( dataBlob, filesize ){
  saveAs( dataBlob, 'D3 vis exported to PNG.png' ); // FileSaver.js function
 }
});

// Below are the functions that handle actual exporting:
// getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
function getSVGString( svgNode ) {
 svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
 var cssStyleText = getCSSStyles( svgNode );
 appendCSS( cssStyleText, svgNode );

 var serializer = new XMLSerializer();
 var svgString = serializer.serializeToString(svgNode);
 svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
 svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix

 return svgString;

 function getCSSStyles( parentElement ) {
  var selectorTextArr = [];

  // Add Parent element Id and Classes to the list
  selectorTextArr.push( '#'+parentElement.id );
  for (var c = 0; c < parentElement.classList.length; c++)
    if ( !contains('.'+parentElement.classList[c], selectorTextArr) )
     selectorTextArr.push( '.'+parentElement.classList[c] );

  // Add Children element Ids and Classes to the list
  var nodes = parentElement.getElementsByTagName("*");
  for (var i = 0; i < nodes.length; i++) {
   var id = nodes[i].id;
   if ( !contains('#'+id, selectorTextArr) )
    selectorTextArr.push( '#'+id );

   var classes = nodes[i].classList;
   for (var c = 0; c < classes.length; c++)
    if ( !contains('.'+classes[c], selectorTextArr) )
     selectorTextArr.push( '.'+classes[c] );
  }

  // Extract CSS Rules
  var extractedCSSText = "";
  for (var i = 0; i < document.styleSheets.length; i++) {
   var s = document.styleSheets[i];
   
   try {
       if(!s.cssRules) continue;
   } catch( e ) {
        if(e.name !== 'SecurityError') throw e; // for Firefox
        continue;
       }

   var cssRules = s.cssRules;
   for (var r = 0; r < cssRules.length; r++) {
    if ( contains( cssRules[r].selectorText, selectorTextArr ) )
     extractedCSSText += cssRules[r].cssText;
   }
  }
  

  return extractedCSSText;

  function contains(str,arr) {
   return arr.indexOf( str ) === -1 ? false : true;
  }

 }

 function appendCSS( cssText, element ) {
  var styleElement = document.createElement("style");
  styleElement.setAttribute("type","text/css"); 
  styleElement.innerHTML = cssText;
  var refNode = element.hasChildNodes() ? element.children[0] : null;
  element.insertBefore( styleElement, refNode );
 }
}


function svgString2Image( svgString, width, height, format, callback ) {
 var format = format ? format : 'png';

 var imgsrc = 'data:image/svg+xml;base64,'+ btoa( unescape( encodeURIComponent( svgString ) ) ); // Convert SVG string to data URL

 var canvas = document.createElement("canvas");
 var context = canvas.getContext("2d");

 canvas.width = width;
 canvas.height = height;

 var image = new Image();
 image.onload = function() {
  context.clearRect ( 0, 0, width, height );
  context.drawImage(image, 0, 0, width, height);

  canvas.toBlob( function(blob) {
   var filesize = Math.round( blob.length/1024 ) + ' KB';
   if ( callback ) callback( blob, filesize );
  });

  
 };

 image.src = imgsrc;
}
<!DOCTYPE html>
<html lang="en">

<head>
 <title>How to properly export SVG D3 visualization to PNG or JPEG</title>
  <meta charset="utf-8">
  <script src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
  <script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
 <script src="https://d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
   .blendCircle {
    mix-blend-mode: multiply;
   }
  </style>
 </head>

<body>
<div>
<button id='saveButton'>Export my D3 visualization to PNG</button>
</div>
</body>

</html>
Gerardo BLANCO
  • 5,590
  • 1
  • 16
  • 35
  • Thanks for reply. I used same code as you mentioned but still no luck. I checked my console but in console no any error but download file not working. Please help me if you have any idea about this. – Dhaval Jun 09 '18 at 16:33
  • I will be happy to help. Pliss provide your code or a live view. – Gerardo BLANCO Jun 09 '18 at 16:52
  • Sorry man. Code is too long and i am working on local server. If you want html then i will add in my question. But if you have any demo link for that please pass me. – Dhaval Jun 09 '18 at 16:59
  • You can upload to a fiddle. I can debbug your code with out it/ – Gerardo BLANCO Jun 09 '18 at 17:03
  • This is my fiddle link please check : https://jsfiddle.net/insystemgrp/m79xqw6d/ I put the svg code directly in html which is display in inspect element. – Dhaval Jun 09 '18 at 17:27
  • ``svg`` ``height`` adn ``width`` are not declare. The code you are copyed declares this variables to create the svg they use. You need to declare them if you are inserting the svg directly – Gerardo BLANCO Jun 09 '18 at 19:08
  • Please check now i added the height and width and now no any error in console but still not download – Dhaval Jun 10 '18 at 04:06
  • What have you tryed to debbug it? – Gerardo BLANCO Jun 10 '18 at 16:24
  • On my end the blob returns null. The error would be that – Gerardo BLANCO Jun 10 '18 at 16:24
  • Hello Gerardo, Please check the screen shot: http://prntscr.com/jtb8zk Now only issue with download option nothing else. – Dhaval Jun 10 '18 at 16:40
  • Please check this fiddle i hope this one understand : https://jsfiddle.net/insystemgrp/43db2cvn/ – Dhaval Jun 10 '18 at 17:09
  • https://jsfiddle.net/43db2cvn/3/ I had to change some things in the JS for it to work – Gerardo BLANCO Jun 10 '18 at 21:06
  • Thanks now downloading working fine but the only tree visible in image not text like: Top Level & Level 2: A. Is it possible with text? – Dhaval Jun 11 '18 at 04:42
  • Im sure its possible, but I actually dont know why it isnt downloading. – Gerardo BLANCO Jun 11 '18 at 12:24