我正在将div滚动效果动画与音频同步,当音频暂停时,当我将element.style le.Animation属性设置为‘None’时,同步工作正常.问题是,当音频暂停时,我try 暂停动画.当我暂停并多次播放时,动画不再与音频同步(动画太高级了).

//This is the audio element
const pupHymn = document.querySelector(".pup-hymn");
//This is the container div of the lyrics
const hymnLyrics = document.querySelector(".lyrics");

const init = () => {
    pupHymn.volume = 0.3;
    //Sync when playing manually 
    pupHymn.addEventListener('play', () => {
        audioTime = pupHymn.currentTime;
        playbackRate = pupHymn.playbackRate;
        hymnLyrics.style.animation = `scroll-effect ${160/playbackRate}s ${(12-audioTime)/playbackRate}s forwards running`;
    );

    pupHymn.addEventListener('pause', () => {
        hymnLyrics.style.animation = 'none'; 
    });

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

但当我暂停AnimationPlayState时,当我暂停并多次播放时,它不会正确同步.

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

我已经try 在播放音频时记录div的动画属性,尽管延迟仍然是正值,但动画已经开始.

推荐答案

这里最可靠的方法可能是通过Web Animation API,它允许您以相对较高的精度管理动画的当前时间.您可以连接到<audio>元素上的一些事件,并将其.currentTime映射到Animation的事件(请注意,前者以秒为单位,而后者以毫秒为单位).

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>

Javascript相关问答推荐

带对角线分隔符的图像滑动器

为什么在react js中没有调用加载器函数?

React:未调用useState变量在调试器的事件处理程序中不可用

使用JavaScript在ionic Web应用程序中更新.pane和.view的背景 colored颜色

通过使用100%间隔时间来代表我们还剩多少时间来倒计时

从mat—country—select获取整个Country数组

基于变量切换隐藏文本

Snowflake JavaScript存储过程返回成功,尽管预期失败

当运行d3示例代码时,没有显示任何内容

用JavaScript复制C#CRC 32生成器

将现场录音发送到后端

我在Django中的视图中遇到多值键错误

正则表达式,允许我匹配除已定义的子字符串之外的所有内容

用于在路径之间移动图像的查询

如何在Svelte中从一个codec函数中调用error()?

如何在JAVASCRIPT中临时删除eventListener?

expo 联系人:如果联系人的状态被拒绝,则请求访问联系人的权限

使用Reaction窗体挂钩注册日历组件

如果对象中的字段等于某个值,则从数组列表中删除对象

select 2-删除js插入的项目将其保留为选项