vue+element制作音乐播放器播放进度条bug(鼠标拖拽slider滑块滑动到指定位置无效)

news/2024/7/10 1:29:40 标签: vue, bug, javascript, js, elementui

bug_0">最开始bug还没解决时的效果图

在这里插入图片描述

bug_3">bug解决后的效果图

在这里插入图片描述

项目场景:

想自己做一个基于vue仿网易云音乐的音乐网站,在制作播放器的时候用到了element ui里面的slider组件,制作完成后发现使用change的方法无法达到我需要的效果,上网查询发现没有好的方案,后面自己琢磨后发现解决方案

问题描述:

在进度条制作完成以后,发现可以通过点击定位到进度条相应的位置,但是在用鼠标拖拽进度条时有时候会失败(在拖拽时间超过1s时),达不到那种可以通过点击跳转到指定区域的功能,并且在鼠标滑动时,进度条依旧在变化。
template:

<audio :src="musicUrl" autoplay class="playMusicAudio" ref="audio" @canplay="getDuration" @timeupdate="durationUpdate"></audio>
<!-- 播放进度条 -->
        <span style="position: absolute;right: 72%;bottom: 14%;">{{this.musicDuration | timeFormat}}</span>
        <div id="playSlider">
            <el-slider v-model="musicDuration" :max="musicAllDuration" :show-tooltip="false" @change="changeMusicDuration"></el-slider>
        </div>
        <span style="position: absolute;left: 72%;bottom: 14%;">{{this.musicAllDuration | timeFormat}}</span>

data:

data() {
            return {
                // 判断当前是否在播放
                isPlaying: false,
                //判断播放顺序模式
                playOrd: 0,
                //歌曲总时长
                musicAllDuration: 0,
                // 歌曲当前时长
                musicDuration: 0,
            }
        },

methods:

			//获得播放歌曲总时长
            getDuration() {
                this.musicAllDuration = this.$refs.audio.duration
            },
            //更新当前时长
            durationUpdate() {
                this.musicDuration = this.$refs.audio.currentTime
            },
            //鼠标拖拽松开时
            changeMusicDuration() {
                if (this.musicAllDuration === 0) return
                this.$refs.audio.currentTime = this.musicDuration
            },

原因分析:

在这里插入图片描述

由于我设置当前时长是随着audio的更新而赋值达到实时更新的,而element的slider的change方法是在鼠标松开后才会触发,这就会导致在拉动的时候鼠标还没松开达到赋值给当前时长前,audio的timeupdata方法就再次触发了,这时再松开鼠标,change方法里面赋予的值就不是鼠标拖拽到的指定进度,而是audio的timeupdate方法赋值给当前时长的进度值。


解决方案:

在鼠标按下时把audio的timeupdate方法禁止掉,在松开的时候再触发,但是没有方法能在一个事件里面禁止掉另一个事件,所以添加一个判断是否在拖拽状态的属性,来达到鼠标按下时timeupdate禁止掉的功能。
附上代码:
template:

<audio :src="musicUrl" autoplay class="playMusicAudio" ref="audio" @canplay="getDuration" @timeupdate="durationUpdate"></audio>
<!-- 播放进度条 -->
        <span style="position: absolute;right: 72%;bottom: 14%;">{{this.musicDuration | timeFormat}}</span>
        <div id="playSlider">
            <el-slider v-model="musicDuration" :max="musicAllDuration" :show-tooltip="false" @change="changeMusicDuration" @mousedown.native="isChange = true" @mouseup.native="isChange = false"></el-slider>
        </div>
        <span style="position: absolute;left: 72%;bottom: 14%;">{{this.musicAllDuration | timeFormat}}</span>

data:

data() {
            return {
                // 判断当前是否在播放
                isPlaying: false,
                //判断播放顺序模式
                playOrd: 0,
                //歌曲总时长
                musicAllDuration: 0,
                // 歌曲当前时长
                musicDuration: 0,
                //判断是否被拖动
                isChange: false
            }
        },

methods:

			//获得播放歌曲总时长
            getDuration() {
                this.musicAllDuration = this.$refs.audio.duration
            },
            //更新当前时长
            durationUpdate() {
                if (this.isChange === true) return
                this.musicDuration = this.$refs.audio.currentTime
            },
            //鼠标拖拽松开时
            changeMusicDuration() {
                if (this.musicAllDuration === 0) return
                this.$refs.audio.currentTime = this.musicDuration
                this.isChange = false
            },

