Search code examples
javascriptgridp5.js

How to change the rows or columns of a grid without messing up the content


I want to be able to implement more rows or columns to the grid depending on the format. (For example if i want to use the sketch on a horizontal 16x9 screen, there would have to be more rows than columns) Right now it only works if the format/canvas is square.

As soon as I change the number of tiles or the size of the canvas, the elements jump around. Here is my sketch:

let colors = [
  "#F7F7F7",
  "#141414",
  "#FB2576",
  "#F48668",
  "#67339E",
  "#00A6A6",
  "#78FFD6"
];

function drawSubdividedCircle(x, y, size, segments, layers) {
  segments = random (1,13);
  layers = random (1,13);
  const r = 360 / segments;

  for (let i = 0; i < segments; i++) {
    for (let j = 0; j < layers; j++) {
      fill(random(colors));
      const s = map(j, 0, layers, size, 0);
      arc(
        x + size / 2,
        y + size / 2,
        s,
        s,
        radians(r * i),
        radians(r * (i + 1)));
    }
  }
}

function setup() {
  createCanvas(500, 500);
  frameRate(2);
}

function draw() {
  noStroke();

  let tilesX = 5;
  let tilesY = 5;
  let tileW = width / tilesX;
  let tileH = height / tilesY;
  const tileSize = width / tilesX;
  
  for (let x = 0; x < tilesX; x++) {
    for (let y = 0; y < tilesY; y++) {
      
  rect(x*tileW, y*tileH, tileW, tileH);
  fill(random(colors));
  
  push();
  for (let x = 0; x < tilesX; x++) {
    for (let y = 0; y < tilesY; y++) {
      
  let r = random(1);
  if (r < 0.5) {
    ellipseMode(CORNER);
    ellipse(x*tileW, y*tileH, tileW, tileH);
    fill(random(colors));
       } else {
        ellipseMode(CENTER);
        drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
        fill(random(colors));
  pop();
          }
        }  
      }
    }
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.js"></script>


Solution

  • I changed your code a little.. Removed two redundant for-loops, it is much faster now. When you want to make your program responsive, you have to make a choice. Do you want the circles to scale when you change the resolution or maybe do you want the amount of rows/columns to change when the resolution changes? There are several possibilities, I made it now to keep the amount of tiles, and use the smaller value of the 'tileW' and 'tileH' to remain the circle shape.

    let colors = [
      "#F7F7F7",
      "#141414",
      "#FB2576",
      "#F48668",
      "#67339E",
      "#00A6A6",
      "#78FFD6"
    ];
    
    var tilesX = 5;
    var tilesY = 5;
    
    var tileW;
    var tileH;
    var tileSize;
    
    function drawSubdividedCircle(x, y, size, segments, layers)
    {
      segments = random (1,13);
      layers = random (1,13);
      
      const r = 360 / segments;
    
      for (let i = 0; i < segments; i++)
      {
        for (let j = 0; j < layers; j++)
        {
          fill(random(colors));
          const s = map(j, 0, layers, size, 0);
          arc(
            x + size / 2,
            y + size / 2,
            s,
            s,
            radians(r * i),
            radians(r * (i + 1)));
        }
      }
    }
    
    function setup()
    {
      createCanvas(550, 500);
      ellipseMode(CENTER);
      //frameRate(2);
      
      tileW    = width / tilesX;
      tileH    = height / tilesY;
      tileSize = min(tileW, tileH);
    }
    
    function draw()
    {
      background(0);
      noStroke();
    
      for (let x = 0; x < tilesX; x++)
      {
        for (let y = 0; y < tilesY; y++)
        {
          rect(x * tileSize, y * tileSize, tileSize, tileSize);
          fill(random(colors));
    
          let r = random(1);
    
          if (r < 0.5)
          {
            ellipse((x - 0.5) * tileSize, (y - 0.5) * tileSize, tileSize, tileSize);
            fill(random(colors));
          }
          else
          {
            drawSubdividedCircle(x * tileSize, y * tileSize, tileSize);
            fill(random(colors));
          }
        }
      }
    }