angular11实现自定义语音播放器

angular11实现自定义语音播放器

本播放器实现了播放、暂停、点击进度条播放、拖动到指定位置播放、指定播放时间范围等等。具体请看代码。

import { Component, OnInit } from '@angular/core';
import { fromEvent } from 'rxjs';
import * as _ from 'lodash';

class Audio implements OnInit {
  audio: HTMLAudioElement;
  duration: number;
  startTime = 0;
  endTime = 0;
  moveDistance = 0;
  dragDistance = 0;
  barWidth = 0;
  sliderWidth = 0;
  canSlideWidth = 0;
  givedEndTime = 0;
  url =
    'https://autotest-qi.obs.cn-north-7.ulanqab.huawei.com:443/%E8%AF%AD%E9%9F%B3%E6%96%87%E4%BB%B6_%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E9%A2%84%E7%BD%AE_%E5%8B%BF%E5%88%A0/2-2.mp3?AccessKeyId=7HU7YO4WE012PTZTVPTB&Expires=1619680596&x-obs-security-token=gQpjbi1ub3J0aC03hmp9srGjyHuP2p45iE1wULlzh5qFF6ZSTPthh8ND_JspOU6g8MkZ-tu-_nbvXMdXCxkPqbJQAm-yPSVNz2uNQbkjW-0EkyluhtuxY82L59hnghOq_eVPHR1prTpCq0ivaC12UbxQgzwD6eoEl-h7zcjrE2MJYz5xPRDSzFoG5VpKrlnmHNzsXPET90C_i0W0THm63MF7XmIeAwKZ_b25lJzgYdGnRR6GAi0Ga_U9dv7WAk1qvOk79bDjnpw9z0-wX7-7eHjtVLY5KKBH1XLaNHGKGp8bksmMP5P4fnyL8SS4oZ9n3fQpMgY0NGPJxMb9U5MKR1FCTgTirh7GQagSPIKkufIk1yioq1_DMKmnYzy9eFCn5HZgIrfeupVg-CC6k0oMYZb0CsaF9J8IXiocw1YAecmOqMvd0JFd-pv7pXipEJYlEuZ7kMOlWAcB4lh09dY-o6L_8QDgA28B_8mBnh-LhiaqnKLjCiUeH-EX9WYyvkL8SA3RjtTOFdlLWE106K_2MhlLRRTTBh9XwjfmXysre8VcDTKKzYc9Runkt7Ckh9gGAlfMrWUdE4I1fsu2C58k1wyoLIfpEzMVomxOh0TiaCKjUkaT0-NPwuXSXFNoq8yf6cgCgsv3r5vmF38nTcDCeg0_8KPxdFJV77DqhH16VkzKgmiAJM9utNa33Q88cswyAt-_PfwNMO1v55_G9RaWgj2gwSV6ofJSiqBzlASNJz0_pwlh1_cVz5sqBds9oZTbcUiyLS8JUfBcUySaUlvoonjb3tEFJ1kOyVIP51vULQDUm6sXTjAle_O5cvFLej1a_JzI56kHoOU-xUTAKePKqIBjSYKszIJnMD5rzSFGRv1xzBwr0RTTdsv9VGLyce1sm4ZE3FwXSBTGrXZJNXFfqtShRqXXwYLxjmbG5kjIad1Hcj3LJ7Mq1i3tVhiIkn6g7xb4R6RKE1CEcbI3hvP5MhII1Qo46u8mvdCi299uLFh2-tGwwHKI_BuMa5DPtBOBjUmXFgppjiPIlDuOZemHwfyUhHp2oIpTZhIuyMDhwK2na7DzfBwNMgEgk5-mWRyF4GubRbI5jUfgwacpPw%3D%3D&Signature=wsqj5ZnaH13J0DkdQ%2FKvnBnBeVA%3D';
  constructor() {}
  ngOnInit(): void {
    this.audio = document.querySelector('audio');
    this.initParam();

    // 基于准备好的dom,初始化echarts实例
    this.addPlayListener();
    this.addCanplayListener();
    this.addTimeupdateChange();
    this.addPauseListener();
  }

  /**
   * 获取播放条宽度
   */
  initParam() {
    const bar = document.querySelector('#bar') as HTMLElement;
    const slider = document.querySelector('#slider') as HTMLElement;
    this.barWidth = +bar.style.width.split('px')[0];
    this.sliderWidth = +slider.style.width.split('px')[0];
    this.canSlideWidth = this.barWidth - this.sliderWidth / 2;
  }

  /**
   * 监听开始播放
   */
  addPlayListener(): void {
    fromEvent(this.audio, 'play').subscribe((res) => {
      this.startTime = this.getCurrentTime();
    });
  }

