Changing the play state of the animation is causing synchronization issues with my audio

As I work on syncing a scroll effect animation in a div with an audio file, I've encountered an issue. The synchronization works perfectly when I set the element.style.animation property to 'none' when the audio is paused. However, things get tricky when I try to pause the animation instead of pausing the audio. Upon multiple pause and play actions, the animation loses its sync with the audio and ends up being too advanced.

//Here's the code snippet for handling the audio and animation synchronization:
const pupHymn = document.querySelector(".pup-hymn");
const hymnLyrics = document.querySelector(".lyrics");

const init = () => {
    pupHymn.volume = 0.3;

    pupHymn.addEventListener('play', () => {
        audioTime = pupHymn.currentTime;
        playbackRate = pupHymn.playbackRate;
        hymnLyrics.style.animation = `scroll-effect ${160/playbackRate}s ${(12-audioTime)/playbackRate}s forwards running`;
    );

    //Pausing the animation when the audio is paused
    pupHymn.addEventListener('pause', () => {
        hymnLyrics.style.animation = 'none'; 
    });

//This part works fine:
pupHymn.addEventListener('pause', () => {
        hymnLyrics.style.animation = 'none'; });
}

When I attempted to pause the animationPlayState instead of the animation, the synchronization wasn't proper especially during multiple pause and play cycles.

pupHymn.addEventListener('pause', () => {
        hymnLyrics.style.animationPlayState = 'paused'; });

I even tried logging the animation property of the div while the audio was playing, but despite the delay still being positive, the animation had already started.

Answer №1

If you're looking for a dependable method, consider using the Web Animation API. This API allows you to carefully manage the timing of your animation, ensuring precise control. By listening to events on your <audio> element and syncing its .currentTime with the Animation's time (keep in mind that one is in seconds while the other is in milliseconds), you can orchestrate a seamless animation experience.

const audio = document.querySelector("audio");
const target = document.querySelector(".content");
audio.addEventListener("loadedmetadata", (evt) => {
  const { duration } = audio;
  const keys = new KeyframeEffect(
    target,
    [{ transform: "translate(0px, -1300px)" },],
    { duration: duration * 1000, fill: "forwards" }
  );
  const anim = new Animation(keys);
  const sync = () => anim.currentTime = audio.currentTime * 1000;
  audio.addEventListener("seeked", sync);
  audio.addEventListener("play", () => {
    sync();
    anim.play();
  });
  audio.addEventListener("pause", () => {
    anim.pause();
    sync();
  });
}, { once: true });
for (let i = 0; i < 46; i++) {
  const el = document.createElement("p");
  el.textContent = i;
  target.append(el);
}
.container {
  width: 300px;
  height: 300px;
  border: 1px solid;
  overflow: hidden;
}
.content {
  height: 1600px;
  background-image: linear-gradient(to bottom, red, blue);
}
.content p {
  margin-top: 0;
}
<audio controls src="https://upload.wikimedia.org/wikipedia/en/transcoded/d/dc/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg/Strawberry_Fields_Forever_%28Beatles_song_-_sample%29.ogg.mp3"></audio>

<div class=container>
  <div class="content"></div>
</div>

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

Creating a new form upon clicking

By clicking the "Add New Job" link, a new form with three fields will appear. This is the primary form: <h2>JOB EXPERIENCE 1</h2> <div class="job-content"> <input type="text" value="Company" name="company" /> <input type="te ...

Mobile Device Centering Problem with Bootstrap Cards

Despite my thorough research efforts, I have been unable to find a solution. The code snippet below is meant to display the image provided, but it seems to shift to the left when viewed on a mobile device. If anyone can assist me with this issue, I would ...

What could be the reason for the malfunction of my for loop within my JSON operation?

Hi everyone, I'm new to coding and currently working on a project involving Twitch Viewer on FreeCodeCamp. I've managed to extract information from the JSON file and display it in my HTML code. However, I'm encountering an issue where I am ...

Extracting JSON coordinates using JavaScript

My objective is to locate the closest coordinate and arrange the cities that are nearest. In the console log, I want the output to appear like this: 8 city, 63.50590523722971; 5 city, 76.32168761236873. The coordinates seem correct, but I am struggling wit ...

Unable to display notifications within the modal using Notistack MUI in React JS

Hey there, I'm currently utilizing react in combination with MUI. To display notifications, I've integrated a library called notistack. My goal is to show an error message in a dialog if there's a failure in the API response. Here's the ...

ES6: Leveraging the power of await in conjunction with callbacks

Check out this TypeScript wrapper for vue-router: abstract class RoutingHelper { // ... public static redirectToNamedRoute(targetRouteName: AnyValueOf<typeof NamedRoutes>): Promise<void> { return new Promise<void>((resolve: () ...

A division of text is colliding with a division that holds a list with no particular

Hello everyone, I am new to HTML/CSS and I am facing an issue that I believe can be easily resolved. Currently, my code has four sections, with the last three displaying as expected in a consecutive manner. However, the second section is overlapping on t ...

What is causing the col divs to stack instead of aligning next to each other?

I am a newcomer to Vue.JS and front-end programming in general. I wanted to create a page with a fixed sidebar and content below a navbar. Here is the configuration I tried: <template> <div class="container-fluid"> <div class ...

d3: It appears that my routes are replicating themselves, and I am unable to ascertain the cause

I've been diving deep into D3, studying the works of Mike Bostock and other experts in the field. I'm also going through Scott Murray's book on Interactive Data Visualization specifically focusing on D3. At the moment, my project involves c ...

Is it possible to create a grid by arranging each statement with a specific format?

After fetching and parsing some data, I have utilized the 'each' function to display it: $.ajax({ url : 'http://ajax.googleapis.com/ajax/services/feed/load?v=1.0&num=10&callback=?&q=' + encodeURIComponent('htt ...

Utilize AngularJS to reattach a DOM node rather than simply updating it

Within my template, I have the following setup: <div> <a ng-href="tel:{{phone}}">{{ phone }}</a> </div> Angular updates the link's DOM node when $scope.phone changes, linking it to the new phone number with no issues. Ho ...

Working with Arrays in Javascript

I am relatively new to the world of JavaScript, so please be patient with me! Currently, I am retrieving data from an AWS DynamoDB using a lambda script connected to an API gateway. The JavaScript function on my page successfully issues a GET request for ...

The share-modal.js file is throwing an error because it is unable to read properties of null, particularly the 'addEventListener' property, at

I encountered an error that I want to resolve, but it's proving to be quite challenging. Despite extensive searching on Google, I haven't found a solution yet. Uncaught TypeError: Cannot read properties of null (reading 'addEventListener&apo ...

Enhance your website with a unique hover and left-click style inspired by the functionality of file explorer

I have a set of items like this: I am trying to replicate the functionality of a file explorer in terms of item selection. To clarify, I aim to create a feature where hovering over an item and left-clicking it would generate a virtual rectangle to select ...

Employing an item as a function

My query pertains to utilizing an express application object (app object) as a callback function. The express application is known for its methods and properties that aid in handling HTTP requests. When integrating the app object with an HTTP server, it se ...

Troubleshooting Karate - jbang.execute() (Node npm)

Need help with a question that's part of our project presentation. We are working on controlling the output of KARATE, ensuring it returns an OK or a KO depending on the test result. Currently, it always gives back 0 regardless of success or failure. ...

Circular Dependencies in Singletons within CommonJS Modules

I am pondering the possibility and method of achieving the following: In a CommonJS environment, using modules for both node and browser (with Browserify). I have two (or more) modules that each return a singleton object that needs to be accessed in diff ...

The concept of the "Centering Effect" refers

Check out the code I have below: http://jsfiddle.net/G8Ste/577/ I want the effect to expand in all directions, not just to the right and bottom. I've experimented with margin: 0, auto, and other CSS and HTML styles to center it, but nothing seems t ...

Storing items in a pre-save hook using Mongoose

I have files that I need to generate, but these files include links, so the structure of the file looks like this: const file = { name: 'some name', content: 'some content, type: 'file type', links: [{ path: 'some ...

Is there a way to insert a row into a datatable without needing to perform an Ajax reload or using the

When using row.add(…) on a datatable, I encounter an issue where it refreshes via an ajax call when draw() is activated. This leads to the new row not being visible because the data is reloaded from the database. The UX flow behind this scenario is as f ...