'Resizing chart before downloading as image

I access the chart canvas to offer users to download image versions of generated charts, like this:

canvas.toBlob(function(blob) {
  let img = URL.createObjectURL(blob);
  let a = document.createElement('a');
  a.href = img;
  a.download = 'chart.png';
  a.click();
});

This approach works but since the chart dimensions are responsive to the users device (which is a good thing), the dimensions of the downloaded chart are also dependent on the user window size, resolution etc. This is not ideal in most cases because the user is likely to want to share the image on social media etc, where standard dimensions are preferable (like a 16/9 ratio).

What is the best approach to this problem? I looked at resizing the chart before generating the image (and then restoring the original dimensions afterwards), but this is a bit complicated - hopefully there is a better solution?



Solution 1:[1]

Here's how I solved the problem. I'm sure there's a better solution, but it does the job:

var button; // link to download chart
var canvas; // the chart canvas to download

button.addEventListener('click', _ => {
        let resized = adjustCanvasWidth(canvas);
        setTimeout(_ => {
            canvas.toBlob(blob => {
                    const img = URL.createObjectURL(blob);
                    const downloadLink = document.createElement('a');
                    downloadLink.href = img;
                    downloadLink.download = CHARTFILENAME + '.png';
                    downloadLink.click();

                    if(resized) {
                        canvas.parentElement.style.width = 'auto';
                        resizeChart(canvas);
                    }
            });
        }, 1000);
});

function adjustCanvasWidth(canvas) {
    let maxWidth = Math.round(canvas.clientHeight * 16 / 9);
    if(canvas.parentElement.clientWidth > maxWidth) {
        canvas.parentElement.style.width = maxWidth + 'px';
        return resizeChart(canvas);
    }
}

function resizeChart(canvas) {
    let charts = Object.values(Chart.instances).filter(chart => {
        return chart.canvas == canvas;
    });
    if(charts.length == 1) {
        let chart = charts[0];
        chart.resize();
        return true;
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 LowCarbonPower