要实现音频的播放如下图:
html代码如下:
<audio src="" preload="metadata" controls />
本来我以为在css3这么强大的年代,自定义一个audio的皮肤应该是完全没问题的,后来的事实证明too young too simple。
看了下audio的shadow dom结构,然后试了试用css去自定义,于是发现两个问题:
-webkit-appearance: media-play-button;
,一个样式控制两种状态,没招。于是只好转向js来控制了,html修改如下:
<div class="audio-wrap">
<audio src="" preload="metadata" controls />
<i class="icon-play"></i> <!-- 播放/暂停按钮 通过js切换class -->
<div clas="timeline"> <!-- 进度条 -->
<div class="playhead"></div>
</div>
<div class="time-num"> <!-- 时间 -->
<span class="num-current">00:00</span> / <span class="num-duration">00:00</span>
</div>
</div>
loadedmetadata
事件,读取音频的总时长timeupdate
事件,用于更新播放进度canplaythrough
事件,是否能够不停下来进行缓冲的情况下持续播放指定的音频/视频icon-play
的点击事件,暂停或播放timeline
的点击事件,用于跳跃播放目前采用的es5,audio地址通过props传入,判断播放还是暂停采用state切换,进度条更新用了reactDOM操作。
var React = require('react');
var ReactDOM = React.__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
// 简单格式化时间,小于9的数字前面添加0
function formatTime(num) {
var num = parseInt(num);
if(num <= 60) {
if(num < 10) {
num = '0' + num;
}
return num;
}
}
module.exports = React.createClass({
getInitialState: function() {
return {
isPlay: false // 默认暂停
}
},
componentDidMount: function() {
var audioNode = ReactDOM.findDOMNode(this.refs.audio),
playNode = ReactDOM.findDOMNode(this.refs.play),
timeline = ReactDOM.findDOMNode(this.refs.timeline),
playhead = ReactDOM.findDOMNode(this.refs.playhead),
timeCurrent = ReactDOM.findDOMNode(this.refs.timeCurrent),
timeDuration = ReactDOM.findDOMNode(this.refs.timeDuration),
timelineWidth = timeline.offsetWidth - playhead.offsetWidth,
that = this,
duration;
// 得到初始数据
function loadedmetadata() {
timeDuration = '00:'+ formatTime(audioNode.duration);
timeCurrent = '00:00';
}
this.loadedmetadata = loadedmetadata;
// 播放进度
function timeUpdate() {
var playPercent = timelineWidth * (audioNode.currentTime / duration);
playhead.style.webkitTransform = "translateX("+playPercent + "px)";
playhead.style.transform = "translateX("+playPercent + "px)";
if (audioNode.currentTime == duration) {
that.setState({
isPlay: false
})
}
timeCurrent = '00:'+ formatTime(audioNode.currentTime);
}
this.timeUpdate = timeUpdate;
// 是否能够不停下来进行缓冲的情况下持续播放指定的音频/视频
function canplaythrough() {
duration = audioNode.duration;
}
this.canplaythrough = canplaythrough;
// 进度条点击
function timelineClick(e) {
// 更新坐标位置
var newLeft = e.pageX - timeline.offsetLeft;
if (newLeft >= 0 && newLeft <= timelineWidth) {
playhead.style.transform = "translateX("+ newLeft +"px)";
}
if (newLeft < 0) {
playhead.style.transform = "translateX(0)";
}
if (newLeft > timelineWidth) {
playhead.style.transform = "translateX("+ timelineWidth + "px)";
}
// 更新时间
audioNode.currentTime = duration * (e.pageX - timeline.offsetLeft) / timelineWidth;
}
this.timelineClick = timelineClick;
// 监听事件
audioNode.addEventListener("loadedmetadata", that.loadedmetadata);
audioNode.addEventListener("timeupdate", that.timeUpdate);
audioNode.addEventListener("canplaythrough", that.canplaythrough);
timeline.addEventListener("click", that.timelineClick);
},
componentWillUnmount: function() {
var audioNode = ReactDOM.findDOMNode(this.refs.audio),
timeline = ReactDOM.findDOMNode(this.refs.timeline);
// 注销事件
audioNode.removeEventListener("loadedmetadata", this.loadedmetadata);
audioNode.removeEventListener("timeupdate", this.timeUpdate);
audioNode.removeEventListener("canplaythrough", this.canplaythrough);
timeline.removeEventListener("click", this.timelineClick);
},
play: function(){
var audioNode = ReactDOM.findDOMNode(this.refs.audio);
this.setState({
isPlay: !this.state.isPlay
})
if (!this.state.isPlay) {
audioNode.play();
} else { // pause music
audioNode.pause();
}
},
render: function() {
return (
<div className="audio-wrap">
<audio ref="audio" src={this.props.audioUrl} preload="metadata" controls />
<i ref="play" className={"icon-play" + (this.state.isPlay ? " pause" : "")} onClick={this.play}></i>
<div ref="timeline" className="timeline">
<div ref="playhead" className="playhead"></div>
</div>
<div className="time-num">
<span ref="timeCurrent" className="num-current">00:00</span> / <span ref="timeDuration" className="num-duration">00:00</span>
</div>
</div>
)
},
propTypes: {
audioUrl: React.PropTypes.string.isRequired
}
})
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有