Search code examples
processing

A circle that has a specific percentage amount of fill


I would like to create a circle that is filled to a certain percentage like so:

a white circle with a thick black outline with a blue section at the bottom of the section, also delineated with a thick outline

and this: a bottom to top preloader masked by a circle with 2 backgrounds: light blue and dark blue. the motion appears as (sine) waves giving the impression of water levels rising. additionally the loaded percentage is displayed as white text

I'm using Processing Java.

My attempt is using the arc() function however I have a hard time determining how I should calculate the values for angle1 and angle2:

        percentageRemaining = 0.25;
        angle1 = ????
        angle2 = ????
        noStroke();
        fill(35);
        arc(100, 100, 200, 200, angle1, angle2, CHORD);

I did try some fixes with no luck thus far.


Solution

  • With p5.js you can use noise for the waves at the top on a square shape. The clip() function makes sure that you draw only inside a circular region.

    First demo without noise:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/p5.min.js"></script>
    

    let startTime;
    let circleRadius = 100;
    let w2, h2;
    
    function setup() {
      createCanvas(240, 240);
      startTime = millis();
      w2 = width / 2;
      h2 = height / 2;
      textSize(42);
      textAlign(RIGHT, CENTER);
      rectMode(CENTER);
    }
    
    function draw() {
      background(0, 0, 88);
      mask();
    
      let elapsedTime = (millis() - startTime) / 500.0;
      let percentage = min(elapsedTime / 10.0, 1);
      let fillHeight = circleRadius * 2 * percentage;
    
      // Draw blue rectangle fill, from bottom to top
      fill(19, 99, 255);
    
      beginShape();
    
      // Add the starting point of the curve at the left edge
      vertex(w2 - circleRadius, h2 + circleRadius); // Start at the bottom-left corner
      vertex(w2 - circleRadius, h2 + circleRadius); // First point on the curve
    
      // Create the curve from left to right
      let y;
      for (let x = w2 - circleRadius; x <= w2 + circleRadius; x += 80) {
        if (percentage == 1) {
          y = h2 + circleRadius - fillHeight;
        } else {
          y = h2 + circleRadius - fillHeight;
        }
        vertex(x, y);
      }
    
      // Add the ending point of the curve at the right edge
      vertex(w2 + circleRadius, h2 + circleRadius - fillHeight); // Last point on the curve
      vertex(w2 + circleRadius, h2 + circleRadius); // Bottom-right corner
    
      endShape(CLOSE); // Close the shape to fill the area
    
      let textY = h2;
      let percentText = int(percentage * 100) + "%";
    
      fill(255);
      text(percentText, w2 + 56, textY);
    }
    
    
    function mask() {
      fill(color(0, 0));
      stroke(0, 0);
      strokeWeight(0);
      ellipse(w2, h2, 2 * circleRadius, 2 * circleRadius);
      drawingContext.clip();
    }
    
    // Save a 5-second gif when the user presses the 's' key.
    function keyPressed() {
      if (key === 's') {
        saveGif('mySketch', 5);
      }
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/p5.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/p5.min.js"></script>
    

    With noise:

    let startTime;
    let circleRadius = 100;
    let w2, h2;
    
    function setup() {
      createCanvas(240, 240);
      startTime = millis();
      w2 = width / 2;
      h2 = height / 2;
      textSize(42);
      textAlign(RIGHT, CENTER);
      rectMode(CENTER);
    }
    
    function draw() {
      background(0, 0, 88);
      mask();
    
      let elapsedTime = (millis() - startTime) / 500.0;
      let percentage = min(elapsedTime / 10.0, 1);
      let fillHeight = circleRadius * 2 * percentage;
    
      // Draw blue rectangle fill, from bottom to top
      fill(19, 99, 255);
    
      beginShape();
      let noiseScale = 0.005;
    
      // Add the starting point of the curve at the left edge
      curveVertex(w2 - circleRadius, h2 + circleRadius); // Start at the bottom-left corner
      curveVertex(w2 - circleRadius, h2 + circleRadius); // First point on the curve
    
      // Create the curve from left to right
      let y;
      for (let x = w2 - circleRadius; x <= w2 + circleRadius; x += 80) {
        if (percentage == 1) {
          y = h2 + circleRadius - fillHeight;
        } else {
          y = h2 + circleRadius - fillHeight + map(noise(x * noiseScale, fillHeight), 0, 1, -50, 50);
        }
        curveVertex(x, y);
      }
    
      // Add the ending point of the curve at the right edge
      curveVertex(w2 + circleRadius, h2 + circleRadius - fillHeight); // Last point on the curve
      curveVertex(w2 + circleRadius, h2 + circleRadius); // Bottom-right corner
    
      endShape(CLOSE); // Close the shape to fill the area
    
      let textY = h2;
      let percentText = int(percentage * 100) + "%";
    
      fill(255);
      text(percentText, w2 + 56, textY);
    }
    
    
    function mask() {
      fill(color(0, 0));
      stroke(0, 0);
      strokeWeight(0);
      ellipse(w2, h2, 2 * circleRadius, 2 * circleRadius);
      drawingContext.clip();
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.2/p5.min.js"></script>