audio-基於Vue的一個小專案(上傳音樂連結)
1 標籤定義聲音,比如音樂或其他音訊流。
2 設定為自動播放的 audio 元素:autoplay=“autoplay”
但是隻有pc端可以實現 移動端不行(pc端的瀏覽器要比移動端的完善很多,對有些屬性支援也會好很多)
3 audio不單單是個標籤 他也是window下的一個物件,物件就有屬性和方法,作為物件他有哪些常用的方法呢
物件屬性:
currentTime 獲取當前播放時間
duration 獲取歌曲的總時間
play 是否在播放 返回true/false
pause 是否暫停 返回true/false
物件方法:
play() 播放歌曲
pause() 暫停歌曲
load()重新載入歌曲
4 onloadedmetadata
事件在指定視訊/音訊(audio/video)的元資料載入後觸發。
視訊/音訊(audio/video)的元資料包含: 時長,尺寸大小(視訊),文字軌道。
視訊/音訊(audio/video)在載入過程中,觸發的順序如下:
onloadstart
ondurationchange
onloadedmetadata
onloadeddata
onprogress
oncanplay
oncanplaythrough
https://www.cnblogs.com/leinov/p/3896772.html
例子:用Vue寫出如下樣式
解析:
1 先寫出HTML樣式
<!-- 時間軸 --> <div id="musicSlider"> <div style="width: 15%; float: left;"> <label v-text="$options.filters.formatSecond(audio.currentTime)"></label> </div> <div style="width: 70%; float: left;"> <input type="range" style="padding: 0; margin: 0;width: 100%;" v-model="sliderTime" min="0" max="100" @change="changeCurrentTime"> </div> <div style="width: 15%; float: left;"> <label v-text="$options.filters.formatSecond(audio.maxTime)"></label> </div> </div> <!-- 歌曲資訊 --> <div id="audioInfo"> <audio id="audio-1" :src="song.musicUrlAudio" ref="audio" autoplay="autoplay" onended="nextMusic()" @pause="onPause" @play="onPlay" @timeupdate="onTimeupdate" @loadedmetadata="onLoadedmetadata" > </audio> </div>
左右兩邊的時間怎麼獲得呢?
v-text不解釋標籤,也就是直接輸出獲取的資料,v-text使用過濾器,通過$options.filters進行使用
v-text如何使用filters:https://jingyan.baidu.com/article/e52e36151dae2040c60c51f0.html
filters: {
formatSecond(second = 0) {
return realFormatSecond(second);
}
}
// 將整數轉換成 時:分:秒的格式
function realFormatSecond(second) {
var secondType = typeof second
if (secondType === 'number' || secondType === 'string') {
second = parseInt(second)
var mimute = Math.floor(second / 60)
second = second - mimute * 60
return ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)
} else {
return '00:00'
}
}
Vue的method方法裡面
// 當timeupdate事件大概每秒一次,用來更新音訊流的當前播放時間
onTimeupdate(res) {
this.audio.currentTime = res.target.currentTime;
this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100);
},
onLoadedmetadata(res) {
console.log(this)
console.log(res)
this.audio.maxTime = parseInt(res.target.duration);
},
changeCurrentTime() {
this.$refs.audio.currentTime = parseInt(this.sliderTime / 100 * this.audio.maxTime)
},
打印出的this
audio.currentTime=> 列印 res.target.duration通過parseInt轉化為整數就是整首歌的時長
那,最左邊的那個時間怎麼變化,那個滑竿怎麼跟著變呢?
過濾器裡面返回了這個函式:realFormatSecond
解決進度條:
http://www.cnblogs.com/lalalagq/p/9961959.html
https://blog.csdn.net/fgdfgasd/article/details/82152482?utm_source=blogxgwz5
原始碼:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="shortcut icon" href="images/fa.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<style type="text/css">
.mui-bar {
background-color: white;
}
body {
background-color: white;
color: black;
}
#musicPlayBtns {
position: fixed;
bottom: 5%;
width: 100%;
}
#musicSlider {
position: fixed;
bottom: 15%;
width: 100%;
}
@media screen and (orientation: portrait) {
#baseIndo {
position: fixed;
width: 100%;
top: 5%;
}
#musicImage {
position: fixed;
width: 100%;
top: 20%;
/* bottom: 45%; */
}
}
@media screen and (orientation: landscape) {
#baseIndo {
width: 50%;
float: right;
top: 1%;
}
#musicImage {
width: 50%;
float: left;
/* top: 1%; */
}
}
.mui-bar {
height: 58px;
}
.mui-title {
font-weight: 700;
}
.sub-title {
font-size: 12px;
font-weight: 400;
line-height: 82px;
position: absolute;
display: block;
width: 100%;
margin: 0 -10px;
padding: 0;
text-align: center;
white-space: nowrap;
color: #000;
}
/* 控制進度條 */
.slider {
/* margin-top:100px; */
width: 100%;
position: relative;
height: 24px;
margin-bottom: 16px;
display: flex;
align-items: center;
cursor: default;
user-select: none;
outline: none;
}
.slider-track {
position: absolute;
height: 2px;
left: 0;
right: 0;
top: 50%;
margin-top: -1px;
background-color: #bec2c1;
}
.slider-fill {
position: absolute;
height: 2px;
width: 100%;
background-color: #888;
left: 0;
top: 50%;
margin-top: -1px;
}
.slider-thumb {
position: absolute;
top: 50%;
width: 12px;
height: 12px;
background-color: #888;
color: #888;
border-radius: 50%;
transform: translate(-50%, -50%);
cursor: pointer;
}
</style>
</head>
<body>
<!-- https://github.com/wangduanduan/element-audio -->
<div id="app">
<div style="margin-top:60px;">
<div style="text-align: center;">
<!-- 顯示 -->
<div id="musicImage">
<img width="65%" height="auto" style="border-radius:50%;" src="music.jpg" alt="" />
</div>
<!-- 時間軸 -->
<div id="musicSlider">
<div style="width: 15%; float: left;">
<label v-text="$options.filters.formatSecond(audio.currentTime)"></label>
</div>
<div style="width: 70%; float: left;">
<input type="range" style="padding: 0; margin: 0;width: 100%;"
v-model="sliderTime" min="0" max="100" @change="changeCurrentTime">
</div>
<div style="width: 15%; float: left;">
<label v-text="$options.filters.formatSecond(audio.maxTime)"></label>
</div>
</div>
<!-- 按鈕 -->
<div id="musicPlayBtns">
<div style="width: 45%; float: left;">
<img width="30px;" height="auto" id="preBtn" src="images/pre1.png" alt="" @click="preMusic" />
</div>
<div style="width: 10%; float: left;">
<img width="30px;" height="auto" id="playBtn" :src="audio.playing ? 'images/play1.png' : 'images/pause1.png'" alt="" @click="startPlayOrPause" />
</div>
<div style="width: 45%; float: left;">
<img width="30px;" height="auto" id="nextBtn" src="images/next1.png" alt="" @click="nextMusic" />
</div>
</div>
<!-- 歌曲資訊 -->
<div id="audioInfo">
<!-- 此處的ref屬性,可以很方便的在vue元件中通過 this.$refs.audio獲取該dom元素 -->
<audio id="audio-1" ref="audio" autoplay="autoplay" controls src="http://192.168.188.1:8000/nwmsucms/music/musicfile_7295697c-04a0-47a3-8b74-b299192a86b6.mp3"
@pause="onPause"
@play="onPlay"
@timeupdate="onTimeupdate"
@loadedmetadata="onLoadedmetadata"
@ended="nextMusic">
</audio>
</div>
</div>
</div>
</div>
<script src="vue.min.js"></script>
<script src="jquery.min.js"></script>
<script type="text/javascript">
// 將整數轉換成 時:分:秒的格式
function realFormatSecond(second) {
var secondType = typeof second
if (secondType === 'number' || secondType === 'string') {
second = parseInt(second)
var mimute = Math.floor(second / 60)
second = second - mimute * 60
return ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)
} else {
return '00:00'
}
}
var app = new Vue({
el: '#app',
data: {
song: {},
audio: {
// 該欄位是音訊是否處於播放狀態的屬性
playing: false,
currentTime: 0,
maxTime: 0,
minTime:0,
step:0.1
},
sliderTime: 0,
},
created: function () {
//var songJson = sessionStorage.getItem('songJson');
// var chineseSongsJson = sessionStorage.getItem('chineseSongsJson');
// var englishSongsJson = sessionStorage.getItem('englishSongsJson');
// this.song = JSON.parse(songJson);
// console.log(this.song)
// this.chineseSongs = JSON.parse(chineseSongsJson);
// this.englishSongs = JSON.parse(englishSongsJson);
},
mounted: function () {
},
methods:{
// 控制音訊的播放與暫停
startPlayOrPause() {
return this.audio.playing ? this.pause() : this.play();
},
play() {
this.$refs.audio.play();
},
pause() {
this.$refs.audio.pause();
},
// 當音訊播放
onPlay() {
this.audio.playing = true;
},
// 當音訊暫停
onPause() {
this.audio.playing = false;
},
/* 音訊的時間顯示主要有兩部分,音訊的總時長和當前播放時間。可以從兩個事件中獲取
loadedmetadata:代表音訊的元資料已經被載入完成,可以從中獲取音訊總時長
timeupdate: 當前播放位置作為正常播放的一部分而改變,或者以特別有趣的方式,例如不連續地改變,可以從該事件中獲取音訊的當前播放時間,該事件在播放過程中會不斷被觸發 */
// 當timeupdate事件大概每秒一次,用來更新音訊流的當前播放時間
onTimeupdate(res) {
this.audio.currentTime = res.target.currentTime;
this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100);
},
// 當載入語音流元資料完成後,會觸發該事件的回撥函式
// 語音元資料主要是語音的長度之類的資料
onLoadedmetadata(res) {
this.audio.maxTime = parseInt(res.target.duration);
},
// 拖動進度條,改變當前時間,index是進度條改變時的回撥函式的引數0-100之間,需要換算成實際時間
changeCurrentTime() {
this.$refs.audio.currentTime = parseInt(this.sliderTime / 100 * this.audio.maxTime)
},
// 進度條格式化toolTip
/* formatProcessToolTip(index = 0) {
index = parseInt(this.audio.maxTime / 100 * index)
return '進度條: ' + realFormatSecond(index)
}, */
handleTouchStart(e) {
this.setValue(e.touches[0]);
document.addEventListener('touchmove', this.handleTouchMove);
document.addEventListener('touchup', this.handleTouchEnd);
document.addEventListener('touchend', this.handleTouchEnd);
document.addEventListener('touchcancel', this.handleTouchEnd);
// e.preventDefault();
// this.onDragStart(e);
},
handleTouchMove(e) {
// console.log(e.changedTouches[0])
this.setValue(e.changedTouches[0]);
},
handleTouchEnd(e) {
this.setValue(e.changedTouches[0]);
document.removeEventListener('touchmove', this.handleTouchMove);
document.removeEventListener('touchup', this.handleTouchEnd);
document.removeEventListener('touchend', this.handleTouchEnd);
document.removeEventListener('touchcancel', this.handleTouchEnd);
// this.onDragStop(e);
},
// 從點選位置更新 value
setValue(e) {
const $el = this.$el;
const {
maxTime,
minTime,
step
} = this.audio;
let value = (e.clientX - $el.getBoundingClientRect().left) / $el.offsetWidth * (maxTime - minTime);
value = Math.round(value / step) * step + minTime;
value = parseFloat(value.toFixed(5));
if (value > maxTime) {
value = maxTime;
} else if (value < minTime) {
value = minTime;
}
this.$refs.audio.currentTime = value;
},
preMusic() {
this.audio.playing = false;
var songIndex = this.chineseSongs.findIndex(x => x.id == this.song.id);
var preIndex = 0;
if(songIndex !== -1) {
preIndex = (songIndex - 1) < 0 ? (this.chineseSongs.length - 1) : (songIndex - 1);
this.song = this.chineseSongs[preIndex];
} else {
songIndex = this.englishSongs.findIndex(x => x.id == this.song.id)
preIndex = (songIndex - 1) < 0 ? (this.englishSongs.length - 1) : (songIndex - 1);
this.song = this.englishSongs[preIndex];
}
// this.readLyric();
},
nextMusic() {
this.audio.playing = false;
var songIndex = this.chineseSongs.findIndex(x => x.id == this.song.id);
var nextIndex = 0;
if(songIndex !== -1) {
nextIndex = (songIndex + 1) >= this.chineseSongs.length ? 0 : (songIndex + 1);
this.song = this.chineseSongs[nextIndex];
} else {
songIndex = this.englishSongs.findIndex(x => x.id == this.song.id)
nextIndex = (songIndex + 1) >= this.englishSongs.length ? 0 : (songIndex + 1);
this.song = this.englishSongs[nextIndex];
}
// this.readLyric();
},
},
filters: {
formatSecond(second = 0) {
return realFormatSecond(second);
}
}
})
</script>
</body>
</html>