Waves emanating from the heart of rings

I'm experimenting with creating a ripple effect using Anime.js on an array of dots forming circles. Despite trying various methods, I can't seem to achieve the desired result. Does anyone have any suggestions on how I can make it work?

Here's the code I've written so far. You can view the animation section at the bottom of this CodePen. I want the ripple effect to look like what's demonstrated in this example, but I'm having trouble implementing it in my current context.

var container     = document.getElementById('container');
var numberOfDots    = 512;
var numberOfCircles = 8;
var dotsPerCircle   = numberOfDots / numberOfCircles;
var circles         = [];

function createDot(i, circleDepth) {
    var rotation  = (360 / dotsPerCircle) * i;
    var height    = "calc( 30% + " + (circleDepth * 10) + "px)";
    var container = document.createElement('div');
          container.classList = 'dot';
          container.style.height = height;
          container.style.transform = 'rotate(' + rotation + 'deg) translateY(-50%)';

    var dot       = document.createElement('span');
        container.appendChild(dot);

    return container;
}

function createCircle(circleDepth) {
    var dotArray = [];
    for (var i = 1; i <= dotsPerCircle; i++) {
        var dot = createDot(i, circleDepth);
        container.appendChild(dot);
        dotArray.push(dot.querySelector('span'));
    }
    return dotArray;
}

for (var i = 1; i <= numberOfCircles; i++) {
    circles.push(createCircle(i));
}

// Animation
var duration   = 6000;
var delay      = duration / numberOfDots;
var myTimeline = anime.timeline({
    complete: function() { myTimeline.restart(); }
});
for (var i = 0; i < circles.length; i++) {
    var dotArray = circles[i];
    myTimeline.add({
        targets: dotArray,
        easing: 'easeInOutSine',
        direction: 'alternate',
        duration: duration * .1,
        scale: [
            {value: 1.6, easing: 'spring(1, 80, 10, 0)', duration: 1000},
            {value: 1, easing: 'spring(1, 80, 10, 0)', duration: 1000}
        ],
    }, "-=990")
}

https://i.sstatic.net/Y03mT.png

Answer №1

One suggestion I have is to incorporate CSS animations for a smoother and more performant effect compared to using a library like anime.js. You can create a ripple effect by animating the dots layer by layer, starting from the inner circle and moving outwards with different animation-delay properties set for each .dot element based on its position within the layers.

I believe the following implementation doesn't look too bad. It's worth noting that this solution utilizes only HTML and CSS, with JavaScript used solely for generating the HTML dynamically!

let makeRipple = (numRings=8, dotsPerRing=64, ringEndAmt=0.5, rippleMs=1000) => {
  
  // ringEndAmt: The portion of ripple filled by rings (0.5 = half the radius is empty of dots)
  // rippleMs: The amount of time between the inner layer and outer layer pulsing
  
  let ripple = document.createElement('div');
  ripple.classList.add('ripple');
  
  for (let r = 0; r < numRings; r++) { for (let d = 0; d < dotsPerRing; d++) {
    
    // `r` indexes the layer we're in, from inner to outermost
    // `d` indexes the specific dot within layer `r`
    
    let radius = 1 - ((r / numRings) * ringEndAmt);
    let angAmt = (d / dotsPerRing) * Math.PI * 2;
    
    let [ x, y ] = [ Math.cos(angAmt), Math.sin(angAmt) ].map(v => v * radius);
    
    let dot = document.createElement('div');
    dot.classList.add('dot');
    dot.style.left = `${(x + 1) * 50}%`;
    dot.style.top = `${(y + 1) * 50}%`;
    dot.style.animationDelay = `${Math.round((1 - ((r + 1) / numRings)) * rippleMs)}ms`;
    ripple.appendChild(dot);
    
  }}
  
  return ripple;
  
};

document.body.appendChild(makeRipple());
@keyframes pulseRipple {
  0%   { transform: scale(0.8); }
  12%  { transform: scale(0.8); }
  16%  { transform: scale(0.82); }
  24%  { transform: scale(0.993); }
  26%  { transform: scale(1); }
  33%  { transform: scale(0.8); }
  100% { transform: scale(0.8); }
}

@keyframes pulseDot {
  0%  { background-color: rgba(0, 150, 0, 0.1); transform: translate(0px, 0px) scale(1); }
  10% { background-color: rgba(0, 150, 0, 0.1); transform: translate(0px, 0px) scale(1); }
  20% { background-color: rgba(0, 150, 0, 0.8); transform: translate(2px, 2px) scale(2); }
  30% { background-color: rgba(0, 150, 0, 0.1); transform: translate(0px, 0px) scale(1); }
}

