Home > Enterprise >  How can I make a canvas element responsive when resizing the screen?
How can I make a canvas element responsive when resizing the screen?

Time:09-27

I have Matrix canvas on my site and there is problem with responsiveness when I change the width of the viewport the canvas doesn't update to fit.

https://codepen.io/ems-sin/pen/zYjpree

HTML
<canvas id="bglitch" ></canvas> 
CSS
    *{
 margin:0;
  background-color:#010b13;
  overflow: hidden;
}
#bglitch{
  opacity: 0.5;
  z-index: -10;
  top: 0;
  right:0;
}
Javascript
var bglitch = document.getElementById("bglitch");
    var ctx = bglitch.getContext("2d");
    bglitch.height = window.innerHeight;
    bglitch.width = window.innerWidth;
    var matrix = "アィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ・ーヽ";
    matrix = matrix.split("");
    var font_size = 24;
    var columns = bglitch.width/font_size;
    var drops = [];
    for(var x = 0; x < columns; x  )
        drops[x] = 1; 
    function draw()
    {
        ctx.fillStyle = "rgba(0, 0, 0, 0.04)";
        ctx.fillRect(0, 0, bglitch.width, bglitch.height);
        ctx.fillStyle = "#f4427d";
        ctx.font = font_size   "px arial";
        for(var i = 0; i < drops.length; i  ){
            var text = matrix[Math.floor(Math.random()*matrix.length)];
            ctx.fillText(text, i*font_size, drops[i]*font_size);
            if(drops[i]*font_size > bglitch.height && Math.random() > 0.975)
                drops[i] = 0;
            drops[i]  ;
        }
    }

    setInterval(draw, 35);

CodePudding user response:

You need to make your code into a function which gets called on the resize event so that the dimensions are updated.

This snippet also clears the current timing interval (if there is one) before starting another one.

<style>
  <canvas id="bglitch"></canvas>
</style>
<canvas id="bglitch"></canvas>
<script>
  var bglitch = document.getElementById("bglitch");
  var ctx = bglitch.getContext("2d");

  let timer = '';

  function init() {
    bglitch.height = window.innerHeight;
    bglitch.width = window.innerWidth;
    var matrix = "アィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ・ーヽ";
    matrix = matrix.split("");
    var font_size = 24;
    var columns = bglitch.width / font_size;
    var drops = [];
    for (var x = 0; x < columns; x  )
      drops[x] = 1;

    function draw() {
      ctx.fillStyle = "rgba(0, 0, 0, 0.04)";
      ctx.fillRect(0, 0, bglitch.width, bglitch.height);
      ctx.fillStyle = "#f4427d";
      ctx.font = font_size   "px arial";
      for (var i = 0; i < drops.length; i  ) {
        var text = matrix[Math.floor(Math.random() * matrix.length)];
        ctx.fillText(text, i * font_size, drops[i] * font_size);
        if (drops[i] * font_size > bglitch.height && Math.random() > 0.975)
          drops[i] = 0;
        drops[i]  ;
      }
    }
    clearInterval(timer);
    timer = setInterval(draw, 35);
  }
  window.onresize = init;
  window.onload = init;
</script>

CodePudding user response:

You need to add resize event listener and recalculate columns accordingly.

Add this at the end of your javascript

window.addEventListener('resize', () => {
  bglitch.height = window.innerHeight;
  bglitch.width = window.innerWidth;
  
  var columns = bglitch.width/font_size;
  for(var x = 0; x < columns; x  ) drops[x] = 1; 
})

Full working resize

    var bglitch = document.getElementById("bglitch");
        var ctx = bglitch.getContext("2d");
        bglitch.height = window.innerHeight;
        bglitch.width = window.innerWidth;
        var matrix = "アィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ・ーヽ";
        matrix = matrix.split("");
        var font_size = 24;
        var columns = bglitch.width/font_size;
        var drops = [];
        for(var x = 0; x < columns; x  )
            drops[x] = 1; 
        function draw()
        {
            ctx.fillStyle = "rgba(0, 0, 0, 0.04)";
            ctx.fillRect(0, 0, bglitch.width, bglitch.height);
            ctx.fillStyle = "#f4427d";
            ctx.font = font_size   "px arial";
            for(var i = 0; i < drops.length; i  ){
                var text = matrix[Math.floor(Math.random()*matrix.length)];
                ctx.fillText(text, i*font_size, drops[i]*font_size);
                if(drops[i]*font_size > bglitch.height && Math.random() > 0.975)
                    drops[i] = 0;
                drops[i]  ;
            }
        }

        setInterval(draw, 35);

window.addEventListener('resize', () => {
  bglitch.height = window.innerHeight;
  bglitch.width = window.innerWidth;
  
  var columns = bglitch.width/font_size;
  for(var x = 0; x < columns; x  ) drops[x] = 1; 
})
*{
 margin:0;
  background-color:#010b13;
  overflow: hidden;
}
#bglitch{
  opacity: 0.5;
  z-index: -10;
  top: 0;
  right:0;
}
<canvas id="bglitch" ></canvas>

It's better practice to separate your code into functions. For example init() function that sets all initial variables and run function that will run setTimeout and so on.

let bgData = {
  element: undefined, 
  g: undefined, 
  matrix: "アィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロヮワヰヱヲンヴヵヶヷヸヹヺ・ーヽ".split(''),
  fontSize: 24,
  columns: undefined,
  drops: [],
};

function init() {
  bgData.element = document.getElementById("bglitch");
  bgData.g = bgData.element.getContext("2d");
  resize();
  window.addEventListener('resize', resize)
}

function resize() {
  bgData.element.height = window.innerHeight;
  bgData.element.width = window.innerWidth;
  bgData.columns = bgData.element.width / bgData.fontSize;
  for(let x = 0; x < bgData.columns; x  ) bgData.drops[x] = 1; 
}


function draw() {
  bgData.g.fillStyle = "rgba(0, 0, 0, 0.04)";
  bgData.g.fillRect(0, 0, bgData.element.width, bgData.element.height);
  bgData.g.fillStyle = "#f4427d";
  bgData.g.font = bgData.fontSize   "px arial";
  
  for(let i = 0; i < bgData.drops.length; i  ) {
    const text = bgData.matrix[Math.floor(Math.random()*bgData.matrix.length)];
    bgData.g.fillText(text, i * bgData.fontSize, bgData.drops[i] * bgData.fontSize);
    if(bgData.drops[i] * bgData.fontSize > bgData.element.height && Math.random() > 0.975) bgData.drops[i] = 0;
    bgData.drops[i]  ;
  }
}

let interval;

function stop() {
  clearInterval(interval);
  window.removeEventListener('resize', resize)
}

function run() {
  stop();
  init();
  interval = setInterval(draw, 35);
}

run();
*{
 margin:0;
  background-color:#010b13;
  overflow: hidden;
}
#bglitch{
  opacity: 0.5;
  z-index: -10;
  top: 0;
  right:0;
}
<canvas id="bglitch" ></canvas>

  • Related