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>

猜你喜欢

转载自blog.csdn.net/fengtingYan/article/details/84832114