浅谈javascript的事件监听——音乐播放器的控制

javascript的事件

javascript是一门基于事件驱动的语言,当html页面中的元素触发一些动作时,可以执行相关的js代码。

1.常见事件
  • 浏览器窗体事件

    事件名描述
    onload当窗体内容被加载时触发
    onunload当窗体中内容卸载时触发
    onbeforeunload当窗体内容被卸载之前触发
    onresize当窗体大小被改变时出发
  • 鼠标事件

    事件名描述
    onclick当鼠标单击时触发
    ondblclick当鼠标双击时触发
    onmouseover当鼠标悬停到元素上时触发
    onmouseout当输入从元素中移出时触发
    onmouseenter当鼠标进入时触发
    onmouseleave当鼠标离开时触发
    onmousedown当鼠标按下时触发
    onmouseup当鼠标抬起时触发
  • 键盘事件

    事件名描述
    onkeydown当键盘按键被按下时触发
    onkeyup当键盘按键抬起触发
    onkeypress当键盘按键被按压时触发
  • 表单事件

    事件名描述
    onchange当控件内容改变时触发
    onselect当控件内容被选中时触发
    onblur当控件失去焦点时触发
    onfocus当控件获得焦点时触发
    onreset表单重置时触发
    onsubmit表单提交时触发
2.事件绑定与移除
事件绑定

javascript为元素绑定事件分为两种方式:

  1. 直接在html中为元素设置相关的事件属性;
  2. 在javascript中通过dom对象获取目标元素之后为其设置事件属性;
//绑定指定名称的函数
div.onclick=fun;
function fun(){
    //执行体
}

//绑定匿名函数
div.onclick=function(){
 	//执行体   
}
  1. 在js中获取dom之后使用addEventListener函数绑定指定事件。
div.addEventListener('click',fun)
function fun(){
    //执行体
}

div.addEventListener('click',function(){
    //执行体
})
解除绑定

对于使用addEventListener绑定的事件fun,可以通过removeEventLitener解除:

div.removeEventListener('click',fun);

对于解除绑定,只能解除指定元素中被绑定的回调函数对象(函数指针必须是一致的)

3.事件冒泡与事件捕获以及阻止事件传播
事件冒泡

事件冒泡,即对内层元素触发事件时,逐级向外传播,导致外层事件逐步执行。

事件捕获

事件捕获即由外向内逐层捕获。需要将事件冒泡机制切换为事件捕获,只需要在为元素通过:e.addEventListene(事件名,回调函数,是否捕获)。

阻止事件传播

由于事件流的传播性,实际开发中这些特性会影响程序的事件处理,因此需要对事件传播进行阻止,如果需要阻止事件的传播,只需要在指定元素的触发时调用事件对象提供的stopPropergation()函数或者设置cancelBubble为true即可:

 		//分别获取三个div元素并绑定点击事件
        //事件冒泡:从内层->外层 默认
        //事件捕获:从外层->内层 加true参数
        document.getElementById('box1').addEventListener('click',function (e) {
            console.log('外层盒子');
            //阻止时间传播
            // e.stopPropagation();
            e.cancelBubble = true;
        });
        document.getElementById('box2').addEventListener('click',function (e) {
            console.log('中层盒子');
            e.cancelBubble = true;
        });
        document.getElementById('box3').addEventListener('click',function (e) {
            console.log('内层盒子');
            e.stopPropagation();
        });

音乐播放器中的相关事件

html主要布局:

 <!-- 底部歌曲播放控制,音量,进度等 -->
        <div class="play-bottom">

            <!-- 播放控制 -->
            <div class="play-control">
                <a href="javascript:;" class="btn-pre"></a>
                <a href="javascript:;" class="btn-play" id="btnPlay"></a>
                <a href="javascript:;" class="btn-next"></a>
            </div>

            <!--播放进度控制-->
            <div class="progress-info">
                <div class="play-info">
                    <a href="" id="playingName">XX</a>
                </div>
                <div class="play-length">
                    <div class="play-current">01:10</div>
                    <!-- 进度条 -->
                    <div class="play-progress">
                        <div class="play-panel"></div>
                        <div class="progress-control">
                            <div class="dot"></div>
                        </div>
                    </div>
                    <div class="play-duration">05:22</div>
                </div>
            </div>

            <!-- 声音控制 -->
            <div class="play-volume">
                <div class="volume-icon">
                </div>
                <div class="volume-wrap">
                    <div class="volume-panel"></div>
                    <div class="volume-control">
                        <a href="" class="dot"></a>
                    </div>
                </div>    
            </div>
        </div>

