H5音频<audio/>样式修改,拖拽、点击进度操作、总时长加载

来源:互联网 发布:网络最热门表情包 编辑:程序博客网 时间:2024/06/01 07:18

<audio/>标签样式修改

修改原因:

不同手机展示的样式不同,特别是IOS 和安卓区别很大,需要统一样式。


修改后样式:




修改理解:

1>“点击播放”和"点击暂停" 调用原生audio.play() 和 audio.pause()来对进度条进行操作

2>总时长加载:解析 audio.duration 来获取总时长,会有部分浏览器兼容问题,下面列举部分兼容方式。

3>点击跳转进度:获取当前的 鼠标点击位置【e.pageX】 - 进度条.offsetLeft【相对于它的直接父元素 的 偏移量】,使用 translateX 改变 “蓝色小球”的播放进度位置。

4>拖拽跳转进度:监听 onTouchStart 、 onTouchMove 和 onTouchEnd 

5> 目前缺点:

  A.只有点击 进度条 才能跳转进度,建议扩大面积

  B.拖拽需要松手的时候才有效果

  C.部分 安卓 UC浏览器,不能愉快的加载时间,只能点击播放才能加载【已经做了其他的兼容】



核心代码:


转换音频时长显示

  /**   * 工具类   */  //转换音频时长显示  transTime(time) {    let duration = parseInt(time);    let minute = parseInt(duration / 60);    let sec = duration % 60 + '';    let isM0 = ':';    if (minute == 0) {      minute = '00';    } else if (minute < 10) {      minute = '0' + minute;    }    if (sec.length == 1) {      sec = '0' + sec;    }    return minute + isM0 + sec  }


获取视频总长

  loadVideo() {    let self = this;    let audio = this.refs.audioTag;    let duration = this.transTime(audio.duration);    let time = duration == "NaN:NaN" ? "00:00" : duration;    // alert(audio.duration);    if (time == "00:00" && duration != "NaN:NaN" && !!initAudio) {      audio.play();      audio.pause();      initAudio = false;      window.setTimeout(() => {        self.loadVideo();      }, 300);    }    this.setState({      voiceDuration: time,    });  }


更新播放进度

  timeUpdate() {    let audio = this.refs.audioTag;    // let value = Math.round((Math.floor(audio.currentTime) / Math.floor(audio.duration)) * 100, 0);    // console.log("timeUpdate " + value);    let timeline = this.refs.timeline;    let playhead = this.refs.playhead;    let timelineWidth = timeline.offsetWidth - playhead.offsetWidth;    let playPercent = timelineWidth * (audio.currentTime / audio.duration);    playhead.style.webkitTransform = "translateX(" + playPercent + "px)";    playhead.style.transform = "translateX(" + playPercent + "px)";    let timeCurrent = this.transTime(audio.currentTime);    this.setState({      timeCurrent: timeCurrent,      currentTime: audio.currentTime,    });  }


进度条操作,拖拽和点击都需要调用

/**   * 进度条操作   * @param  {[type]} e [description]   * @return {[type]}   [description]   */  timelineClick(e) {    let timeline = this.refs.timeline;    let playhead = this.refs.playhead;    let audio = this.refs.audioTag;    let timelineWidth = timeline.offsetWidth - playhead.offsetWidth;    // 更新坐标位置    // e.pageX 鼠标点击位置    // offsetLeft  元素 相对于它的直接父元素 的 偏移量    let newLeft = e.pageX - timeline.offsetParent.offsetLeft;    let currentTime = audio.duration * (e.pageX - timeline.offsetParent.offsetLeft) / timelineWidth;    if (newLeft >= 0 && newLeft <= timelineWidth) {      playhead.style.transform = "translateX(" + newLeft + "px)";    }    if (newLeft < 0) {      playhead.style.transform = "translateX(0)";      currentTime = 0;    }    if (newLeft > timelineWidth) {      playhead.style.transform = "translateX(" + timelineWidth + "px)";      currentTime = audio.duration;    }    // 更新时间    let timeCurrent = this.transTime(currentTime);    this.setState({      timeCurrent: timeCurrent,      currentTime: currentTime,    });    // 如果在播放    if (this.state.isPlay) {      audio.currentTime = currentTime;      audio.play();    } else { // pause music      audio.pause();    }  }

进度条拖拽相关

  // 进度条点击  touchStart(e) {    let events = e.touches[0] || e;    this.timelineClick(events);  }  touchMove(e) {    // if (this.state.touching !== true) {    //   return;    // }    let events = e.touches[0] || e;    this.timelineClick(events);  }  touchEnd(e) {    this.setState({      touching: false,    })  }


HTML代码

          <div className="inline-block voice-container">            <audio  ref="audioTag" src={this.state.voice} onTimeUpdate={()=>this.timeUpdate()} onLoadedMetadata={()=>this.loadVideo()}/>            <div className="controls">              <div className="fake-control">                <div  className="inline-block fake-control-timeline" >                  <div ref="timeline" className="timeline inline-block" onClick={(e)=> this.timelineClick(e)} >                       <div ref="playhead" className="playhead" onTouchStart={(e)=>this.touchStart(e)} onTouchMove={(e)=>this.touchMove(e)} onTouchEnd={(e)=>this.touchEnd(e)}></div>                  </div>                                    <div className="inline-block play-time">                    <div className="inline-block played-time">{this.state.timeCurrent}</div>                    <div className="inline-block">/</div>                    <div className="inline-block audio-time" id="audioTime">{this.state.voiceDuration}</div>                  </div>                 </div>                <div className="inline-block voice-control">                  <a className="play-pause" id="playPause" onClick={()=>this.play()}>                    <div className="play-icon">{ this.state.isPlay ? stop : play }</div>                  </a>                </div>              </div>            </div>                      </div>


CSS代码就不具体粘贴了~可以看下面的demo调试~



踩的坑:

不能愉快的加载音频的时长


采取兼容方式:

1>第一次没有加载出来时间的时候,自动再调用一次。

2>采用 播放、暂停的方式,获取到 总时长

3>部分机型 vivo  Xplay5A等,没有办法在UC上的获取到时长


兼容性测试:

兼容浏览器包括:
QQ浏览器、微信、手淘、百度浏览器、UC 

兼容手机包括:
IPhone7, IPhone6s, 华为P8Max,小米5,OPPO R9, vivo  Xplay5A ,小米  MI5 ,魅族  note2,乐视  X900


DEMO 演示地址:

https://codepen.io/CandyQiu/pen/VMOPaw?editors=0110




原创粉丝点击