试图解决这个问题几个小时,我似乎无法找到解决方案。
基本上,我有一个使用HTML5的音频播放器。 音频播放时有一个事件监听器,每隔一秒触发一次,直到音频结束。
我根据API提供的时间戳在音频时间轴上生成标记,它看起来像这样。
此处有三个标记 - 如果总持续时间为60秒,我认为标记为5,10,29。
在每个标记之后,我需要从DOM上的API更改图像和段落文本,并使用jquery来执行此操作。
在#time; timeupdate'监听器,我有一个for循环,它遍历DOM上的每个标记,然后检查' currentTime' Audio对象的值小于' timestamp'。
audioObject.addEventListener('timeupdate', () =>
{
for (let i = 0; i < $(options.markers).length; i++)
{
// If the current time of the audio is greater than the first timestamp second, continue
if (options.audioObject.currentTime > options.podcastData[i].timestamp)
{
options.coverImage.attr('src', options.podcastData[i].image);
options.theTitle.text(options.podcastData[i].name)
}
}
}, false)
现在这样可行,但它每秒更新一次DOM,所以我看到Inspector Element上的闪烁,直到播客完成。
我需要的是只有在经过标记后才更新DOM一次,但目前我似乎找不到办法来做到这一点。
答案 0 :(得分:1)
我做了两处修改:
for (let i = $(options.markers).length - 1; i >= 0; i--)
{
if (options.audioObject.currentTime > options.podcastData[i].timestamp)
{
if (! options.podcastData[i].seen)
{
options.coverImage.attr('src', options.podcastData[i].image);
options.theTitle.text(options.podcastData[i].name)
options.podcastData[i].seen = true
}
break
}
}
答案 1 :(得分:1)
每次事件触发时,您总是遍历整个标记列表,这意味着您将始终显示过去发生过的标记数据,并且之前已显示过。在您的示例中,在音频文件中29秒后,您将显示来自标记的数据,该数据以5秒的间隔以5秒的间隔发生,在此之后的每个间隔,标记在10秒处10秒间隔和之后的每个间隔和标记在29秒一次。每当您的事件发生时,您实际上都会显示并覆盖timestamp
符合timestamp
一个接一个的所有其他标记的每个标记。
如果您在阵列显示后从阵列中删除标记怎么办?一旦标记过去并且您更新了图像和标题,您就不需要在音频文件进展时再次显示它,因为您已经拥有(如果这样做,您可以随时恢复数组的缓存副本)标记,比方说,如果用户倒回流,如果可能的话。)
audioObject.addEventListener('timeupdate', () => {
for (let i = 0; i < $(options.markers).length; i++)
{
// If the current time of the audio is greater than the first timestamp second, continue
if (options.audioObject.currentTime > options.podcastData[i].timestamp)
{
options.coverImage.attr('src', options.podcastData[i].image);
options.theTitle.text(options.podcastData[i].name)
// *** We've displayed this marker. No need to display it the next
// time this event fires!
options.markers = options.markers.splice(i, 1);
}
}
}, false)
这样,每次事件发生时,您都不会经常显示旧标记的数据(然后使用其他标记的数据覆盖它们,等等)。
答案 2 :(得分:0)
尝试这样的事情:
if (options.theTitle.text()!=options.podcastData[i].name) options.theTitle.text(options.podcastData[i].name);
如果当前内容与您要显示的内容不同,则应仅更新内容。您可以使用与图像类似的语法,但我不想冒险键入它而不进行测试,我现在无法测试。