数据:

var musics = [
    {
        ablum: "xxx",
        artist: "GALA ",
        id: 2,
        name: "追梦赤子心",
        path: "musics/1592373330188.mp3",
        size: 8357216,
        style: "摇滚",
        uptime: 1592373330000
    },
    {
        ablum: "xxx",
        artist: "Bruno Mars ",
        id: 4,
        name: "Just The Way You Are",
        path: "musics/1592383891287.mp3",
        size: 3602925,
        style: "摇滚",
        uptime: 1592383891000
    }]

添加相关事件

//创建音频播放器对象
var player = document.createElement('audio');
//记录正在播放的歌曲的索引
var currentIndex = 0;
//声明标记,记录歌曲的播放状态(是否播放)
var isplay = false;

//自调用函数绑定列表数据(并动态绘制歌曲列表)
((function() {
    //绑定数据到页面中
    var html ='';
    //循环遍历歌曲列表,根据歌曲数目在页面中生成对应的html代码
    for (var i = 0; i < musics.length; i++) {
        var m = musics[i];
        //根据循环的次数创建对应的歌曲信息
        html += `<tr class="music-item" data-index="${i}">
                <td class="tb-space" style="text-align: center"></td>
                <td><a href="javascript:;">${m.name}</a></td>
                <td><a href="javascript:;">${m.artist}</a></td>
                <td><a href="javascript:;">${m.ablum}</a></td>
                <td>${fmtsize(m.size)}</td>
                <td class="tb-space"></td>
             </tr>`;
    }
    //将生成的html代码插入到指定的dom节点
    document.getElementById('tbody').innerHTML = html;
    //初始化播放源
    player.src = musics[currentIndex].path;
})());

//为列表项触发点击事件
var trs = document.querySelectorAll('.music-item');
for (var i = 0; i < trs.length; i++) {

    trs[i].addEventListener('click',function() {
        clearStatus();
        //获取元素上data-index属性的属性值(获取需要播放的歌曲列表项)
        var index = this.dataset.index;
        //记录正在播放的歌曲
        currentIndex = index;
        //获取需要播放的歌曲对象
        var m = musics[index];
        //为播放器设置播放源
        player.src = m.path;
        //开始播放
        startPlay();
    });

    //使用函数闭包的方式获取点击的列表索引
    // trs[i].addEventListener('click',(function (index) {
    //     return function () {
    //         alert(index);
    //     }
    // })(i))
}

//清除上一首正在播放的状态
function clearStatus() {
    //还原上一首正在播放歌曲的列表项背景
    trs[currentIndex].style.backgroundColor = '';
    //清除当前行下的第一个单元格内容(清除图标)
    trs[currentIndex].getElementsByTagName('td')[0].innerHTML = '';
}

//播放
function startPlay() {
    //标记状态为正在播放
    isplay = true;
    //播放
    player.play();
    //修改当前正在播放的歌曲所在列表项的背景色
    trs[currentIndex].style.backgroundColor = '#f0f0f0';
    //清除当前行下的第一个单元格内容(清除图标)
    // this.querySelector('td:nth-child(1)');
    trs[currentIndex].getElementsByTagName('td')[0].innerHTML = '<img src="imgs/playing-list.gif">';
    // 将播放按钮的背景图片设为暂停
    document.getElementById('btnPlay').className = 'btn-pause';
    //将正在播放的歌曲信息显示在底部控制区域
    document.getElementById('playingName').innerText = musics[currentIndex].name;
}

//暂停
function pausePlay(){
    //将播放状态标记为false
    isplay = false;
    //暂停播放
    player.pause();
    //将当前播放按钮的类名称修改
    document.getElementById('btnPlay').className = 'btn-play';
}

//播放控制
document.getElementById('btnPlay').addEventListener('click',function () {
    if(isplay){
        //暂停
        pausePlay();
    }else{
        //播放
        startPlay();
    }
});

