Phill Alexakis
Phill Alexakis

Reputation: 1499

I can not properly re scale <canvas> with width and height attributes

I'm using Charts.js library and my <canvas> element is acting strangely when i try to re scale it by changing it's width and height attributes

I'm definitely missing something , keep in mind that i capture the whole window

here are some examples:

enter image description here

enter image description here

enter image description here

enter image description here

Try it here , this is supposed to be a 10x10 square (pretty small right?)

var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
            label: '# of Votes',
            data: [12, 19, 3, 5, 2, 3],
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        }
    }
});
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script> 
<canvas id="myChart" width="10" height="10"></canvas>

Why can't i make it a 100x100 square? and not be placed in the whole browser?do i need a placeholder for this?

Here is the playground that makes a graph non-resizable as you might notice in the desktop view although the mobile view is perfect

enter image description here

enter image description here

Note:

When <div> is not included and <canvas> has not attributes in browser it's huge , and on mobile resolution is perfect. If you apply width and height to <div> which contains <canvas> you can resize it but on mobile will be stretched.

Edit: added code snippet

Edit2: added code playground

Upvotes: 1

Views: 334

Answers (2)

yqlim
yqlim

Reputation: 7080

If you look at it through your console, you will notice that an extra element div.chartjs-size-monitor is added to the DOM right before your target canvas.

This is done by ChartJS to ensure the canvas can be resized properly.

To solve the it, you simply need to

  1. Move the canvas into a container element
  2. Set your size at the container element.

Note that the parent element must be display: block (i.e., div).

ChartJS will change the width and height attribute of your canvas anyway, so there is no point setting it from your end.

var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  }
});


/* CODE BELOW ONLY EXIST TO IMITATE BROWSER SIZE */

const wrapper = document.querySelector('#window');
const desktop = document.querySelector('#desktop');
const mobile = document.querySelector('#mobile');

desktop.addEventListener('click', resize.bind(this, 'desktop'));
mobile.addEventListener('click', resize.bind(this, 'mobile'));

function resize(size, event){
  event.preventDefault();
  wrapper.classList.remove('desktop', 'mobile')
  wrapper.classList.add(size);
}
/* CSS HERE ONLY EXIST TO IMITATE BROWSER SIZE */

#window {
  margin-top: 10px;
  border: 1px solid black;
  transition: all 0.3s;
}

#window.desktop {
  width: 450px;
  height: 253px;
}

#window.mobile {
  width: 320px;
  height: 568px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

<!-- Ignore these -->
<button id="desktop">Desktop</button>
<button id="mobile">Mobile</button>

<!-- #window is to imitate browser window size -->
<!-- imagine #container as the direct children of <body> -->
<div id="window" class="desktop">

  <!-- Moved all CSS to HTML as your requirement -->
  <div id="container" style="width: 100%; height: 100%; position: relative;">
    <canvas id="myChart"></canvas>
  </div>
  
</div>

Upvotes: 1

Mehdi Ayari
Mehdi Ayari

Reputation: 548

This is happening because you have "reponsive" activated by default. In this case , the attributes width and height will be ignored.

The solution is to desactivate the responsive option like this :

 options: {
    responsive:false,
    scales: {
        yAxes: [{
            ticks: {
                beginAtZero: true
            }
        }]
    }
}

Upvotes: 2

Related Questions