基于jQuery的音频播放器Range Slider在Chrome中失效求助
修复MP3播放器进度滑块在Chrome中失效的问题
问题根源分析
Chrome对NaN值的处理比Firefox更严格:当音频未加载完成时,track.duration会返回NaN,直接用它计算滑块值会导致滑块失效;另外代码中还存在未声明变量、重复创建定时器、索引越界等隐性问题,进一步加剧了异常。
具体修复方案
1. 避免NaN导致的滑块异常
在更新滑块的range_slider函数中,先判断音频时长是否有效,再执行后续计算:
function range_slider() { // 音频未加载完成时直接返回 if (isNaN(track.duration) || track.duration <= 0) return; let current_time = Math.floor(track.currentTime); let duration = Math.floor(track.duration); let minutes = Math.floor(current_time / 60); let seconds = current_time % 60; let total_minutes = Math.floor(duration / 60); let total_seconds = duration % 60; // 补零优化,让时间显示更规范 seconds = seconds < 10 ? `0${seconds}` : seconds; total_seconds = total_seconds < 10 ? `0${total_seconds}` : total_seconds; show_duration.innerHTML = `${minutes}:${seconds} / ${total_minutes}:${total_seconds}`; slider.value = (current_time / duration) * 100; }
2. 修复未声明变量与重复定时器问题
在拖动滑块跳转进度的change_duration函数中,声明局部变量并移除重复创建的定时器(load_track中已创建定时器,无需重复添加):
function change_duration() { if (isNaN(track.duration) || track.duration <= 0) return; let slider_position = track.duration * (slider.value / 100); // 声明局部变量避免全局污染 track.currentTime = slider_position; }
3. 等待音频加载完成后再启动定时器
在load_track函数中,监听音频的loadedmetadata事件,确保获取到有效时长后再更新滑块:
function load_track(index_no) { clearInterval(timer); reset_slider(); track.src = All_song[index_no].path; title.innerHTML = All_song[index_no].name; track_image.src = All_song[index_no].img; artist.innerHTML = All_song[index_no].singer; track.load(); // 等待音频元数据加载完成后启动定时器 track.addEventListener('loadedmetadata', function() { timer = setInterval(range_slider, 500); }); total.innerHTML = All_song.length; present.innerHTML = index_no + 1; }
4. 修复上一曲函数的索引越界问题
原代码中previous_song函数最后会设置index_no = All_song.length,导致索引越界,修正为:
function previous_song() { if (index_no > 0) { index_no -= 1; load_track(index_no); playsong(); } else { index_no = All_song.length - 1; // 定位到最后一首 load_track(index_no); playsong(); } }
5. 修正静音函数的变量错误
原代码中静音函数误用了未定义的volume变量,替换为声明过的recent_volume:
function mute_sound() { track.volume = 0; recent_volume.value = 0; volume_show.innerHTML = 0; }
完整修复后的代码
JavaScript代码
let previous = document.querySelector('#pre'); let play = document.querySelector('#play'); let next = document.querySelector('#next'); let title = document.querySelector('#title'); let recent_volume = document.querySelector('#volume'); let volume_show = document.querySelector('#volume_show'); let slider = document.querySelector('#duration_slider'); let show_duration = document.querySelector('#show_duration'); let track_image = document.querySelector('#track_image'); let auto_play = document.querySelector('#auto'); let present = document.querySelector('#present'); let total = document.querySelector('#total'); let artist = document.querySelector('#artist'); let timer; let autoplay = 0; let index_no = 0; let Playing_song = false; // 创建音频元素 let track = document.createElement('audio'); // 歌曲列表 let All_song = [{ name: "{{ $data->name }}", path: "{{ asset('assets/' . $data->file) }}", img: "/assets/images/quran.jpg", singer: "{{ $data->description }}" }]; // 加载曲目 function load_track(index_no) { clearInterval(timer); reset_slider(); track.src = All_song[index_no].path; title.innerHTML = All_song[index_no].name; track_image.src = All_song[index_no].img; artist.innerHTML = All_song[index_no].singer; track.load(); // 等待元数据加载完成后启动定时器 track.addEventListener('loadedmetadata', function() { timer = setInterval(range_slider, 500); }); total.innerHTML = All_song.length; present.innerHTML = index_no + 1; } load_track(index_no); // 静音函数 function mute_sound() { track.volume = 0; recent_volume.value = 0; volume_show.innerHTML = 0; } // 播放/暂停切换 function justplay() { if (Playing_song === false) { playsong(); } else { pausesong(); } } // 重置滑块 function reset_slider() { slider.value = 0; } // 播放歌曲 function playsong() { track.play(); Playing_song = true; play.innerHTML = '<i class="fa fa-pause" aria-hidden="true"></i>'; } // 暂停歌曲 function pausesong() { track.pause(); Playing_song = false; play.innerHTML = '<i class="fa fa-play" aria-hidden="true"></i>'; } // 下一曲 function next_song() { if (index_no < All_song.length - 1) { index_no += 1; load_track(index_no); playsong(); } else { index_no = 0; load_track(index_no); playsong(); } } // 上一曲 function previous_song() { if (index_no > 0) { index_no -= 1; load_track(index_no); playsong(); } else { index_no = All_song.length - 1; load_track(index_no); playsong(); } } // 音量调节 function volume_change() { volume_show.innerHTML = recent_volume.value; track.volume = recent_volume.value / 100; } // 拖动滑块跳转进度 function change_duration() { if (isNaN(track.duration) || track.duration <= 0) return; let slider_position = track.duration * (slider.value / 100); track.currentTime = slider_position; } // 自动播放开关 function autoplay_switch() { if (autoplay === 1) { autoplay = 0; auto_play.style.background = "rgba(255,255,255,0.2)"; } else { autoplay = 1; auto_play.style.background = "#FF8A65"; } } // 更新滑块与时间显示 function range_slider() { if (isNaN(track.duration) || track.duration <= 0) return; let current_time = Math.floor(track.currentTime); let duration = Math.floor(track.duration); let minutes = Math.floor(current_time / 60); let seconds = current_time % 60; let total_minutes = Math.floor(duration / 60); let total_seconds = duration % 60; // 补零处理 seconds = seconds < 10 ? `0${seconds}` : seconds; total_seconds = total_seconds < 10 ? `0${total_seconds}` : total_seconds; show_duration.innerHTML = `${minutes}:${seconds} / ${total_minutes}:${total_seconds}`; slider.value = (current_time / duration) * 100; }
HTML代码
<div class="duration"> <input type="range" min="0" max="100" value="0" id="duration_slider" onchange="change_duration()"> </div>
内容的提问来源于stack exchange,提问作者Stack Overflow
相关产品推荐
相关产品推荐

