2

I have a function that creates circle.

Circles appear every 3 seconds, for this I use setInterval

const rate = 3000;

setInterval(() => {
    i += 1;
    createDiv(`circle${i}`);
}, rate);

Such a question, can I make the speed of the appearance of circles gradually increase, let's say every minute the value decreases by 100?

Or is it possible to somehow make several such setInterval and change them after some time has passed? Or just change their values?

//create circle

var clickEl = document.getElementById("clicks");

var spawnRadius = document.getElementById("spawnRadius");
var spawnArea = spawnRadius.getBoundingClientRect();
const circleSize = 95; // Including borders

function createDiv(id, color) {
    let div = document.createElement('div');
    div.setAttribute('class', id);
    if (color === undefined) {
        let colors = ['#ebc6df', '#ebc6c9', '#e1c6eb', '#c6c9eb', '#c6e8eb', '#e373fb', '#f787e6', '#cb87f7', '#87a9f7', '#87f7ee'];
        randomColor = colors[Math.floor(Math.random() * colors.length)];
        div.style.borderColor = randomColor;
    }
    else {
        div.style.borderColor = color;
    }
    
    // Randomly position circle within spawn area
    div.style.top = `${Math.floor(Math.random() * (spawnArea.height - circleSize))}px`;
    div.style.left = `${Math.floor(Math.random() * (spawnArea.width - circleSize))}px`;
    div.classList.add("circle", "animation");

    // Add click handler
    let clicked = false;
    div.addEventListener('click', (event) => {
        if (clicked) { return; } // Only allow one click per circle
        clicked = true;
        
        div.style.animation = 'Animation 200ms linear forwards';
        setTimeout(() => { spawnRadius.removeChild(div); }, 220);
    });
    
    spawnRadius.appendChild(div);
}

let i = 0;

const rate = 3000;

setInterval(() => {
    i += 1;
    createDiv(`circle${i}`);
}, rate);
html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  background: #0f0f0f;
}

.circle {
  width: 80px;
  height: 80px;
  border-radius: 80px;
  background-color: #0f0f0f;
  border: 3px solid #000;
  position: absolute;
}

#spawnRadius {
    top: 55%;
    height: 650px;
    width: 1000px;
    left: 50%;
    white-space: nowrap;
    position: absolute;
    transform: translate(-50%, -50%);
    background: #0f0f0f;
    border: 2px solid #ebc6df;
}

@keyframes Animation {
    0% {
        transform: scale(1);
        opacity: 1;
    }
    50% {
        transform: scale(.8);
    }
    100% {
        transform: scale(1);
        opacity: 0;
    }
}
<html>
<body>

<div id="spawnRadius"></div>

</body>
</html>

1 Answers1

1

TL;DR: Use setTimeout instead of setInterval. That way, on every timeout you can decrement your spawn rate ms timeout:

const createCircle = () => { /* Your code goes here */ };

const spawnRate = {curr: 3000, min: 400};

const loop = () => {
  createCircle();
  spawnRate.curr -= 100;
  spawnRate.curr = Math.max(spawnRate.min, spawnRate.curr);
  setTimeout(loop, spawnRate.curr);
};

loop(); // Start loop!
  • to prevent your loop go to extreme speeds you can also make use of Math.max to limit your spawn rate to a spawnRate.min
  • you don't need a setTimeout to remove an element after 200ms, use the "animationend" Event.
  • use Element.append() and Element.remove() methods
  • You don't need to cancel/prevent extra clicks using variables, just pass the {once: true} options to the Event Listener.

Example:

// DOM utility functions:

const ELNew = (tag, prop) => Object.assign(document.createElement(tag), prop);
const ELS = (sel, par) => (par || document).querySelectorAll(sel);
const EL = (sel, par) => (par || document).querySelector(sel);

// Task: Create circles

const colorRand = () => `hsl(${Math.floor(Math.random() * 360)}, 80%, 80%)`;
const EL_spawn = EL("#spawnRadius");

const spawnRate = {
  curr: 3000,
  min: 400,
};

const createCircle = () => {
  
  const BCR_area = EL_spawn.getBoundingClientRect();
  const EL_circle = ELNew("div", {className: `circle animation`});
  const size = 95;

  Object.assign(EL_circle.style, {
    borderColor: colorRand(),
    top: `${Math.floor(Math.random() * (BCR_area.height - size))}px`,
    left: `${Math.floor(Math.random() * (BCR_area.width - size))}px`,
    width: `${size}px`,
    height: `${size}px`,
  });

  EL_circle.addEventListener('click', (event) => {
    EL_circle.style.animation = 'Animation 200ms linear forwards';
    EL_circle.addEventListener("animationend", () => {
      EL_circle.remove();
    });
  }, {once: true});

  EL_spawn.append(EL_circle);
};

const loop = () => {
  createCircle();
  spawnRate.curr -= 100;
  spawnRate.curr = Math.max(spawnRate.min, spawnRate.curr);
  setTimeout(loop, spawnRate.curr);
};

loop(); // Start loop!
* {
  margin: 0;
  box-sizing: border
}

html,
body {
  width: 100%;
  height: 100%;
  background: #0f0f0f;
}

.circle {
  border-radius: 50%;
  background-color: #0f0f0f;
  border: 3px solid #000;
  position: absolute;
  transition: background-color 0.2s;
}

.circle:hover {
  background-color: hsla(0, 100%, 100%, 0.1);
}

#spawnRadius {
  position: absolute;
  width: 100%;
  height: 100%;
}

@keyframes Animation {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(.8);
  }
  100% {
    transform: scale(1);
    opacity: 0;
  }
}
<div id="spawnRadius"></div>
  • you don't necessarily need an Array of colors... you could use hsl() clors for that matter.
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313