Home > front end >  Full size download Chartjs canvas on mobile device
Full size download Chartjs canvas on mobile device

Time:01-06

This is my Chartjs canvas builds inside the bootstrap and chartjs framework. The problem is I cannot download the full width image while in small screens such as mobile devices.

---- Bootstrap is a must have

--- NOTE: if you make the width of screen in the example small and then click on download the output would be that size and small.

HTML:

<div >

  <div >
    <h4 > Average </h4>

    <a data-name="avg-chart" id="downloadavg" download="searchtrends-average-position-chart.jpg" href="" >
      <button  type="button">
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white"  viewBox="0 0 16 16">
          <path d="M8 2a5.53 5.53 0 0 0-3.594 1.342c-.766.66-1.321 1.52-1.464 2.383C1.266 6.095 0 7.555 0 9.318 0 11.366 1.708 13 3.781 13h8.906C14.502 13 16 11.57 16 9.773c0-1.636-1.242-2.969-2.834-3.194C12.923 3.999 10.69 2 8 2zm2.354 6.854-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 1 1 .708-.708L7.5 9.293V5.5a.5.5 0 0 1 1 0v3.793l1.146-1.147a.5.5 0 0 1 .708.708z" />
        </svg>
      </button>
    </a>
    <div  id="avg-chart_parent">
      <canvas  id="avg-chart" style="height:300px;width:100%" height="300"></canvas>
    </div>
  </div>
</div>

JS:

new Chart(document.getElementById("avg-chart"),{"type":"line",
                      "data":{"labels":["2020.11.1","2020.11.2","2020.11.3","2020.11.4","2020.11.5","2020.11.6","2020.11.7","2020.11.7","2020.11.9","2020.11.10","2020.11.11","2020.11.12","2020.11.13","2020.11.14","2020.11.15","2020.11.16","2020.11.17","2020.11.18","2020.11.19","2020.11.20","2020.11.21","2020.11.22","2020.11.23","2020.11.24","2020.11.25","2020.11.26","2020.11.27","2020.11.28","2020.11.29","2020.11.30",],
                      "datasets":[{"label":"Average Position ",
                      "data":["11","12","13","14","15","16","17","18","19","19","19","19","19","19","19","19","19","19","19","20","21","22","23","24","25","26","27","28","29","30",],
                      "fill":false,"borderColor":"rgb(37,154,71)","lineTension":0.1}]}, options: {
        scales: {
            yAxes: [{
                ticks: {
                        reverse: true,
                }
            }],
            xAxes: [{
                type: 'time',
                distribution: 'series',
                time: {
          tooltipFormat:'MM/DD/YYYY', 
              }
        
                    }]
        },
        legend: {
            display: false,
            maxWidth: 9999
             
        }
    }});
    
    
        function downloadpng(chartname,chartid){
      var canvas = document.getElementById(chartname);
   var url_base64jp =canvas.toDataURL("image/jpg");
  var a =  document.getElementById(chartid);
  a.href = url_base64jp;
  }
//Download Chart Image
$('.download').on( 'click', function (event) {
  var chartname =  $(this).attr('data-name');
  var chartid =  $(this).attr('id'); 
    downloadpng(chartname,chartid);
 
}); 

I made an example here:

http://jsfiddle.net/aneeshtan/vu27aew3/49/

As you can see I cannot save the full sized canvas (Chartjs) in small screens and automatically it changes the ratio.

How can I have the full-sized chartjs canvas to download.

CodePudding user response:

Custom dimensions can be applied by creating a new canvas element along with a new canvas context

function downloadpng(chartname, chartid) {
  var canvas = document.getElementById(chartname);
  var url_base64jp = canvas.toDataURL("image/jpg");
  var a = document.getElementById(chartid);
  
  var resizedCanvas = document.createElement("canvas");
  var resizedContext = resizedCanvas.getContext("2d");

  resizedCanvas.height = "1080";
  resizedCanvas.width = "1920";
  
  resizedContext.drawImage(canvas, 0, 0, 1920, 1080);
  
  url_base64jp = resizedCanvas.toDataURL("image/jpg");


  a.href = url_base64jp;
}

Updated Fiddle Link

CodePudding user response:

In order to get a higher resolution snapshot of the chart, you first need to resize it and then wait for it to redraw.

The simplest way to do that is to resize the parent and wait ~ 300ms.
Note: if your chart is more complex (has significantly more data to draw), the resize & redraw might take longer, feel free to increase the timeout interval accordingly - it's 321ms now.

Because you need to wait for the chart to resize, you can't use the initial click anymore. You need to trigger another one, after the chart has resized.

Lastly, I'm deleting the href value after the download. If I don't, any subsequent click on the button will return the first snapshot and, in case the chart is dynamic and you want to be able to snapshot it again without having to refresh the page.

Here's how the code looks like:

function downloadImage(name, id) {
  setTimeout(() => {
    const a = $(id)[0];
    a.href = $(name)[0].toDataURL("image/jpg");
    a.click();
  }, 321)
}
$('.download').on('click', function(e) {
  const name = '#'   $(this).data('name');
  const id = '#'   this.id;
  const parent = $(name).parent();
  if (!$(this).attr('href')) {
    parent.css({ width: Math.max(1200, parent.width()) });
    downloadImage(name, id);
    e.preventDefault();
  } else {
    parent.css({ width: '' });
    setTimeout(() => $(id).attr('href', ''));
  }
});

Feel free to change 1200 to whatever min-width you want for your chart. Currently, if the displayed chart width is larger than that value, you'll download a bigger image, as you said in comments. I personally find that a bit weird.

If you change your mind, and want the downloaded chart to always have the same size (even when downloaded from larger monitors), replace

parent.css({ width: Math.max(1200, parent.width()) });

with

parent.css({ width: 1920 }); // or whatever fixed chart width you want

See it working: http://jsfiddle.net/websiter/Lzdc3bw1/

  •  Tags:  
  • Related