.ripple {
  position: relative;
  background-color: rgba(0, 150, 0, 0.02);
  border-radius: 100%;
  width: 45%; padding-bottom: 45%;
  box-shadow: 0 0 0 2px rgba(0, 150, 0, 0.02);
    
  animation-name: pulseRipple;
  animation-duration: 8000ms;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in;
}
.ripple > .dot {
  position: absolute;
  background-color: rgba(0, 150, 0, 0.1);
  width: 4px;
  height: 4px;
  margin-left: -2px; margin-top: -2px; /* Dots are centered */
  border-radius: 100%;
  
  animation-name: pulseDot;
  animation-duration: 8000ms;
  animation-iteration-count: infinite;
  animation-timing-function: ease-in-out;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is preventing Protractor from detecting Angular on a site that has been automatically initialized with Angular?

Whenever I try to utilize browser.get() in my code, I encounter the following error: Error: Angular could not be found on the page http://localhost:5000/#/login debug=timing&saveLogs=true&displayAll=true : angular never provided resumeBootstrap A ...

What is the process for assigning values once the Google Charts program has completed its drawing?

It might sound strange, but I have a piece of code here: let globalResult = []; let defaultData = ["None", 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200]; $(document).ready(() => { // add a listener to the textbox $('#in ...

Unsuccessful attempts to animate with Jquery in Google Chrome are persisting

I've been facing a challenge with my jquery code that seems to be getting the "click" function but does not animate. Instead, it just abruptly jumps without any smooth animation. I've spent hours trying to troubleshoot this issue. Here is the Jq ...

What is the best way to manage a batch of files in a response from an Ajax POST request?

Currently, I am utilizing the OGRE web client to convert GeoJSON text data into ESRI shapefiles by making a POST request with Ajax. var data = { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coord ...

Tips for locating a file using javascript

My application scans a folder and displays all folders and HTML files inside it in a dropdown menu. It also shows any HTML files inside an iframe. There is one file named "highlighted.html" that should not appear in the dropdown menu, but if it exists in t ...

Prevented: Techniques for providing extra cushioning for a button, but with the condition that it contains an external icon

How can I apply padding to a button only if it contains an external icon? If the button has an external icon, I want to give it padding-right: 30px (example). However, if there is no external icon present, then the button should not have the 30px padding. ...

New React Component Successfully Imported but Fails to Render

I've encountered issues with the code I'm currently working on. Dependencies: React, Redux, Eslinter, PropTypes, BreadCrumb Within a view page, I am importing components from other files. The current structure is as follows: import Component ...

I am seeking to incorporate several Three.js animations into my HTML document, but I am experiencing issues with them

As a professional graphic designer, I am facing an issue with Three.js https://i.sstatic.net/6ZsWa.jpg I have tried several solutions, but none seem to work effectively. In my attempt, I duplicated the imported model and changed its name. Despite trying ...

What is the best way to check if a function has been successfully executed?

When working with PDF documents, I often use an instance of pdfkit document known as doc: import PDFDocument from 'pdfkit' const doc = new PDFDocument() This doc instance is then passed into a function called outputTitle: export const outputTi ...

Enhancing live query functionality and providing a substitute for DOMNodeInserted specifically tailored for

I have searched multiple times on various platforms for a solution to my specific issue, but have not found one that fits my unique circumstances. My goal is to replace outdated code such as livequery and DOMNodeInserted. See examples below. I am current ...

What could be the reason behind the child component updating without triggering a re-render in Reactjs?

I am encountering an issue with my main component and child chart component. Even though the main component updates the state of the child chart component upon connecting to a websocket, the chart does not redraw as expected. Interestingly, when I click on ...

How can I trigger a CSS animation to replay each time a button is clicked, without relying on a timeout function?

I am having trouble getting a button to trigger an animation. Currently, the animation only plays once when the page is refreshed and doesn't repeat on subsequent clicks of the button. function initiateAnimation(el){ document.getElementById("anima ...

Implementing pagination in a Node.js application using MongoDB.ORCreating

function implementPaginationForDigitalMigrationJoin(req, res, next) { DigitalMigrationForm.aggregate([ // Join with user_info table { $lookup: { from: DigitalMigrationFormList.collection.name, // other ...

Encountering a circular structure while attempting to convert to JSON -- starting at an object created by the 'HTMLInputElement' constructor

I have been trying multiple solutions to fix this issue, but I'm still struggling to resolve it. My application is built using Next.js and I am using axios as the HTTP client. import React, {useState} from 'react' import axios from 'axi ...

Having difficulty maintaining trailing zeroes in decimals after converting to float in Angular

I need assistance with converting a string to float in Angular. Whenever I use parseFloat, it seems to remove the zeros from the decimal values. How can I ensure that these zeros are retained with the numerical values? The example below should provide more ...

Wordpress causing Jquery to malfunction; PHP function not executing

Looking to incorporate a script into my WordPress function.php file. Here's what I have so far: <?php function add_google_jquery() { if ( !is_admin() ) { wp_deregister_script('jquery'); wp_register_script('jquery', ...

Creating dynamic cubes in Magento with interact.js within a .phtml template

I utilized the interact.js library to create this code snippet, which functions perfectly on Chrome, Firefox, and w3schools "Try it Yourself" platform (unfortunately not compatible with Edge and IE for unknown reasons). However, when I include this code wi ...

Clicking on the image in the Swiper Slider will update the URL

Hi there! I am looking for help with changing the image URL when clicked. Currently, I am using swiper for my image gallery. I want to change this URL: to If anyone has a solution or suggestion on how I can achieve this, please let me know! ...

Using jQuery in Yii: Detecting when a radio button loses its checked state

Here is the code regarding the issue at hand: <script> $(function(){ $('#widgetId-form input[name="valueType"]').change(function(){ if ($(this).is(":checked")) { console.log("enabling "+$(this).data("class") ...

The React-Leaflet curly braces positioned on the top left corner of the map

Is there a way to remove the curly braces and symbols near the zoom pane when the map is too far? https://i.stack.imgur.com/eGQCd.png p.s. Here is some provided code for reference: p.s. 2 - I have noticed that adding a condition like {condition1 &a ...