0

I am using canvg lib to convert svg to png but some how when my svg size is more than 10000 it fails to draw it on canvas and data-URL get only "data:;" empty

here is my code that I am using

function getDiagramImage(isTrue,_callback){
var html = d3.select("svg")
    //.attr("version", 1.1)
    //.attr("xmlns", "http://www.w3.org/2000/svg")
    .attr({
        'xmlns': 'http://www.w3.org/2000/svg',
        'xmlns:xmlns:xlink': 'http://www.w3.org/1999/xlink',
        version: '1.1'
    }) 
    .node().parentNode.innerHTML;


   d3.select('#hiddenCanvas').attr('width',_canvasWidth).attr('height',(parseFloat(_canvasHeight) + 300) );
   var canvas = document.getElementById('hiddenCanvas');
   var context = canvas.getContext("2d");

   canvg(document.getElementById('hiddenCanvas'), html, {
     renderCallback: function() {
         var dataURL = canvas.toDataURL();
         if(!isTrue){
           var pngimg = '<img src="'+dataURL+'">'; 
           d3.select("#pngdataurl").html(pngimg);

           var a = document.createElement("a");
           a.download = "export_"+Date.now()+".png";
           a.href = dataURL; 
           document.body.appendChild(a);
           a.click();  
         }
         if(_callback){
             _callback(dataURL);
         }
        }
    });
}

About This function .. there d3.js code which create diagram. and one save and download button is there save will get data URL to png and save it on server while download will download image instantly.. same function work for both with arguments .

Issue comes with "renderCallback " while svg is large that data URL comes empty I tried with timeout also but it's not get me result and timer keep running

Amit Rana
  • 1,117
  • 1
  • 10
  • 32
  • 1
    maybe related : http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element – Kaiido Mar 16 '15 at 16:22
  • Ok it describe problem but any solution ? – Amit Rana Mar 17 '15 at 09:09
  • well if it is the problem, solution would be to parse your svg into multiple stacked canvas, as proposed in comments of accepted answer. Don't know if canvg has any support for this – Kaiido Mar 17 '15 at 09:13
  • I put check like if height go over 10000 i set it to scaleHeight 10000 but canvg set canvas height 34000 not the 10000 – Amit Rana Mar 17 '15 at 14:03

2 Answers2

2

I made my tests, finally, and actually, it seems to work well until approximately a size of 23500 x 23500 px in Firefox.

But only if you change the

d3.select("svg")
.attr(foo:bar)
.node().parentNode.innerHTML

with

d3.select("svg")
.attr(foo:bar)
.node().outerHTML();

Also, canvg seems to set itself the size of the rendering canvas, so your

d3.select('#hiddenCanvas').attr('width',_canvasWidth).attr('height',(parseFloat(_canvasHeight) + 300) );

is useless, probably as is the part where you set _canvasWidth and _canvasHeight.

__Be carefull with this snippet, there will be lags__

function getDiagramImage(isTrue,_callback){
var html = d3.select("svg")
    .attr({
        'xmlns': 'http://www.w3.org/2000/svg',
        'xmlns:xmlns:xlink': 'http://www.w3.org/1999/xlink',
        version: '1.1'
    }) 
    .node().outerHTML;
   var canvas = document.getElementById('hiddenCanvas');
   var context = canvas.getContext("2d");

   canvg(canvas, html, {renderCallback: function(){
   var dataURL = canvas.toDataURL();
         if(!isTrue){
           var pngimg = '<img src="'+dataURL+'">'; 
           d3.select("#pngdataurl").html(pngimg);

           var a = document.createElement("a");
           a.download = "export_"+Date.now()+".png";
           a.href = dataURL; 
           document.body.appendChild(a);
          // a.click();  
         }
         if(_callback){
             _callback(dataURL);
         }
   }});
   }
getDiagramImage();
svg{border:3px solid green;}
canvas{border:3px solid blue;}
img{border:3px solid red;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/exporting/canvg.js"></script>
<svg id="svg" xmlns="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink" width="15000" height="15000" viewBox="-0.5,0,500.5,500.5"> 
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,118 382,500.5 441,500.5 -0.5,59  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,295 205,500.5 264,500.5 -0.5,236  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,59 441,500.5 500,500.5 499.8,500.2 -0.5,0  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,354 146,500.5 205,500.5 -0.5,295  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,500.5 28,500.5 -0.5,472  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,472 28,500.5 87,500.5 -0.5,413  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,413 87,500.5 146,500.5 -0.5,354  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="-0.5,236 264,500.5 323,500.5 -0.5,177  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="499.5,0.5 448,0.5 499.5,52  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="499.5,52 448,0.5 392,0.5 499.5,108  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="0,0.5 499.5,500 499.5,444 56,0.5  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="392,0.5 336,0.5 499.5,164 499.5,108  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="280,0.5 499.5,220 499.5,164 336,0.5  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="56,0.5 499.5,444 499.5,388 112,0.5  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="112,0.5 499.5,388 499.5,332 168,0.5  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="168,0.5 499.5,332 499.5,276 224,0.5  "/>
  <polygon fill="none" stroke="#000000" stroke-miterlimit="10" points="224,0.5 499.5,276 499.5,220 280,0.5  "/>
 </svg>
<canvas id="hiddenCanvas"></canvas>
<div id="pngdataurl"></div>


<!--**__Be carefull with this snippet, there will be lags__**-->
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • yes you right canvg set size of canvas by it self after given svg – Amit Rana Mar 19 '15 at 09:43
  • but for now i did this var _imageHeight = parseFloat(_canvasHeight); var _imageWidth = parseFloat(_canvasWidth); if(_imageHeight > 10000){ _imageHeight = 9700; } if(_imageWidth > 7000){ _imageWidth = 7000; } and for canvg canvg('hiddenCanvas', html, { ignoreMouse:true, ignoreAnimation:true, ignoreDimensions:true, scaleWidth:_imageWidth, scaleHeight:_imageHeight, renderCallback: function() { – Amit Rana Mar 19 '15 at 09:44
0

here is what i try to fix this for temp

function getDiagramImage(isTrue,_callback){

var html = d3.select("#nodePane svg#nodeEditor")
    .attr({
        'xmlns': 'http://www.w3.org/2000/svg',
        'xmlns:xmlns:xlink': 'http://www.w3.org/1999/xlink',
        version: '1.1'
    }) 
    .node().parentNode.innerHTML;

var _imageHeight = parseFloat(_canvasHeight);
var _imageWidth = parseFloat(_canvasWidth);

if(_imageHeight > 10000){
     _imageHeight = 9700;
}

if(_imageWidth > 7000){
    _imageWidth = 7000;
}

d3.select('#hiddenCanvas').attr('width',_imageWidth+"px").attr('height',( _imageHeight + 300+"px" ) );
 var canvas = document.getElementById('hiddenCanvas');
 var context = canvas.getContext("2d");

 canvg('hiddenCanvas', html, {
      ignoreMouse:true,
      ignoreAnimation:true,
      ignoreDimensions:true,
      scaleWidth:_imageWidth,
      scaleHeight:_imageHeight,
      renderCallback: function() {
        var dataURL = canvas.toDataURL();
        if(!isTrue){
          var pngimg = '<img src="'+dataURL+'">'; 
          d3.select("#pngdataurl").html(pngimg);

          var a = document.createElement("a");
          a.download = "export_"+Date.now()+".png";
          a.href = dataURL; 
          document.body.appendChild(a);
          a.click();  
        }
        if(_callback){
            _callback(dataURL);
        }
    }
  });
}
Amit Rana
  • 1,117
  • 1
  • 10
  • 32