Responsive canvas

Hello all!

I am very new with p5js, and as an exercise I created a very simple sketch that generates an abstract landscape based on a lot of lines tied to a vector field originated by perlin noise.

I am trying to make it responsive enough to be shown in tablets and mobile devices as well. What I would like to obtain in a mobile, is the same full-size canvas as if it was on a desktop (eg: 1200 x 750) but without any margin (eg: in position (0,0) rather than centered). In this way, one would have the full canvas and ideally it would be possible to scroll horizontally to see it all.

I managed to do it, but there’s one very annoying detail I can’t get rid of: an extra bottom padding is added as a consequence of the canvas being larger than the screen size. You can see it happening here, if you visit it from a mobile device (or you activate the mobile device simulator in your browser): http://pietrobolcato.com/p5/thirdPerlin/

Does anybody know why?

The code is shown below (sorry for the quality of it, as I said I am just a beginner with processing):

var scl = 1;
var inc; // 0.009 o 0.005;
var inc2;
var inc3;
var perlinNoiseRnd;
var cols, rows;
var zoff = 0;
var xoff = 0;
var yoff = 0;
var name;

var canvasoffset = 200;

var x = 0;
var y = 0;

function centerCanvas(cvn) {
  var x = (windowWidth - width) / 2;
  var y = (windowHeight - height) / 2;
  cvn.position(0, y);
}

function setup() {
  pixelDensity(1)
  if (displayWidth >= 1024) { // tablet and desktops
    createCanvas((displayWidth * 0.625) + canvasoffset, (displayHeight * 0.625) + canvasoffset);
  } else if (displayWidth < 1024 && displayWidth >= 768) { // tablet - WIP
    let cvn = createCanvas(1200 + canvasoffset, 750 + canvasoffset);
    centerCanvas(cvn)
  }
  else { // mobile
    canvasoffset = 0;
    let cvn = createCanvas(1200 + canvasoffset, 750 + canvasoffset);
    cvn.position(0, 0)
  }
  
  strokeWeight(0.5);
  background(11, 9, 10)
  // noiseSeed(500)
  // randomSeed(500)
  cols = floor((width - canvasoffset) / scl);
  rows = floor((height - canvasoffset) / scl);
  inc = random(0.005, 0.009);
  inc2 = random(0.005, 0.009);
  inc3 = random(0, 0.001)
  perlinNoiseRnd = random(1, 1.5)

  name = "p.00" + inc.toString()[4] + inc2.toString()[4] + inc3.toString()[4]
  document.title = name;

  console.log(inc, inc2, inc3)
}

function mousePressed() {
  let fs = fullscreen();
  fullscreen(!fs);
}

function draw() {
  // background(0);

  if (y < rows) {
    y++;
    xoff = 0;
    for (var x = 0; x < cols; x++) {
      var n = perlinNoiseRnd * noise(xoff, yoff, zoff);
      var v = p5.Vector.fromAngle(n * TWO_PI * 1.2);

      xoff += inc;

      var chance = random(["head", "tail"])
      var plus;
      var fact;

      if (chance === "head" || y > (rows-50)  ) { // low density
        plus = 0;
        fact = 1;
      }
      else { // high density
        plus = 1;
        fact = 2/3;
        // plus = 0;
        // fact = 1;
      }

      for (var i = 0; i < scl + plus; i++) {
        for (var j = 0; j < scl; j++) {
          push();
          translate((canvasoffset / 2) + (x * scl + i), (canvasoffset / 2) + (y * scl + j));
          stroke(238, 238, 255, map(n, 0, 1, (-12 * fact) - map(perlinNoiseRnd, 1, 1.5, 0, 5), (30 * fact)))
          rotate(v.heading());
          line(0, 0, random(map(n, 0, 1, 0, 25)) + random(15), 0);
          pop();
        }
      }
      x++;
    }
    yoff += inc2;
  } else {
    console.log("finito")
    noLoop()
  }

  // noLoop();
  zoff += inc3 // 0.01;
  // console.log(frameRate())
}

function keyPressed() {
  if (key === 's') {
    saveCanvas(name, 'png');
  }
}

And index.html

<!DOCTYPE html>
<html lang="">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width">
  <title>p.00000</title>
  <style>
    html, body {
      height: 100%;
      background-color: #0b090a;
    }

    body {
      margin: 0;
      display: flex;

      /* This centers our sketch horizontally. */
      justify-content: center;

      /* This centers our sketch vertically. */
      align-items: center;
    }
  </style>
  <script src="../p5.js"></script>
  <script src="../addons/p5.sound.min.js"></script>
  <script src="sketch.js"></script>
</head>

<body>
  <main>
  </main>
</body>

</html>

Thank you so much in advance for taking the time to read the post and to help me! I really appreciate it! :slight_smile:

Removing the inline style of width/height of your canvas from the browser inspector DOM removes that extra bottom margin so I suspect the logic of setting canvas width and height on a tall screen has something wrong.

1 Like

add this style to your main and it will solve the issue
main{
height:100vh;
overflow-x:hidden;
}

1 Like

This works! Thanks a lot! :slight_smile: I also thought of another workaround of setting via javascript the max-height property of the body to the windowHeight, but your solution is cleaner, I like it way more! Thank you again! :slight_smile:

Also thanks @ErraticGenerator for taking the time to read the post and give your input, I really appreciate as well!

One last question: what do you think of the graphical result itself?

1 Like

I think it looks pretty cool

1 Like

Thanks a lot! appreciate the time for your feedback! :slight_smile: