Hi everyone!
Here is another fun animation I created to try out some things:
The full code looks as follows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Animating Dynamic Elements</title>
<style>
body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
display: grid;
place-items: center;
}
.container {
width: 400px;
height: 400px;
display: grid;
place-items: center;
overflow: hidden;
background-color: #FFF;
animation-name: pulse;
animation-timing-function: cubic-bezier(1,-0.42,.19,1.37);
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction:alternate-reverse;
}
@keyframes pulse {
0% {
filter: drop-shadow(0px 0px 5px #02ffee);
}
50% {
filter: drop-shadow(0px 0px 20px #f6d603);
}
100% {
filter: drop-shadow(0px 0px 40px #fb00ff52);
}
}
.main {
display: grid;
place-items: center;
position: relative;
}
.particle {
width: 50px;
height: 50px;
background-color: #76bfff;
border-radius: 50%;
opacity: 0;
position: absolute;
will-change: transform;
animation-name: absorb;
animation-timing-function: cubic-bezier(1, -0.01, .3, 1.32);
animation-iteration-count: infinite;
animation-fill-mode: backwards;
}
@keyframes absorb {
0% {
scale: 0;
opacity: 0;
}
100% {
translate: -50% -50%;
scale: var(--scale);
opacity: var(--opacity);
}
}
.robot {
animation-name: jittery;
animation-duration: .5s;
animation-iteration-count: infinite;
width: 100px;
position: absolute;
z-index: 100;
filter: drop-shadow(0px 2px 10px #666);
}
@keyframes jittery {
10% {
transform: translate(-2px, -3px) scale(1.01, 1.01);
}
20% {
transform: translate(3px, 2px) scale(.99, .99);
}
30% {
transform: translate(-4px, -5px) scale(1.01, 1.01);
}
40% {
transform: translate(2px, 3px) scale(1, 1);
}
50% {
transform: translate(-1px, -2px) scale(.98, .98);
}
60% {
transform: translate(0px, 3px) scale(1.02, 1.02);
}
70% {
transform: translate(-2px, -4px) scale(1, 1);
}
80% {
transform: translate(3px, 5px) scale(.99, .99);
}
90% {
transform: translate(-5px, -3px) scale(1.1, 1.1);
}
100% {
transform: translate(3px, 1px) scale(.95, .95);
}
}
</style>
</head>
<body>
<div class="container">
<div class="main">
<img class="robot" src="https://www.kirupa.com/icon/1f916.svg">
</div>
</div>
<template id="particlesTemplate">
<div class="particleContainer">
<div class="particle"></div>
</div>
</template>
<script>
let main = document.querySelector(".main");
let container = document.querySelector(".container");
let width = container.offsetWidth;
let height = container.offsetHeight;
let numberOfparticles = 20;
let elements = [];
function drawElements() {
let template = document.querySelector("#particlesTemplate").content;
for (let i = 0; i < 200; i++) {
let particle = template.querySelector(".particle");
let particleWrapper = template.querySelector(".particleWrapper");
setItemProperties(particle, true);
let newElement = main.appendChild(document.importNode(template, true));
}
}
drawElements();
function setItemProperties(item, initial) {
let duration = 2 + Math.random() * 4;
item.style.opacity = 0;
item.style.scale = 0;
let randomX = -1 * width + Math.random() * 2 * width;
let randomY = -1 * height + Math.random() * 2 * height;
item.style.setProperty("--scale", .1 + Math.random() * 1);
item.style.setProperty("--opacity", .1 + Math.random() * 1);
item.style.translate = `${Math.round(randomX)}px ${Math.round(randomY)}px`;
if (initial) {
item.style.animationDelay = -1 * (Math.random() * duration) + "s";
}
item.style.animationDuration = duration + "s";
}
function resetElement(event) {
if (event.target.className == "particle") {
setItemProperties(event.target, false);
}
}
window.addEventListener("animationiteration", resetElement, false);
</script>
</body>
</html>
I’ll explain more on how I created this in the future, but the above is the full code in case you want to try it out yourself!
You can also read my Twitter summary here: https://twitter.com/kirupa/status/1698528371414900823
Cheers,
Kirupa