//记录歌曲的当前播放时间
var now = 0;
//记录歌曲的总播放时间
var total = 0;
//当播放器数据被加载时触发
player.addEventListener('loadeddata',function () {
   //获取当前播放器的播放位置和总播放时长
    now = player.currentTime;
    total = player.duration;
    //将歌曲的播放时间显示在控制区域
    document.querySelector('.play-current').innerText = fmtTime(now);
    document.querySelector('.play-duration').innerText = fmtTime(total);
});

//为播放器绑定播放进度改变事件
player.addEventListener('timeupdate',updateProgress);
function updateProgress() {
    //获取最新的播放进度
    now = player.currentTime;
    //计算进度百分比
    var p = now / total * 100 + '%';
    document.querySelector('.progress-control').style.width = p;
    //更新播放时间
    document.querySelector('.play-current').innerText = fmtTime(now);
}

//播放完成事件
player.addEventListener('ended',function () {
    //清除上一首播放状态
    clearStatus();
    currentIndex++;
    if(currentIndex >= musics.length){
        currentIndex = 0;
    }
    //为播放器设置播放源
    player.src = musics[currentIndex].path;
    //开始播放
    startPlay();
});

//上一曲事件
document.querySelector('.btn-pre').addEventListener('click',function () {
    //清除上一首播放状态
    clearStatus();
    currentIndex--;
    if(currentIndex <= 0){
        currentIndex = musics.length - 1;
    }
    //为播放器设置播放源
    player.src = musics[currentIndex].path;
    //开始播放
    startPlay();
});

//下一曲事件
document.querySelector('.btn-next').addEventListener('click',function () {
    //清除上一首播放状态
    clearStatus();
    currentIndex++;
    if(currentIndex >= musics.length){
        currentIndex = 0;
    }
    //为播放器设置播放源
    player.src = musics[currentIndex].path;
    //开始播放
    startPlay();
});

// 滑动进度条改变歌曲播放进度
(function(box,bar) {
    //标记鼠标是否按下
    var status = false;

    //鼠标按下监听事件
    document.querySelector(box).addEventListener('mousedown',function (e) {
        //解除播放器时间更新事件
        player.removeEventListener('timeupdate',updateProgress);
        move(e);
    });

    //鼠标抬起监听事件
    document.querySelector(box).addEventListener('mouseup',function () {
        //播放进度更新
        player.currentTime = now;
        //重新绑定播放器时间更新事件
        player.addEventListener('timeupdate',updateProgress);
        //标记鼠标抬起
        status = false;
    });

    //鼠标移动监听事件
    document.querySelector(box).addEventListener('mousemove',function (e) {
        if(status){
            move(e);
        }
    });

    //滑块移动
    function move(e){
        //点击事件与左边缘的距离
        var eventLeft = e.offsetX;
        // 更新进度条位置
        document.querySelector(bar).style.width = eventLeft+'px';
        // 获取进度条总长度
        var w =  window.getComputedStyle(document.querySelector(box)).width;
        //获取播放器当前所在位置
        now = eventLeft / parseInt(w) * total;
        //设置鼠标状态为按下
        status = true;
    }
})('.play-length','.progress-control');//参数为可触发事件的进度条所在盒子类,进度条类

//格式化歌曲的播放时间
function fmtTime(time) {
    //秒转化为毫秒
    time *= 1000;
    //使用毫秒数构建一个日期对象
    time = new Date(time);
    var min = time.getMinutes();
    var sec = time.getSeconds();
    min = min < 10? '0'+ min:min;
    sec = sec < 10? '0'+ sec:sec;
    return min+':'+sec;
}

//格式化歌曲大小
function fmtsize(size) {
    size = size / (1024 * 1024);
    size = size.toFixed(1);
    return size + 'MB';
}

总结

  1. js语法相对灵活,而结合html+css+js可以完成许多的操作,前两者使得界面更加美观,而后者使得界面具备一些功能。
  2. 当然,在当前的一些主流框架的使用,使得js语法更加简单,学会后使用也更加方便;其底层一样通过原生js实现理解这些,对jQuery等框架的使用会更加得心应手。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值