附上播放器组件的代码(不完整,播放器还没有制作完成,后续会修改播放条样式和歌曲封面等细节):

	<template>
    <div class="musicPlay">
        <audio :src="musicUrl" autoplay class="playMusicAudio" ref="audio" @canplay="getDuration" @timeupdate="durationUpdate"></audio>
        <div id="audioFunc">
            <!-- 播放顺序 -->
            <div @click="changeOrd">
                <el-tooltip class="item" effect="light" content="顺序播放" placement="top" :open-delay="500">
                    <div id="playOrd" v-show="playOrd === 0"><i class="iconfont icon-liebiaoshunxu" style="font-size: 18px;"></i></div>
                </el-tooltip>
                <el-tooltip class="item" effect="light" content="列表循环" placement="top" :open-delay="500">
                    <div id="playOrd" v-show="playOrd === 1"><i class="iconfont icon-liebiaoxunhuan" style="font-size: 18px;"></i></div>
                </el-tooltip>
                <el-tooltip class="item" effect="light" content="单曲循环" placement="top" :open-delay="500">
                    <div id="playOrd" v-show="playOrd === 2"><i class="iconfont icon-danquxunhuan" style="font-size: 18px;"></i></div>
                </el-tooltip>
                <el-tooltip class="item" effect="light" content="随机播放" placement="top" :open-delay="500">
                    <div id="playOrd" v-show="playOrd === 3"><i class="iconfont icon-suijibofang" style="font-size: 18px;"></i></div>
                </el-tooltip>
            </div>
            <!-- 上一首歌曲 -->
            <div id="backSong"><i class="iconfont icon-shangyishou" style="font-size: 18px;"></i></div>
            <!-- 播放与暂停 -->
            <div>
                <div id="pause" v-show="isPlaying" @click="pauseSong"><i class="iconfont icon-zanting" style="font-size: 18px;"></i></div>
                <div id="play" v-show="!isPlaying" @click="playSong"><i class="iconfont icon-bofang" style="font-size: 30px;"></i></div>
            </div>
            <!-- 下一首歌曲 -->
            <div id="nextSong"><i class="iconfont icon-xiayishou" style="font-size: 18px;"></i></div>
            <!-- 歌词 -->
            <div id="album"><span style="font-size: 15px;"></span></div>
        </div>
        <!-- 播放进度条 -->
        <span style="position: absolute;right: 72%;bottom: 14%;">{{this.musicDuration | timeFormat}}</span>
        <div id="playSlider">
            <el-slider v-model="musicDuration" :max="musicAllDuration" :show-tooltip="false" @change="changeMusicDuration" @mousedown.native="isChange = true" @mouseup.native="isChange = false"></el-slider>
        </div>
        <span style="position: absolute;left: 72%;bottom: 14%;">{{this.musicAllDuration | timeFormat}}</span>
    </div>
</template>

<script>
    export default {
        name: 'musicPlay',
        props: {
            musicUrl: String
        },
        components: {},
        data() {
            return {
                // 判断当前是否在播放
                isPlaying: false,
                //判断播放顺序模式
                playOrd: 0,
                //歌曲总时长
                musicAllDuration: 0,
                // 歌曲当前时长
                musicDuration: 0,
                //判断是否被拖动
                isChange: false
            }
        },
        methods: {
            // 播放音乐
            playSong() {
                if (!this.musicUrl) {
                    const h = this.$createElement;
                    this.$message.error({
                        message: h('p', null, [
                            h('span', null, '列表中没有可播放的歌曲'),
                            h('i', {
                                style: 'color: red'
                            }, '')
                        ]),
                        offset: 280,
                        center: true,
                        showClose: true
                    });
                    return
                }
                this.isPlaying = true
                this.$refs.audio.play()
            },
            // 暂停音乐
            pauseSong() {
                this.isPlaying = false
                this.$refs.audio.pause()
            },
            //变化播放模式
            changeOrd() {
                if (this.playOrd === 3) return this.playOrd = 0
                this.playOrd++
            },
            //获得播放歌曲总时长
            getDuration() {
                this.musicAllDuration = this.$refs.audio.duration
            },
            //更新当前时长
            durationUpdate() {
                if (this.isChange === true) return
                this.musicDuration = this.$refs.audio.currentTime
            },
            //鼠标拖拽松开时
            changeMusicDuration() {
                if (this.musicAllDuration === 0) return
                this.$refs.audio.currentTime = this.musicDuration
                this.isChange = false
            },
        },
    }
</script>