  /**
   * 监听暂停播放
   */
  addPauseListener(): void {
    fromEvent(this.audio, 'pause').subscribe((res) => {
      this.endTime = this.getCurrentTime();
    });
  }

  /**
   * 监听是否能播放
   */
  addCanplayListener(): void {
    fromEvent(this.audio, 'canplay').subscribe((res) => {
      this.initTime();
    });
  }

  /**
   * 点击调整播放位置
   */
  goto(event: MouseEvent) {
    let position =
      event.clientX -
      (event.target as HTMLElement).parentElement.offsetLeft -
      this.sliderWidth / 2;
    const currentTime = this.distanceToTime(position);
    this.toPlayTime(currentTime);
  }

  /**
   * 时间改变的回调
   */
  addTimeupdateChange(): void {
    fromEvent(this.audio, 'timeupdate').subscribe((res) => {
      // 是否在给定时间内播放
      if (this.givedEndTime !== 0) {
        let over = this.playRangeTime(this.endTime, this.givedEndTime);
        if (over) {
          this.givedEndTime = this.duration;
        }
      }
      this.endTime = this.getCurrentTime();
      this.moveDistance = this.timeToDistance(0, this.endTime);
    });
  }

  /**
   * 从给定时间点播放
   */
  playFromGiveTime(start: number, end: number) {
    this.toPlayTime(start);
    this.play();
    this.givedEndTime = end;
  }

  /**
   * 当前进度播放范围内
   */
  playRangeTime(current: number, end: number): boolean {
    if (current > end) {
      this.pause();
      return true;
    }
  }

  /**
   * 初始化播放时间和当前进度
   */
  initTime(): void {
    // 获取播放总时间
    this.duration = this.getPlayTime();
  }

  /**
   * 获取播放长度
   */
  getPlayTime(): number {
    return this.audio.duration;
  }

  /**
   * 获取当前播放进度
   */
  getCurrentTime(): number {
    return this.audio.currentTime;
  }

  /**
   * 播放
   */
  play(): void {
    this.audio.play();
  }

  /**
   * 暂停
   */
  pause(): void {
    this.audio.pause();
  }

  /**
   * 点击播放圆点
   */
  mouseclick(event: MouseEvent) {
    event.stopPropagation();
  }

  /**
   * 拖动
   */
  mousedown(event: MouseEvent): void {
    const currentX = event.clientX;
    const slider = document.querySelector('#slider') as HTMLElement;
    const leftVal = currentX - slider.offsetLeft;
    const mousemove = fromEvent(document, 'mousemove').subscribe((event2) => {
      const barLeft = (event2 as MouseEvent).clientX;
      const move = barLeft - leftVal;
      if (_.inRange(move, 0, this.canSlideWidth)) {
        this.dragDistance = move;
        const currentTime = this.distanceToTime(move);
        this.toPlayTime(currentTime);
      }
      window.getSelection().removeAllRanges();
    });

    fromEvent(document, 'mouseup').subscribe(() => {
      mousemove.unsubscribe();
    });
  }

  /**
   * 根据拖动距离设置当前播放时间
   */
  toPlayTime(time): void {
    this.audio.currentTime = time;
  }

  /**
   * 时间转为距离
   */
  timeToDistance(start, end): number {
    return ((end - start) / this.duration) * this.canSlideWidth;
  }

  /**
   * 距离转为时间
   */
  distanceToTime(distance): number {
    return (distance / this.canSlideWidth) * this.duration;
  }
}

<audio [src]="url" controls style="display: none">
  您的浏览器不支持 audio 标签。
</audio>
<div style="display: flex; align-items: center;margin-left: 100px;">
  <div (click)="goto($event)" id="bar" style="height: 5px; width: 500px; background-color: aquamarine;position: relative;cursor: pointer;">
    <div
      style="height: 5px; background-color: red;position: absolute;top: 0;left: 0;"
      [style.width]="moveDistance + 'px'"
    >
    <div id="slider" (click)="mouseclick($event)" (mousedown)="mousedown($event)" style="position: absolute;left: 100%;top:-150%;width: 20px;height: 20px;border-radius: 50%;background-color: aqua;cursor: pointer;"></div>
  </div>

  </div>

  <span>{{ duration }}</span>
</div>

<button (click)="play()">播放</button>
<button (click)="pause()">暂停</button>
<button (click)="playFromGiveTime(5,10)">指定范围</button>

在这里插入图片描述
具体效果请编辑代码实现哈,有问题请留言,会及时回复的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Young soul2

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值