Aside from some basic transitions, i'm pretty much a novice when it comes to animations in css/JS. For a Project that starts next week, i have commited to a specific animation that i find somewhat challenging. Here's the Animation explained:
- There should be 10-30 Images that rotate/circulate around a Ring/circle.
- The Images should also randomly have a small offset away from the Ring, as to give a "scattered" effect
- The Images should be spread around the ring to "fill" it.
- The Images should have a "bounce" effect or similar
Image of what i'd hope to achieve:

What i've tried so far: I've been researching some JS Libraries for Animations. Those that stood out to me were animeJS (https://animejs.com/) and MoJS (https://mojs.github.io/). I've decided to test out AnimeJS.
Here is a CodePen: CodePen
const imgContainer = document.getElementById("imgContainer");
const svgContainer = document.getElementById("svgContainer");
const imgURL =
"https://images.unsplash.com/photo-1678833823181-ec16d450d8c1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=774&q=80";
function generateCircleWithRandomSizes(index) {
const randomSize = generateRandomNumberBetween(450, 520);
return `<div class="svgWrapper">
<svg width="${randomSize}" height="${randomSize}" fill="none" stroke="none" id="svgContainer">
<path id="path${index + 1}" fill="none" d="
m ${(800 - randomSize) / 2}, ${800 - randomSize}
a 1,1 0 1,1 ${randomSize},0
a 1,1 0 1,1 -${randomSize},0
" />
</svg>
</div>`;
}
function generateRandomNumberBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
for (let i = 0; i < 30; i++) {
imgContainer.innerHTML += `<img class="image" id="img${i + 1}" src="${imgURL}" />`;
svgContainer.innerHTML += generateCircleWithRandomSizes(i);
let path = anime.path(`#path${i + 1}`);
anime({
targets: `#img${i + 1}`,
translateX: path("x"),
translateY: path("y"),
easing: "linear",
duration: 10000,
loop: true
});
}
Here's the approach i'm currently trying, but as the CodePen shows, i'm running into multiple issues. I'm generating as many Circles as i have images and want target 1 Image per Path. This approach would give me the scattered effect i'm trying to get. However, as you can see, it seems that animeJS only animates one of the Images, and that it seems to follow the path, but offset to the top left. I'm assuming this has something to do with my CSS and how i "center" SVG/Path, which ultimately shows another issue i have. I'm not quite sure how to dynamically generate theses rings and always center them.
I'm having a bit of a hard time to put my finger on how to best solve this. Am i using the best library for this use case? Do i even need a library? Should i got at it from a completely different angle?
I'd really love to get some help on this.
You current anime.js code only animates the last element as you're breaking the previous element bindings by using
innerHTML().As an alternative you could use
insertAdjacentHTML()as explained here "Is it possible to append to innerHTML without destroying descendants' event listeners?"Example: anime.js
Alternative: SVG SMIL
<AnimateMotion>In this example you could append your images as
<image>elements to your<svg>element.The path offset can be achieved by a negative
beginvalue.As explained here "Offseting animation start point for SVG AnimateMotion".
Alternative 2:
offset-pathDisclaimer: Currently not fully implemented by a lot of browsers (especially webkit /safari).
Hopefully, we see better support in the near future. The main benefits:
offset-distanceproperty.