<style scoped>
    /* 音乐播放栏 */
    
    .musicPlay {
        position: fixed;
        box-shadow: 0 0 1px 1px #b9b5b5;
        bottom: 0;
        width: 100%;
        height: 90px;
        background: #f6f6f8;
    }
    /* 音乐操作 */
    
    #play,
    #pause {
        cursor: pointer;
        background: #ebebed;
        border-radius: 100%;
        /* width: 40px; */
        height: 40px;
        line-height: 40px;
        text-align: center;
    }
    
    #play:hover,
    #pause:hover {
        background: #ddddde;
    }
    
    #playOrd,
    #backSong,
    #nextSong {
        cursor: pointer;
        border-radius: 100%;
        height: 40px;
        line-height: 40px;
        text-align: center;
    }
    
    #playOrd:hover,
    #backSong:hover,
    #nextSong:hover,
    #album:hover {
        color: #ed6566;
    }
    
    #album {
        cursor: pointer;
        border-radius: 100%;
        height: 40px;
        line-height: 36px;
        text-align: center;
    }
    
    #audioFunc {
        display: grid;
        width: 280px;
        grid-template-columns: repeat(5, 1fr);
        column-gap: 20px;
        margin-top: 1%;
        margin-left: 50%;
        transform: translateX(-50%);
    }
    /* 播放条样式 */
    
    #playSlider {
        width: 43%;
        margin-top: -5px;
        margin-left: 50%;
        transform: translateX(-50%);
    }
</style>

musicUrl是由父组件传过来的值,歌曲详情还没有制作,此篇文章主要是解决此bug,后续可能会陆续更新项目中遇到的各种bug和项目实战教程。


http://www.niftyadmin.cn/n/861686.html

相关文章

vue给路由添加滚动条达到路由内滚动

前言 在我们制作网站不止一级路由时&#xff0c;可能会要在子路由里面单独设置一个滚动条。而不是由网页自带的滚动条进行滑动。不然可能会出现这种效果 网页自带滚动条滑动 如果用网页自带的浏览器的话就是整个页面向下滑动&#xff0c;如果用户想切换到另一个子路由模块的话…

element导航栏对应路由高亮在刷新或前进后退时错误(二级子路由和三级子路由以上各自的解决办法)

问题描述&#xff1a; 当设置的有默认路径时&#xff0c;进入到二级或三级路由时&#xff0c;刷新或前进后退操作会导致导航栏高亮没有改变或错误 使用前提 将router里面的main.js里的路由路径设置全部设置为完整的路径。 routes: [{//路径为空时跳到发现音乐path: ,redire…

基于vue的高仿网易云音乐网站,实现大多数功能

文章目录前言项目演示地址线上地址项目仓库总结前言 基于Vue Vue-Router Vuex axios elementui,ui参考网易云音乐&#xff0c;后端接口使用网易云音乐接口.&#xff0c;项目中遇到的bug基本都有解决 项目演示地址 bilibili高仿网易云音乐. 线上地址 wdwmusic.&#xf…

vue部署后刷新白屏404?前端路由模式详解(hash和history)

文章目录前言一、为什么要有前端路由&#xff1f;二、前端路由模式1.hash优点缺点2.history优点缺点三、为什么history会404呢&#xff1f;1.原因2.解决方式总结前言 不知道大家有没有遇到过一种情况&#xff0c;当自己的vue部署在服务器上时&#xff0c;一切都如想象办运转&a…

手把手带你在vue中封装axios(含携带token)

文章目录前言一、认识axios1、axios是什么&#xff1f;2、为什么要用axios&#xff1f;特性二、封装axios1.引入库2.建立封装axios实例文件3.导入所需依赖4.创建axios实例5.axios拦截器请求拦截器响应拦截器5.封装成请求6.完整代码代码代码中的setLocalStorage和getLocalStorag…

防抖节流原理及实现(含演示图)

文章目录前言一、防抖&#xff08;debounce&#xff09;1、什么是防抖&#xff1f;2、防抖实现二、节流&#xff08;throttle&#xff09;1.什么是节流&#xff1f;2.节流实现总结前言 随着前端飞速的发展&#xff0c;用户体验也越来越重要。大家在逛一些网站时&#xff0c;会…

【css定位】超详细!手把手带你体验position属性(含sticky属性与效果图)

文章目录前言一、relative1.介绍2.场景相对自身定位二、absolute1.介绍2.场景相对于除static外的父元素定位父元素都是static相对于谁定位脱离文档流会占位吗三、fixed1.介绍2.场景四、sticky1.介绍2.场景总结前言 面试官&#xff1a;说说position的属性吧。 我&#xff1a;哦…

超超超超详细!手把手带你用js实现简易版position:sticky

文章目录一、基本思路二、实现过程1.准备工作1.获取dom元素&#xff0c;设置偏移量2.给滑动添加事件3.判断是否在可视区4.脱离可视区触发回调函数总结# 前言 前面我们在介绍position属性时&#xff08;不知道的小伙伴可以去看看我的另一篇说position的博客哟&#xff0c;传送门…