用angular2+ 完成音频播放器代码实现,
在这里我们用angular实现一个音频播放器,包含了播放条的操作
这里我们直接上效果图
里面的所有操作,全部用的是angular里面的属性指令操作,并没有自己写html页面,而是全部用angular里面操作的技术创建dom元素。
下面看代码:
import { Directive, AfterViewInit, ElementRef, Renderer2, Input, OnDestroy } from '@angular/core';
import { AudioHelper } from '@shared/helpers/AudioHelper';
@Directive({
selector: '[audioJs]'
})
export class AudioJsDirective implements AfterViewInit, OnDestroy {
/**
* 温馨提示:在div中放入属性指令,同时必须要有一个父级div。
*/
// tslint:disable-next-line: no-input-rename
@Input('url') url = '';
// tslint:disable-next-line: no-input-rename
@Input('isMax') isMax = false;
interl: any;
constructor(
private _element: ElementRef,
private renderer2: Renderer2
) {
}
ngAfterViewInit(): void {
let currentTime = 0; // 当前播放时长
let audio = this.renderer2.createElement('audio');
let p = this._element.nativeElement as HTMLElement;
this.renderer2.addClass(p, 'play-audio');
p.appendChild(audio);
AudioHelper.loadAudio(this.url, audio);
// 完整播放器的操作
if (this.isMax) {
this.renderer2.addClass(p.parentElement, 'parent-div-audio');
this.renderer2.setStyle(p, 'margin-left', '15px');
this.renderer2.setStyle(p, 'margin-top', '10px');
let audioTime = this.renderer2.createElement('div'); // 时间
let allProgressDiv = this.renderer2.createElement('div'); // 进度条
let sliderDiv = this.renderer2.createElement('div'); // 滑动条
let dragCircleDiv = this.renderer2.createElement('div'); // 拖拽圆球
// 给进度条他们分别添加class样式
p.parentElement.appendChild(audioTime);
this.renderer2.addClass(audioTime, 'audio-time');
p.parentElement.appendChild(allProgressDiv);
this.renderer2.addClass(allProgressDiv, 'allProgress');
allProgressDiv.appendChild(sliderDiv);
this.renderer2.addClass(sliderDiv, 'pro-silder');
allProgressDiv.appendChild(dragCircleDiv);
this.renderer2.addClass(dragCircleDiv, 'drag-circle');
// audio.duration为录音总时长
setTimeout(() => {
audioTime.innerText = AudioHelper.NumberToDate(audio.duration);
}, 500);
p.addEventListener('click', (e) => {
if (audio.paused) {
this.interl = setInterval(() => {
currentTime = currentTime + 0.1;
this.renderer2.setStyle(sliderDiv, 'width', (currentTime / audio.duration) * 110 + 'px');
}, 100);
}
});
}
// 播放失败操作
setTimeout(() => {
if (!audio.duration) {
this.renderer2.removeClass(p, 'play-audio');
this.renderer2.addClass(p, 'black-audio');
}
}, 2000);
// 点击暂停,播放操作
p.onclick = (evevt) => {
event.stopPropagation();
if (audio.paused) {
// 单个播放器播放,不允许多个播放操作
let audioFiveParent = p.parentElement.parentElement.parentElement.parentElement.parentElement.querySelector('.pause-audio');
if (audioFiveParent) {
this.renderer2.addClass(audioFiveParent, 'play-audio');
this.renderer2.removeClass(audioFiveParent, 'pause-audio');
let audioFiveParentToAny = audioFiveParent.firstChild as any; // 防止编译报错转换为any类型
audioFiveParentToAny.pause();
}
audio.play();
this.renderer2.removeClass(p, 'play-audio');
this.renderer2.addClass(p, 'pause-audio');
} else {
audio.pause();
clearInterval(this.interl);
this.renderer2.addClass(p, 'play-audio');
this.renderer2.removeClass(p, 'pause-audio');
}
};
// 判断是否播放完毕
$('audio').on('ended', () => {
this.renderer2.addClass(p, 'play-audio');
this.renderer2.removeClass(p, 'pause-audio');
clearInterval(this.interl);
currentTime = 0;
});
}
ngOnDestroy(): void {
clearInterval(this.interl);
}
}
上面代码为directive.ts里面的全部代码,详细过程直接看代码,dom元素全部是用angular里面的render
创建而来,并不是在html页面中去写div这些。
export class AudioHelper {
static loadAudio(url: string, dom: HTMLElement, cb?: () => void) {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onload = function (e) {
if (this.status === 200) {
let blob = this.response;
dom.setAttribute('src', URL.createObjectURL(blob));
}
};
xhr.send();
}
/**
* 秒转为时间格式
*/
static NumberToDate(value: number) {
if (!value) {
return '失败';
}
let second = Math.floor(value);
let minite = 0;
if (second > 60) {
minite = Math.floor(second / 60);
second = second % 60;
}
let result = '';
if (second > 10 && minite < 10) {
result = '0' + minite + ':' + second;
} else if (second < 10 && minite < 10) {
result = '0' + minite + ':' + '0' + second;
} else if (second > 10 && minite > 10) {
result = minite + ':' + second;
} else if (second < 10 && minite > 10) {
result = minite + ':' + '0' + second;
}
return result;
}
}
这些为get方式请求录音文件用到的方法 ,
还有一些class样式代码
.play-audio {
width : 20px;
height : 20px;
background : url(./assets/images/voice_zanting_icon.png) no-repeat;
background-size: cover;
}
.pause-audio {
width : 20px;
height : 20px;
background : url(./assets/images/voice_bofang_icon.png) no-repeat;
background-size: cover;
}
.black-audio {
width : 20px;
height : 20px;
background : url(./assets/images/voice_black_icon.png) no-repeat;
background-size: cover;
}
.parent-div-audio {
display : flex;
width : 220px;
height : 40px;
background : rgba(255, 255, 255, 1);
box-shadow : 0px 3px 10px 0px rgba(98, 146, 193, 0.26);
opacity : 0.99;
border-radius: 1px;
.audio-time {
width : 15%;
margin-left: 10px;
font-size : 12px;
font-family: Microsoft YaHei;
font-weight: 400;
font-style : italic;
color : rgba(97, 172, 249, 1);
line-height: 38px;
}
.allProgress {
display : flex;
width : 50%;
height : 5px;
background-color: #D2D5E0;
border-radius : 5px;
margin-left : 15px;
margin-top : 16px;
.pro-silder {
width : 0px;
height : 5px;
background-color: #61ACF9;
}
.drag-circle {
width : 9px;
height : 9px;
margin-top : -2px;
border-radius : 50%;
cursor : pointer;
background-color: rgb(38, 132, 175);
}
}
}
以上就为播放器全部代码,此播放器为项目中需要更改浏览器自带的播放器样式需求而重新自写的一个播放器,
并没有详解代码过程,看不懂代码的小伙伴或者遇到问题的小伙伴可直接留言,看到必回复。
(版权所有,转摘请附加本文章链接地址)