You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:05:32