Bull's eye pattern with delay in between the bands

Viewed 27

I have to draw a Bull's eye pattern using html canvas and js. There's a delay checkbox. If checked, each band will have to be drawn with a delay of 1500 ms.

Here's my HTML code:

<canvas id="testCanvas" style="border: 1px solid;"  width="400" height="400"> 
</canvas>
<p></p>
<label for="band">BandWidth:</label>
<input type="range" id="band" min="5" max="50" step="5" value="25"
    oninput="bullsEyeModule.drawPattern()"></input>
<p>Current Band Width: <output id="widthDisplay"></output></p>

<label for="delay">Delay:</label>
<input type="checkbox" id="delay"
    onclick="bullsEyeModule.drawPattern()"></input>

Javascript code:

window.onload = init;
function init() {
    
        let canvas = document.getElementById("testCanvas");
        let context = canvas.getContext("2d");

        let centerX = canvas.width / 2;
        let centerY = canvas.height / 2;
         //interval
         let timerId;
         let delay = false;
        // draw the initial pattern
        drawPattern();
}

// called whenever the slider value changes or the delay checkbox is clicked
function drawPattern()
{
    if (timerId) {
        clearInterval(timerId);
        timerId = undefined;
    }
    context.clearRect(0, 0, canvas.width, canvas.height);
    let bandWidth = document.getElementById("band").value;
    document.getElementById("widthDisplay").value = bandWidth;
    delay = document.getElementById("delay").checked;
    
    let currentRadius = 200;
    let color = ["red", "blue"];
    let count = 0;
    context.fillStyle = "red";
    while (currentRadius > 0 ) {
        //alternate color
        if (count % 2 === 0) {
            context.fillStyle = color[0];
        } else {
            context.fillStyle = color[1];
        }
        context.beginPath();
        context.arc(centerX, centerY, currentRadius, 0, 2 * Math.PI, true);
        context.fill();
        context.closePath();
        count++;
        currentRadius = currentRadius - bandWidth; 
}
    
}

return {
    drawPattern: drawPattern
};

The part without delay works, I can't figure out how to implement the delay part. I've tried using setInterval function but does not work as required.

1 Answers

This is a recursion actually. We use a helper function foo_next to draw a circle then handle whether call itself after 1500ms or not.

window.onload = init;

let canvas = document.getElementById("testCanvas");
let context = canvas.getContext("2d");
let centerX = canvas.width / 2;
let centerY = canvas.height / 2;
let delay = false;
var speed = 500;
let color = ["red", "white"];

function init() {
  // draw the initial pattern
  drawPattern();
}


// called whenever the slider value changes or the delay checkbox is clicked
function drawPattern() {
  let bandWidth = document.getElementById("band").value;
  document.getElementById("widthDisplay").value = bandWidth;
  delay = document.getElementById("delay").checked;
  if (delay) {
    speed = 250
  } else {
    speed = 0
  }
  var currentRadius = 200;
  var count = 0
  context.clearRect(0, 0, canvas.width, canvas.height);


  function do_spiral(foo_then) {
    context.fillStyle = color[count % 2];
    context.beginPath();
    context.arc(centerX, centerY, currentRadius, 0, 2 * Math.PI, true);
    context.fill();
    foo_then();
  }

  function foo_next() {
    if (currentRadius > 0) {
      do_spiral(function() {
        count++;
        currentRadius = currentRadius - bandWidth;
        setTimeout(foo_next, speed)
      })

    } else {
      // console.log("done")
    }

  }

  foo_next();


}
<canvas id="testCanvas" style="border: 1px solid;" width="400" height="400"> 
</canvas>
<p></p>
<label for="band">BandWidth:</label>
<input type="range" id="band" min="5" max="50" step="5" value="25" oninput="drawPattern()"></input>
<p>Current Band Width: <output id="widthDisplay"></output></p>

<label for="delay">Delay:</label>
<input type="checkbox" id="delay" onclick="drawPattern()" checked></input>

Related