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;
}
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/