1. 程式人生 > >專案總結(關於audio音訊標籤的使用和在angular4.0中使用過程中的一些坑)

專案總結(關於audio音訊標籤的使用和在angular4.0中使用過程中的一些坑)

馬上又到月底了,又一波新的需求又要來臨了。所以趁此空隙把之前這一個月的心得和遇到的問題寫一下
因為專案中有一個資訊轉語音的功能,也就是把一篇文章轉化為語音播放。至於怎麼轉化,這個是由後臺這邊轉化好之後,傳送了一個url音訊地址給前端,由前端直接載入到audio標籤的src屬性上。
audio標籤的使用這個可以直接參考w3c的文件
例如:

<audio src="/i/horse.ogg" controls="controls">
Your browser does not support the audio element.
</audio>

其中有很多屬性,這個也是參考w3c的文件。
首先我先說一下我遇到的一些問題,我在angular中用document.getElementById("audio")

獲取不到這個物件,然後我就發現原來是獲取的時候audio這個元素還沒有載入進來,因為這個專案是由angular4.0+ionic3.0開發的,所以我就使用了ionic3.0的生命週期鉤子ionViewDidEnter(每次進入頁面的時候呼叫,這個時候頁面已經載入好了,已經進入頁面了),在這個時候我獲取到了audio元素,但是我獲取到後打印出來是這樣一段程式碼

<audio id="audio">
   <source src="asset/a.mp3" type="audio/mp3">
<audio>   

獲取的不是一個物件,而是一段程式碼,當我用typeof 驗證資料型別的時候輸出的是object。經過查詢搜尋才發現自己把一些基礎都遺忘了,doucument.getElementById獲取的是一個dom物件,但是它是一段dom元素,這段dom元素具有一些物件的屬性,這個我以後還需要再去看一下基礎知識。
獲取到audio物件之後呢發現,這個時候它沒有duration(播放總長)和currentTime(當前播放的時間)這個兩個屬性。audio物件有很多屬性,這個具體參考下面:
*****Audio 物件屬性
屬性 描述
audioTracks 返回表示可用音訊軌道的 AudioTrackList 物件。
autoplay 設定或返回是否在就緒(載入完成)後隨即播放音訊。
buffered 返回表示音訊已緩衝部分的 TimeRanges 物件。
controller 返回表示音訊當前媒體控制器的 MediaController 物件。
controls 設定或返回音訊是否應該顯示控制元件(比如播放/暫停等)。
crossOrigin 設定或返回音訊的 CORS 設定。
currentSrc 返回當前音訊的 URL。
currentTime 設定或返回音訊中的當前播放位置(以秒計)。
defaultMuted 設定或返回音訊預設是否靜音。
defaultPlaybackRate 設定或返回音訊的預設播放速度。
duration 返回音訊的長度(以秒計)。
ended 返回音訊的播放是否已結束。
error 返回表示音訊錯誤狀態的 MediaError 物件。
loop 設定或返回音訊是否應在結束時再次播放。
mediaGroup 設定或返回音訊所屬媒介組合的名稱。
muted 設定或返回是否關閉聲音。
networkState 返回音訊的當前網路狀態。
paused 設定或返回音訊是否暫停。
playbackRate 設定或返回音訊播放的速度。
played 返回表示音訊已播放部分的 TimeRanges 物件。
preload 設定或返回音訊的 preload 屬性的值。
readyState 返回音訊當前的就緒狀態。
seekable 返回表示音訊可定址部分的 TimeRanges 物件。
seeking 返回使用者當前是否正在音訊中進行查詢。
src 設定或返回音訊的 src 屬性的值。
textTracks 返回表示可用文字軌道的 TextTrackList 物件。
volume 設定或返回音訊的音量。
Audio 物件方法
方法 描述
addTextTrack() 向音訊新增新的文字軌道。
canPlayType() 檢查瀏覽器是否能夠播放指定的音訊型別。
fastSeek() 在音訊播放器中指定播放時間。
getStartDate() 返回新的 Date 物件,表示當前時間線偏移量。
load() 重新載入音訊元素。
play() 開始播放音訊。
pause() 暫停當前播放的音訊。*

這個時候我查詢之後我才發現audio元素雖然載入好了,但是audio的資源還沒有載入好,也就是這個src屬性值還沒有載入好,所以這時候這段音訊的總時長和當前播放時間肯定是不知道的,這個時候呢,我給它增加了一個監聽事件:

let that = this;
this.audio.addEventListenter("canplay",function(e){
  that.currentTime = that.toTime(this.currentTime);
  that.duration = that.toTime(this.duration);
});

