[Chartjs]-Using chartjs, how to define relative width and height of canvas?

1👍

It seems that the standard way for a chart.js plot to fill a certain area with a size set in css, is to do these:

  • include the canvas in a div that doesn’t contain anything else

  • set the size in the style of the div, not the canvas (that is already done in your code)

  • have at least one size in absolute units, (that is not both in %) – in your case

      <div style="height:100vh; width:80vw">
          <canvas id="myChart"></canvas>
      </div>
    

    See also this comment from the docs.

  • set chart options maintainAspectRatio: false and responsive: true – the latter for the chart to be redrawn when you resize the window.

Here’s a code snippet doing these, including a plugin I wrote that displays the current sizes of the canvas, div and window

const plugin = {
    id: 'canvasSizeMonitor',
    currentWidth: 0,
    currentHeight: 0,
    resizing: false,
    
    displaySizes(chart){
        const canvas = chart.canvas,
            div = canvas.parentElement;
        document.querySelector('#sizes').innerText+=
            `div: ${div.offsetWidth}x${div.offsetHeight}\n`+
            `canvas: ${canvas.offsetWidth}x${canvas.offsetHeight}\n`+
            `window:${window.innerWidth}x${window.innerHeight}\n`+
            `0.8 * ${window.innerWidth} = ${Math.round(0.8*window.innerWidth)}\n`+
            '---------\n'//`aspRatio: ${chart.options.aspectRatio.toFixed(3).replace(/[.]?0*$/, '')}\n\n`;
    },
    
    afterRender(chart){
        if(!plugin.resizing &&
            (chart.canvas.offsetWidth !== plugin.currentWidth ||
                chart.canvas.offsetHeight !== plugin.currentHeight)){
            plugin.resizing = true;
            setTimeout(
                function(){
                    plugin.resizing = false;
                    plugin.currentWidth = chart.canvas.offsetWidth;
                    plugin.currentHeight = chart.canvas.offsetHeight;
                    plugin.displaySizes(chart);
                }, 500
            )
        }
    }
};


chart = new Chart(document.getElementById("myChart"), {
    type: 'line',
    data: {
        datasets: Array.from({length: 8}, (_, i)=>({
            label: `k = ${i+1}`,
            data: Array.from({length: 100}, (_, j)=>({
                x: j/50, y: Math.exp(-j/10)*Math.cos((i+1)*j*Math.PI/100)
            }))
        }))
    },
    options: {
        parsing: {
            xAxisKey: 'x',
            yAxisKey: 'y'
        },
        pointStyle: false,
        borderWidth: 1,
        
        responsive: true,
        maintainAspectRatio: false,
        //aspectRatio: 1,
        scales: {
            x: {
                type: 'linear',
                grid: {
                    drawOnChartArea: true,
                    lineWidth: 1
                },
                border:{
                    color: '#000',
                },
                ticks: {
                    display: true,
                    color: '#000',
                    padding: 10
                },
                title: {
                    display: true,
                    text: 'x',
                    align: 'end'
                }
            },
            y: {
                type: 'linear',
                ticks: {
                    padding: 10,
                    color: '#000',
                },
                grid: {
                    drawOnChartArea: true,
                    lineWidth: 1
                },
                border:{
                    color: '#000',
                },
                title: {
                    display: true,
                    text: 'f[k](x)',
                    align: 'end'
                }
            }
        },
        plugins:{
            legend:{
                position: 'right'
            }
        },
        animation: {duration: 0}
    },
    plugins: [plugin]
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.1.2/chart.umd.js"
        integrity="sha512-t41WshQCxr9T3SWH3DBZoDnAT9gfVLtQS+NKO60fdAwScoB37rXtdxT/oKe986G0BFnP4mtGzXxuYpHrMoMJLA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<body style="margin: 0">

<pre id="sizes" style="position: absolute; top: 0; right: 10px; text-align: right;background-color:rgba(255, 200, 100,0.4)"></pre>

<div style="height:100vh; width:80vw; padding:0; margin: 0; background: red">
<canvas style="background: #ddd" id="myChart"></canvas>
</div>

</body>

Leave a comment