热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

vue-music关于Player播放器组件详解

本文实例为大家分享了关于Player播放器组件的具体内容,供大家参考,具体内容如下 迷你播放器: 1.播放器组件会在各个页面的情

本文实例为大家分享了关于Player播放器组件的具体内容,供大家参考,具体内容如下

迷你播放器:

1.播放器组件会在各个页面的情况下会打开。 首先在vuex state.js 中定义全局的播放器状态

import {playMode} from 'common/js/config.js';

const state = {
 singer:{}, 
 playing:false, //是否播放
 fullScreen:false, //是否全屏
 playList:[], //播放列表
 sequenceList:[], // 非顺序播放列表
 mode:playMode.sequence, // 播放模式(顺序0,循环1,随机2)
 currentIndex:-1, //当前播放索引
}
export default state 


---------------------------------------------
// config.js

export const playMode = {
 sequence:0,
 loop:1,
 random:2
}

2.进入播放器页面时获取播放列表数据,改变播放状态   在music-list列表中打开

在song-list 组件中派发事件到父组件,传入当前歌曲的信息和索引

  • ------------------------------ selectItem(item,index){ this.$emit('select',item,index) },
  • 在music-list 组件中接受派发事件。

     

    3. 如果commit 多个状态在actions 里设置

    import {playMode} from 'common/js/config.js'
    
    export const selectPlay = function({commit,state},{list,index}){
     commit(types.SET_SEQUENCE_LIST, list)
     commit(types.SET_PLAYLIST, list)
     commit(types.SET_CURRENT_INDEX, index)
     commit(types.SET_FULL_SCREEN, true)
     commit(types.SET_PLAYING_STATE, true)
    }
    
    

    4. 在music-list 组件中 用mapActions提交 改变值

    import {mapActions} from 'vuex'
    
    methods:{
     selectItem(item,index){
      this.selectPlay({
      list:this.songs,
      index
      })
     },
     ...mapActions([
      'selectPlay'
     ])
     },
    
    

    5.在palyer 中获取vuex 全局状态,赋值状态到相应位置(代码为完整代码,对照后面讲解慢慢理解)

        // 如果有列表数据则显示
      //如果全屏
        //模糊背景图

        //当前歌曲名称

      //当前歌手名
        //封面图
    {{ format(currentTime) }}
    {{ format(currentSong.duration) }}

    打开播放器的状态

    import {mapGetters,mapMutations} from 'vuex';
    
    ...mapGetters([
     'fullScreen',
     'playList',
     'currentSong',
     'playing',
     'currentIndex',
    ])
    
    

    注意:不可在组件中直接赋值改版vuex 中的状态 this.fullScreen = false 需要通过mutations 改变,定义mutation-types 和mutations 然后 用vuex的 mapMutations 代理方法调用

    [types.SET_FULL_SCREEN](state, flag) {
     state.fullScreen = flag
     },
    
    import {mapGetters,mapMutations} from 'vuex';
    methods:{
     ...mapMutations({
     setFullScreen:"SET_FULL_SCREEN", 
     }),
     back(){
     this.setFullScreen(false)
     },
    }
    
    

    设置点击播放按钮方法

     
    
    togglePlaying(){
     this.setPlayingState(!this.playing); //改变全局变量playing 的属性
    },
    
    // 然后watch 监听playing 操作实际的audio 标签的播放暂停
    watch:{
      playing(newPlaying){
       let audio = this.$refs.audio;
       this.$nextTick(() => {
        newPlaying ? audio.play():audio.pause();
       })
      }
     },
    
    // 用计算属性改变相应的播放暂停图标
    playIcon(){
     return this.playing? 'icon-pause':'icon-play'
    },
    
    

    设置点击播放上一首和下一首按钮方法。用mapGetters 获取currentIndex 的值(加一或减一) 并改变,从而改变 currentSong 的状态,监听切换播放。判断播放列表界限重置。

    prev(){
        if(!this.songReady){
          return;
        }
    
     let index = this.currentIndex - 1;
     if(index === -1){    //判断播放列表界限重置
      index = this.playList.length-1;
     }
     this.setCurrentIndex(index);
     if(!this.playing){  //判断是否播放改变播放暂停的icon
      this.togglePlaying();
     }
     this.sOngReady= false;
    },
    next(){
     if(!this.songReady){
        return;
       }
     let index = this.currentIndex + 1;
     if(index === this.playList.length){    //判断播放列表界限重置
      index = 0;
     }
     this.setCurrentIndex(index);
     if(!this.playing){
      this.togglePlaying();
     }
     this.sOngReady= false;
    },
    
    

    监听audio 元素标签的canpaly 事件,当歌曲加载就绪 和 error 事件,当歌曲发生错误的时候,做用户体验,防止用户快速切换导致报错。

    设置songReady 标志位 如果歌曲没有准备就绪,点击下一首的时候直接return false

    data(){
     return {
      songReady:false,
     }
    },
    
    ready(){
     this.sOngReady= true;
    },
    error(){
     this.sOngReady= true;
    },
    
    

    进度条

    audio元素监听 timeupdate 事件获取当前播放时间的 可读写属性 时间戳。用formt做格式化时间处理,(_pad 为补零函数 )

    获取音频总时长 currentSong.duration

    {{ format(currentTime) }}
    {{ format(currentSong.duration) }}
    updateTime(e){
     this.currentTime = e.target.currentTime; // 获取当前播放时间段
    },
    
    format(interval){
     interval = interval | 0;
     const minute = interval/60 | 0;
     const secOnd= this._pad(interval % 60);
     return `${minute}:${second}`;  
    },
    
    _pad(num,n=2){
     let len = num.toString().length;
     while(len
    

    建立progress-bar 组件 接收pencent 进度参数,设置进度条宽度和小球的位置。player组件 设置计算属性percent

    percent(){
     return this.currentTime / this.currentSong.duration  // 当前时长除以总时长
    },
    

    progress-bar 组件

    const progressBtnWidth = 16 //小球宽度
    
    props:{
     percent:{
     type:Number,
     default:0
     }
    },
    
    
    watch:{
     percent(newPercent){
     if(newPercent>=0 && !this.touch.initated){    
      const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth;
      const offsetWidth = newPercent * barWidth;
      this.$refs.progress.style.width = `${offsetWidth}px`;
      this.$refs.progressBtn.style.transform=`translate3d(${offsetWidth}px,0,0)`
     }
     }
    }
    
    

    设置拖动

    在进度条小按钮progressBtn 上添加touchstart,touchmove,touchend 事件监听方法,事件添加 prevent 防止拖动默认浏览器行为,获取拖动的信息进行计算

    在实例上创建一个touch 对象维护不同的回调之间的通讯共享状态信息。  touchstart事件方法中 ,首先设置this.touch.initated为true,表示拖动开始。  记录开始点击位置 e.touches[0].pageX 存到 touch 对象上,记录当前的进度宽度。

    在touchmove 中首先判断 是否先进入了 touchstart 方法,计算得到 移动的位置 减去 点击开始的位置的 偏移量长度。 let deltax = e.touches[0].pageX - this.touch.startX

    就可以 设置进度条 已有的长度加上偏移量长度。最大不能超过父级progressbar 的宽度

    调用this._offset(offsetWidth) 方法设置进度条宽度

    在touchend 事件方法中将 this.touch.initated 设置为false,表示拖动结束,并派发事件到player 组件将audio的currentTime 值设置为正确值,参数为pencent

    在progressbar 中增加点击事件,调用this._offset(e.offsetX),并且派发事件

     created(){
     this.touch = {};
     },
    
    methods:{
     progressTouchStart(e){
     this.touch.initiated = true;
     this.touch.startX = e.touches[0].pageX;
     this.touch.left = this.$refs.progress.clientWidth;
     },
     progressTouchMove(e){
     if(!this.touch.initiated){
      return;
     }
     let deltaX = e.touches[0].pageX - this.touch.startX;
     let offsetWidth = Math.min(this.$refs.progressBar.clientWidth - progressBtnWidth,Math.max(0,this.touch.left + deltaX));
     this._offset(offsetWidth);
     },
     progressTouchEnd(e){
     this.touch.initiated = false;
     this._triggerPercent();
     },
     progressClick(e){
     const rect = this.$refs.progressBar.getBoundingClientRect();
     const offsetWidth = e.pageX - rect.left;
     this._offset(offsetWidth);
     // this._offset(e.offsetX);
     this._triggerPercent();
     },
     _offset(offsetWidth){
     this.$refs.progress.style.width = `${offsetWidth}px`;
     this.$refs.progressBtn.style[transform] = `translate3d(${offsetWidth}px,0,0)`;
     },
     _triggerPercent(){
     const barWidth = this.$refs.progressBar.clientWidth - progressBtnWidth;
     const percent = this.$refs.progress.clientWidth / barWidth;
     this.$emit("percentChange",percent)
     }
    },
    
    

    本文已被整理到了《Vue.js前端组件学习教程》,欢迎大家学习阅读。

    关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

    更多vue学习教程请阅读专题《vue实战教程》

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


    推荐阅读
    author-avatar
    盧品澄_673
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有