這段程式碼也是放在ionViewDidEnter生命週期鉤子中的,所以這個時候定義個
let that = this;這裡寫程式碼片

ionViewDidEnter(){
  let that = this;
  this.audio.addEventListenter("canplay",function(e){
  that.currentTime = that.toTime(this.currentTime);
  that.duration = that.toTime(this.duration);
});
  this.currentTime = this.toTime(this.audio.currentTime);
  this.duration = this.toTime(this.audio.duration);
}

這裡的that和this來回切換主要是this代表的值不一樣,也就是執行的環境不一樣。
之所以監聽事件之後又加了兩行程式碼是因為,在第一次進入這個頁面時會執行監聽,之後因為有快取,就不會走監聽事件了,這時候播放時長和當前播放時間就獲取不到了,所以要加一下這兩行程式碼。
然後就要給播放按鈕加上點選事件按鈕,也就是播放與暫停來回切換

audioPlay(){
  this.isPlay = !this.isPlay; // 控制是播放還是暫停
  let that = thisif(this.isPlay){
    this.audio.play();//播放
    let progressBar = this.progressBar;
    this.interval = setInterval(function(){//設定一個定時器主要是為了播放條滑動
        that.currentTime = that.toTime(that.audio.currentTime);
        //下面是播放條主要的
        let widthLine = Math.round(that.audio.currentTime) / Math.round(that.audio.duration) * 100 + 4;
        progressBar.style.width = widthLine + "%";
        //如果當前播放的時間和總共的播放時長相等的話就停止播放,顯示暫停按鈕
        if(that.toTime(that.audio.currentTime) == that.toTime(that.audio.duration)){
        that.isPlay = false;
        //  清除定時器
        clearInterval(that.interval);
        }
    },1000);
  }else{
     this.audio.pause();//暫停
     clearInterval(this.interval);//清除定時器
  }
}

// 時間轉化為分秒
toTime(s) {
        let t;
        if(s > -1){
           //  var hour = Math.floor(s/3600);
            var min = Math.floor(s/60) % 60;
            var sec = s % 60;
           // if(hour < 10) {
               // t = '0'+ hour + ":";
           // } else {
               // t = hour + ":";
           //  }

            if(min < 10)
            {t = "0";}
            else{
            t="";
            }
            t += min + ":";
            if(sec < 10){t += "0";}
            t += sec.toFixed(2);
        }
        return t;
    }
    // 秒轉化為00:00這樣的格式的

以上為js,下面為html程式碼佈局
語音展示

<p>
  <audio>
   <source [src]="voiceUrl" type="audio/mp3"/>
  </audio>
  <span class="audio_play_area" tapple (click)="audioPlay()">
       <i>
         <img *ngIf="!isPlay" src="assets/images/video/shengyin.png"/>
         <img *ngIf="isPlay" src="assets/images/video/shengyin.gif"/>
    </i>
  </span>
  <span class="audio_length">{{duration}}</span>
  <span class="current_time">{{currentTime}}</span>
  <span class="audio_info_area">資訊</span>
  <span class="progress_bar_box">
        <span class="progress_bar"><img class="progress_slider" src="assets/images/video/slider.png"/></span>
  </span>
</p>
// 主要是看這個佈局

css樣式如下

//語音樣式
.bullet_audio{
width:100%;
height:80px;
margin-top:12px;
border: 1px solid #ddd;
background-color: #f4f5f7;
position: relative;
.audio_play_area{
position:absolute;
left:20px;
top: 40px;
transform: translateY(-50%);
i{
display:block;
img{
width: 34px;
height:34px;
}
}
}
.audio_length{
font-size:13px;
position:absolute;
bottom:15px;
right: 20px;
color:#999;
}
.current_time{
font-size:13px;
position:absolute;
bottom:15px;
left: 22%;
color:#999;
}
.audio_info_area{
font-size:13px;
color:#333;
overflow:hidden;
display:block;
width:60%;
text-overflow:ellipsis;
white-space: nowrap;
word-wrap:normal;
position:absolute;
top:15px;
left:22%;
}
.progress_bar_box{
width:72%;
display:block;
position:absolute;
bottom:36px;
right:20px;
background-color:#c3c3c3;
height:3px;
cursor: pointer;
.progress_bar{
background-color:#ff6000;
height:3px;
display:block;
position:relative;
width:4%;
}
.progress_slider{
width:10px;
height;10px;
position:absolute;
right:0;
top:50%;
transform: translateY(-50%);
}
}
}

最後的效果圖如下:
![這裡寫圖片描述]