美文网首页
Vue-audio实现音乐播放器托盘

Vue-audio实现音乐播放器托盘

作者: 二营长家的张大炮 | 来源:发表于2020-08-04 15:39 被阅读0次
<template>
  <div class="music-player flex-row-justify-end">
    <audio
      :src="src"
      ref="audio"
      @timeupdate="onTimeUpdate"
      @loadeddata="onLoad"
    ></audio>
    <!-- 进度条 -->
    <el-slider
      :min="0"
      :max="duration"
      v-model="progress"
      :show-tooltip="false"
      class="music-player-progress"
      @change="handleProgressChange"
      @mousedown.native="onMouseDown"
      @mouseup.native="onMouseUp"
    ></el-slider>

    <!-- 歌曲信息 -->
    <div class="music-player-avatar flex">
      <img v-if="musicInfo.picUrl" :src="musicInfo.picUrl" alt />
      <div class="info">
        <div>{{ musicInfo.name || '' }}</div>
        <div v-if="duration">
          {{ formatDuration(progress) }}/{{ formatDuration(duration) }}
        </div>
      </div>
    </div>

    <!-- 按钮 -->
    <div class="music-player-btn">
      <i class="iconfont icon-shangyishou"></i>
      <i v-show="playing" class="iconfont icon-bofang" @click="pause"></i>
      <i v-show="!playing" class="iconfont icon-bofang1" @click="play"></i>
      <i class="iconfont icon-xiayishou"></i>
    </div>

    <!-- 音量 -->
    <div class="music-player-operation flex">
      <el-slider v-model="volumeSlide" :min="0" :max="100"></el-slider>
      <i class="iconfont icon-yinliang"></i>
    </div>
  </div>
</template>
<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator'
import { MusicApi } from '@/service/modules/index'

@Component({
  name: 'MusicPlayer'
})
export default class MusicPlayer extends Vue {
  // 播放链接
  private src = ''
  // 是否在播放
  private playing = false
  // 音量*100
  private volumeSlide = 50
  // 进度
  private progress = 0
  // 歌曲总时长
  private duration = 0
  // 是否处于拖动进度条状态
  private isDrag = false
  // 格式化
  formatDuration(time: number) {
    return (this as any).$formatDuration(time)
  }
  // 鼠标按下
  onMouseDown() {
    this.isDrag = true
  }
  // 鼠标抬起
  onMouseUp() {
    this.isDrag = false
  }
  // 修改进度
  handleProgressChange(value: number) {
    this.isDrag = false
    this.progress = value
    this.audioPlayer.currentTime = value
  }
  // 暂停
  pause() {
    if (this.audioPlayer) {
      this.audioPlayer.pause()
    }
    this.playing = false
  }
  // 播放
  play() {
    this.playing = true
    if (this.audioPlayer) {
      ;(this.audioPlayer as HTMLAudioElement).play()
    }
  }
  // 更新时间
  onTimeUpdate(e: any) {
    if (this.audioPlayer && !this.isDrag) {
      this.progress = this.audioPlayer.currentTime
    }
  }
  // 加载完成
  onLoad() {
    this.duration = Math.ceil(this.audioPlayer.duration)
  }
  // 获取歌曲
  get musicInfo() {
    return this.$store.state.music.musicInfo
  }
  // audio实例
  get audioPlayer(): HTMLAudioElement {
    return this.$refs.audio as HTMLAudioElement
  }
  // 监听musicinfo变化
  @Watch('musicInfo')
  async handleMusicInfoChange(
    newVal: { id: string; name: string; picUrl: string },
    oldVal: { id: string; name: string; picUrl: string }
  ) {
    try {
      const res = await MusicApi.getMusicUrlById({ id: newVal.id })
      if (res && res.data) {
        this.src = res.data[0].url
        setTimeout(() => {
          this.play()
        }, 500)
      }
    } catch (error) {
      console.log(error)
    }
  }
  // 监听音量变化
  @Watch('volumeSlide')
  handleVolumeSlideChange(newVal: number, oldVal: number) {
    if (this.audioPlayer) {
      this.audioPlayer.volume = Number((newVal / 100).toFixed(1))
    }
  }
  mounted() {
    this.progress = 0
    this.duration = 0
  }
}
</script>
<style lang="less" scoped>
@import url('../style/common.less');
.music-player {
  position: relative;
  height: 3rem;
  padding: 0.3rem 0.4rem;
  align-items: center;
  &-progress {
    position: absolute;
    top: -0.9rem;
    left: 0;
    width: 100%;
    ::v-deep .el-slider__runway {
      height: 0.1rem;
      background-color: #ededed;
      margin: 0.5rem 0;
      .el-slider__button {
        width: 0.1rem;
        height: 0.1rem;
        position: relative;
        top: -2px;
        border-color: @common-color;
      }
      .el-slider__bar {
        bottom: 0;
        height: 2px;
        background-color: @common-color;
      }
    }
  }
  &-avatar {
    .info {
      font-size: 0.8rem;
      padding-left: 0.5rem;
      text-align: left;
      div {
        line-height: 1.2rem;
      }
    }
    img {
      width: 3rem;
      height: 3rem;
    }
  }
  &-btn {
    font-size: 1rem;
    color: @common-color;
    cursor: pointer;

    .icon-bofang,
    .icon-bofang1 {
      font-size: 2.2rem;
      margin: 1rem;
    }
    .icon-shangyishou,
    .icon-xiayishou {
      position: relative;
      bottom: 0.2rem;
      font-size: 1.2rem;
    }
    .icon-shangyishou:hover,
    .icon-xiayishou:hover {
      transition: 200ms all ease-in;
      font-size: 1.3rem;
    }
  }
  &-operation {
    ::v-deep .el-slider {
      width: 7rem;
      height: 4px;
      margin-right: 0.6rem;
      .el-slider__runway {
        height: 4px;
      }
      .el-slider__button-wrapper {
        top: -0.8875rem;
        .el-slider__button {
          width: 0.3rem;
          height: 0.3rem;
          position: relative;
          top: -1px;
          border-color: @common-color;
        }
      }
      .el-slider__bar {
        background-color: @common-color;
      }
    }
    .iconfont {
      font-size: 1.1rem;
      position: relative;
      top: 0.5rem;
    }
  }
}
</style>

相关文章

网友评论

      本文标题:Vue-audio实现音乐播放器托盘

      本文链接:https://www.haomeiwen.com/subject/heswrktx.html