Home > Net >  How to draw 100 concentric circles (with four changing attributes) with a for loop
How to draw 100 concentric circles (with four changing attributes) with a for loop

Time:11-03

Using p5.js, I want to create 100 concentric circles that do the below:

  1. Draw initial circle:

    • choose size based on 0.8 x width
    • start at color 1 (based on HSB color mode)
    • start at opacity 0.01 (based on HSB color mode )
    • start at shade 100 (based on HSB color mode)).
  2. Draw next circle:

    • size to be 0.98 x previous circle size
    • color to progress by 1
    • opacity to increase by 0.01
    • shade to decrease by 1

I understand how to do this manually by drawing 100 circles with different inputs, but I want to wrap this all up in a for loop. I can get one parameter to change within the for loop but my expertise unfortunately stops there, I am very beginner. If I try hang the other parameters off the same for loop it gets really complex and something seems to break, and I don't quite understand how nested for loops work if that's what I need to do. Thank you for help in advance!

This is what I have tried so far with just 10 circles:

function setup() {
  createCanvas(1000, 1000);
  colorMode(HSB, 360, 100, 100, 100);
}

function draw() {
 
  background(0, 0, 100); // white background
  
  for (let i = width; i >= 0; i = i - width/10) {  
    
    noStroke();
    
    let colour = (i/1000)*360;
    let shade = i/10;
    let opacity = ((i/10)*-1) 100;
    fill(colour, 100, shade, opacity);
    
    let diameter = i;
    circle(width/2, height/2, diameter); 
  } 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.js"></script>

CodePudding user response:

I updated your code to match what you describe that it should do.

function draw() {
    
  background(0, 0, 100);

  for (let i = 0; i < 100; i  ) {
    
    noStroke();
    
    let colour = (10*i % 360);
    let shade = 100 - i;
    let opacity = 50   i;
    fill(colour, 100, shade, opacity);
    
    let diameter = width * Math.pow(0.98, i);
    circle(width/2, height/2, diameter); 
  } 
}
  • The color is set with (10*i % 360). I tried increasing it by 1, but that didn't do a lot, so I increased it to 10. The % operator ensures that it will wrap around [0, 360]. As an example 370 % 360 = 10.
  • The shade seems to be between [0, 100], so it starts at fill brightness, and slowly reduces to 0 when it is nearing the center of the circle. This gives a tunnel effect.
  • The opacity also seems to be between [0, 100]. I have added a starting value of 50 so you can see the effect.
  • The diameter is changing based on the iteration of the loop. It uses Math.pow(0.98, i) to calculate the coefficient which indicates how small it has gotten.

All in all, this is the result that I've got:

enter image description here

CodePudding user response:

function setup() 
{
  createCanvas(800, 800);
  stroke(255);
  strokeWeight(2);
  noFill();
}

function draw() 
{
  background(0);
  translate(width/2,height/2);
  let NUMCIRCLES = 100;
  let startRadius = 100;
  let endRadius = 400;
  for(let i = 0; i < NUMCIRCLES; i  )
  {
    let circleRadius = map(i,0,NUMCIRCLES-1, startRadius, endRadius);
    let color = map(i,0,NUMCIRCLES-1, 20,255);
    let opacity = map(i,0,NUMCIRCLES-1, 100,255);

    stroke(color, opacity);
    ellipse(0,0, circleRadius,circleRadius);
  }
}

It would help if you used the map function instead. It's super handy. Also, don't mind that I'm using an ellipse instead of the circle function. I just like thinking in terms of radius.

  • Related