'Add disappearing circle element to click function

I have a page where circles randomly appear in a certain place. When you click on the circle, it disappears.

So, I have another circle-smoke, and I want that when the clicked circle disappears, this circle with the circle-smoke class appears in its place, and also dissolves in just a second.

I tried to add new element creation to my click function, but it didn't work

let div1 = document.createElement('div');
div1.classList.add("circle-smoke");

Isn’t it possible for the smoky circle to hold on a little more and steam out? The first one quickly disappeared.

In general, the whole point is to remain like this in the place of the disappearing circle, and then also disappear

enter image description here

How can I best implement this?

//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: 250px;
    width: 500px;
    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;
    }
}

.circle-smoke {
  position: relative;
  height: 500px;
  width: 500px;
  filter: url(#wave);
  transform: scale(0.3);
}
.circle-smoke::before {
  content: "";
  position: absolute;
  top: 100px;
  left: 100px;
  right: 100px;
  bottom: 100px;
  border: 10px solid #fff;
  border-radius: 50%;
  box-shadow: 0 0 50px #ebc6df, inset 0 0 50px #ebc6df;
  filter: url(#wave) blur(10px);
}

svg {
  display: none;
}
<html>
<body>

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

</body>
</html>


Solution 1:[1]

We can animate box-shadow:

let noOfCircles = 0;
const totalCircles = 10;
const colors = ['#ebc6df', '#ebc6c9', '#e1c6eb', '#c6c9eb', '#c6e8eb', '#e373fb', '#f787e6', '#cb87f7', '#87a9f7', '#87f7ee'];
const circleSize = 95; // Including borders
let i = 0;
const rate = 1000;


const clickEl = document.getElementById("clicks");
const spawnRadius = document.getElementById("spawnRadius");
const spawnArea = spawnRadius.getBoundingClientRect();

function createDiv(id, color) {
  let div = document.createElement('div');
  div.classList.add("circle", id);

  if (!color)
    color = colors[Math.floor(Math.random() * colors.length)];

  div.style.setProperty('--bStart', color);
  // Randomly position circle within spawn area
  div.style.top = `${(Math.floor(Math.random() * spawnArea.height + circleSize)) % (spawnArea.height - circleSize)}px`;
  div.style.left = `${(Math.floor(Math.random() * spawnArea.width + circleSize)) % (spawnArea.width - circleSize)}px`;
  // Add click handler
  div.addEventListener('click', (event) => {
    div.style.setProperty('border-color', color+'ee');
    div.style.setProperty('pointer-events', 'none');
    div.classList.add("circle-smoke");
    
    setTimeout(() => {
      spawnRadius.removeChild(div);
      noOfCircles--;
    }, 1500);

  }, { once: true });

  spawnRadius.appendChild(div);
  noOfCircles++;
}

setInterval(() => {
  if (noOfCircles >= totalCircles) return;
  createDiv(`circle${++i}`);
}, rate);
*{
 box-sizing:border-box;
}
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  background: #0f0f0f;
}

.circle {
  --bStart: #fff;
  width: 80px;
  height: 80px;
  border-radius: 50%;
  background-color: transparent;
  border: 3px solid var(--bStart);
  position: absolute;
}

#spawnRadius {
  height: 100vh;
  width: 100vw;
  background: #0f0f0f;
  border: 2px solid #ebc6df;
}

@keyframes Animation {
  0% {
    box-shadow: 0 0 0px 0px var(--bStart), inset 0 0 0px 0px var(--bStart);
    opacity: 1;
  }
  100% {
    box-shadow: 0 0 30px 25px #0000, inset 0 0 30px 25px #0000;
    border-color: #0000;
    opacity: 0;
  }
}

.circle-smoke {
  animation: Animation 1.5s linear forwards;
}
<div id="spawnRadius"></div>

{ once: true } removes the click event handler after one click.
div.style.setProperty('pointer-events', 'none') this allows us to click on multiple circles that are on top of each other.
For the demo I am allowing only 10 circles at a time.

Solution 2:[2]

My quick and dirty solution is here (the filters were disabled and the rate was increased for debugging purposes):

//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, isSmoke) {
  let div = document.createElement('div');
  div.setAttribute('class', id);

  if (!isSmoke) {
    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;
  if (!isSmoke) {
    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);

      let newDiv = createDiv(id, color, true);
      newDiv.style.top = div.style.top;
      newDiv.style.left = div.style.left;
      newDiv.classList.add("circle-smoke");
      newDiv.classList.remove("circle");
      newDiv.id = null;
    });
  } else {
    div.style.animation = 'Animation 500ms linear forwards';
    setTimeout(() => {
      spawnRadius.removeChild(div);
    }, 220);
  }

  spawnRadius.appendChild(div);

  return div;
}

let i = 0;

const rate = 1000;

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: 250px;
  width: 500px;
  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;
  }
}

.circle-smoke {
  position: absolute;
  margin: -5px;
  height: 80px;
  width: 80px;
  border: 10px solid rgba(255, 255, 255, .5);
  border-radius: 50%;
  box-shadow: 0 0 50px #ebc6df, inset 0 0 50px #ebc6df;
  //filter: url(#wave) blur(10px);
}

svg {
  display: none;
}
<html>

<body>

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

</body>

</html>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 the Hutt
Solution 2 jiwopene