Случайное появление и автоматическое перемещение элементов html с помощью js

Всем привет. Хочу сделать, чтобы изображения(сердца) появлялись случайным образом на экране, перемещались вверх, немного в бок разные стороны и исчезали, становясь прозрачными, затем они начинают анимацию с нового места.

<div class="serdca">
<img class="serdce_img" src="img/serce.png">
<img class="serdce_img" src="img/serce.png">
<img class="serdce_img" src="img/serce.png">
<img class="serdce_img" src="img/serce.png">
<img class="serdce_img" src="img/serce.png">
</div> `



let img = document.querySelectorAll(".serdce_img");
let arr = new Array(img.length).fill(0).map((_, i) => i).sort(() => Math.random() - 0.5);

for (let i = 0; i < 5; i++) {
let rand_img = img[ arr[i] ];
rand_img.classList.remove(".serdce_img");
rand_img.parentNode.appendChild(rand_img);
}

// попытался сделать рандом, но не вышло. Кто поможет тому буду очень благодарен!

Ответы (2 шт):

Автор решения: UModeL

Если сердец единовременно не более двадцати, то простейшие CSS-анимации (с перезапуском путём клонирования и замены) вполне справятся:

window.addEventListener('animationend', function(ev) {
  if (ev.animationName === 'rise_up') {
    let target = ev.target;
    target.style.setProperty('--ad', `${4 + Math.random() * 5}s`);
    let newone = target.cloneNode(true);
    target.parentNode.replaceChild(newone, target);
  }
});

let imgs = document.querySelectorAll('.serdce_img');
[...imgs].forEach(function(img) {
  img.style.setProperty('--ad', `${4 + Math.random() * 5}s`);
});
.serdca {
  display: flex;
  justify-content: space-around;
  align-items: flex-end;
  height: 90vh;
  overflow: hidden;
  filter: drop-shadow(0 25px 4px #0002);
}

.serdce_img {
  --ad: 5s;
  opacity: 0;
  animation: rise_up var(--ad) linear forwards, side_to_side var(--ad) ease-in-out infinite;
  
  height: 24px;
  aspect-ratio: 1;
  background: radial-gradient(circle at 60% 65%, #fccf 10%, #f000 50%) top -15% left -20%, radial-gradient(circle at 40% 65%, #faaf 0%, #f000 35%) top -30% right 15%, radial-gradient(circle at 60% 65%, #f00f 64%, #f000 65%) top left, radial-gradient(circle at 40% 65%, #f00f 64%, #f000 65%) top right, linear-gradient(to bottom left, #f00f 43%, #f000 43%) bottom left, linear-gradient(to bottom right, #f00f 43%, #f000 43%) bottom right;
  background-size: 50% 50%;
  background-repeat: no-repeat;
}

@keyframes rise_up {
  from { transform: translatey(0);   }
  25%, 85% { opacity: 1; }
  to { transform: translatey(-80vh); }
}
@keyframes side_to_side {
  0%, 100% { translate: 0; }
  10% { translate: -10px;  }
  25% { translate:  20px;  }
  40% { translate: -40px;  }
  60% { translate:  65px;  }
  85% { translate: -70px;  }
}
<div class="serdca">
  <div class="serdce_img"></div><div class="serdce_img"></div><div class="serdce_img"></div>
  <div class="serdce_img"></div><div class="serdce_img"></div><div class="serdce_img"></div>
  <div class="serdce_img"></div><div class="serdce_img"></div><div class="serdce_img"></div>
  <div class="serdce_img"></div><div class="serdce_img"></div><div class="serdce_img"></div>
  <div class="serdce_img"></div><div class="serdce_img"></div><div class="serdce_img"></div>
</div>

→ Ссылка
Автор решения: Rudi

Можно сделать что-то такое и поиграть с значениями в setTimeout и randomPos...

let count = 60;

function createHeart() {
  const heart = document.createElement('img');
  heart.setAttribute('class', 'serdce_img');
  heart.setAttribute('src', 'https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg');
  heart.addEventListener('animationend', (event) => {
    event.target.remove();
    setTimeout(createHeart, Math.floor(Math.random() * (1500 - 700) + 500));
  });
  randomPos(heart);
  document.querySelector('.serdca').appendChild(heart);
}

function randomPos(heart) {
  heart.style.top = Math.floor(Math.random() * (window.innerHeight - 10) + 30) + 'px';
  heart.style.left = Math.floor(Math.random() * (window.innerWidth - 200) + 90) + 'px';
}

function initHearts() {
  for (let i = 0; i < count; i++) {
    setTimeout(createHeart, Math.floor(Math.random() * (1500 - 700) + 500))
  }
}

initHearts();
.serdca {
  position: relative;
  height: 100px;
}

.serdce_img {
  position: absolute;
  width: 30px;
  height: 30px;
  animation: moveHearts 3s forwards;
}

@keyframes moveHearts {
  0% {
    opacity: 1;
    transform: translateY(0) translateX(0);
  }
  25% {
    opacity: 0.75;
    transform: translateY(-50px) translateX(10px);
  }
  50% {
    opacity: 0.5;
    transform: translateY(-100px) translateX(-10px);
  }
  75% {
    opacity: 0.25;
    transform: translateY(-150px) translateX(20px);
  }
  100% {
    opacity: 0;
    transform: translateY(-200px) translateX(-20px);
  }
}
<div class="serdca">
  <img class="serdce_img" src="https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg">
  <img class="serdce_img" src="https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg">
  <img class="serdce_img" src="https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg">
  <img class="serdce_img" src="https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg">
  <img class="serdce_img" src="https://img.freepik.com/free-psd/red-heart-isolated-transparent-background_191095-27355.jpg">
</div>

→ Ссылка