HTML - 音频播放器



带有可视化工具的 HTML 本地音频播放器

HTML功能,包括原生音频和视频支持,无需Flash.下面的代码基于HTML,CSS和Java脚本,您可以将本地Mp3文件拖放到容器中。

例子

让我们看一下下面的示例,我们将在其中创建一个本地音频可视化工具

HTML 文件:


<!DOCTYPE html>
<html>
	 <style>
			#instructions {
				 width: 100%;
				 text-align: center;
				 top: 50%;
				 margin-top: -100px;
				 color: #DE3163;
			}

			#container {
				 position: absolute;
				 width: 100%;
				 height: 100%;
				 background: #D5F5E3;
			}

			#canvas-container {
				 width: 600px;
				 height: 600px;
				 margin: auto;
				 position: relative;
				 top: 50%;
				 margin-top: -263px;
				 margin-right: -61px;
			}

			#canvas-copy {
				 opacity: 0.05;
				 -webkit-transform: scaleY(-1);
				 margin-top: -6px;
			}
	 </style>
<body>
	 <div id="container">
			<div id="canvas-container">
				 <canvas width=600 height=300 id="canvas"></canvas>
				 <canvas width=600 height=300 id="canvas-copy"></canvas>
			</div>
			<div id="instructions">
				 <a href="https://www.qikepu.com/index.htm" align="center"> 启科普 </a>
				 <h2 style="font-family:verdana"> 拖动本地MP3文件 </h2>
			</div>
			<div id="button"></div>
	 </div>
	 <script src="js.html"></script>
</body>
</html>

现在,我们将创建一个 javascript 文件,其名称与上面的 HTML 文件中提到的名称相同

js.html :


<script>
	 (function() {
			var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
			window.requestAnimationFrame = requestAnimationFrame;
	 })();
	 window.onload = function() {
			var element = document.getElementById('container')
			dropAndLoad(element, init, "ArrayBuffer")
	 }

	 function dropAndLoad(dropElement, callback, readFormat) {
			var readFormat = readFormat || "DataUrl"
			dropElement.addEventListener('dragover', function(e) {
				 e.stopPropagation()
				 e.preventDefault()
				 e.dataTransfer.dropEffect = 'copy'
			}, false)
			dropElement.addEventListener('drop', function(e) {
				 e.stopPropagation()
				 e.preventDefault()
				 loadFile(e.dataTransfer.files[0])
			}, false)

			function loadFile(files) {
				 var file = files
				 var reader = new FileReader()
				 reader.onload = function(e) {
						callback(e.target.result)
				 }
				 reader['readAs' + readFormat](file)
			}
	 }

	 function init(arrayBuffer) {
			document.getElementById('instructions').innerHTML = 'Audio Loading'
			window.audioCtx = new AudioContext()
			window.analyser = audioCtx.createAnalyser()
			if (window.source) source.noteOff(0)
			audioCtx.decodeAudioData(arrayBuffer, function(buffer) {
				 window.source = audioCtx.createBufferSource()
				 source.buffer = buffer
				 source.connect(analyser)
				 analyser.connect(audioCtx.destination)
				 source.start(0)
				 var viz = new simpleViz()
				 new visualizer(viz['update'], analyser)
				 document.getElementById('instructions').innerHTML = ''
			})
	 }

	 function visualizer(visualization, analyser) {
			var self = this
			this.visualization = visualization
			var last = Date.now()
			var loop = function() {
				 var dt = Date.now() - last
				 var byteFreq = new Uint8Array(analyser.frequencyBinCount)
				 analyser.getByteFrequencyData(byteFreq)
				 last = Date.now()
				 self.visualization(byteFreq, dt)
				 requestAnimationFrame(loop)
			}
			requestAnimationFrame(loop)
	 }

	 function simpleViz(canvas) {
			var self = this
			this.canvas = document.getElementById('canvas')
			this.ctx = this.canvas.getContext("2d")
			this.copyCtx = document.getElementById('canvas-copy').getContext("2d")
			this.ctx.fillStyle = '#fff'
			this.barWidth = 10
			this.barGap = 4
			this.bars = Math.floor(this.canvas.width / (this.barWidth + this.barGap))
			this.update = function(byteFreq) {
				 self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
				 var step = Math.floor(byteFreq.length / self.bars)
				 for (var i = 0; i < self.bars; i++) {
						var barHeight = byteFreq[i * step]
						self.ctx.fillRect(i * (self.barWidth + self.barGap), self.canvas.height - barHeight, self.barWidth, barHeight)
						self.copyCtx.clearRect(0, 0, self.canvas.width, self.canvas.height)
						self.copyCtx.drawImage(self.canvas, 0, 0)
				 }
			}
	 }
</script>

让我们将这两个文件结合起来,并观察我们将要得到的输出。


<!DOCTYPE html>
<html>
	 <style>
			#instructions {
				 width: 100%;
				 text-align: center;
				 top: 50%;
				 margin-top: -100px;
				 color: #DE3163;
			}

			#container {
				 position: absolute;
				 width: 100%;
				 height: 100%;
				 background: #D5F5E3;
			}

			#canvas-container {
				 width: 600px;
				 height: 600px;
				 margin: auto;
				 position: relative;
				 top: 50%;
				 margin-top: -263px;
				 margin-right: -61px;
			}

			#canvas-copy {
				 opacity: 0.05;
				 -webkit-transform: scaleY(-1);
				 margin-top: -6px;
			}
	 </style>
<body>
	 <div id="container">
			<div id="canvas-container">
				 <canvas width=600 height=300 id="canvas"></canvas>
				 <canvas width=600 height=300 id="canvas-copy"></canvas>
			</div>
			<div id="instructions">
				 <a href="/index.htm" align="center"> 启科普 </a>
				 <h2 style="font-family:verdana"> 拖动本地MP3文件 </h2>
			</div>
			<div id="button"></div>
	 </div>
	 <script>
			(function() {
				 var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
				 window.requestAnimationFrame = requestAnimationFrame;
			})();
			window.onload = function() {
				 var element = document.getElementById('container')
				 dropAndLoad(element, init, "ArrayBuffer")
			}

			function dropAndLoad(dropElement, callback, readFormat) {
				 var readFormat = readFormat || "DataUrl"
				 dropElement.addEventListener('dragover', function(e) {
						e.stopPropagation()
						e.preventDefault()
						e.dataTransfer.dropEffect = 'copy'
				 }, false)
				 dropElement.addEventListener('drop', function(e) {
						e.stopPropagation()
						e.preventDefault()
						loadFile(e.dataTransfer.files[0])
				 }, false)

				 function loadFile(files) {
						var file = files
						var reader = new FileReader()
						reader.onload = function(e) {
							 callback(e.target.result)
						}
						reader['readAs' + readFormat](file)
				 }
			}

			function init(arrayBuffer) {
				 document.getElementById('instructions').innerHTML = 'Audio Loading'
				 window.audioCtx = new AudioContext()
				 window.analyser = audioCtx.createAnalyser()
				 if (window.source) source.noteOff(0)
				 audioCtx.decodeAudioData(arrayBuffer, function(buffer) {
						window.source = audioCtx.createBufferSource()
						source.buffer = buffer
						source.connect(analyser)
						analyser.connect(audioCtx.destination)
						source.start(0)
						var viz = new simpleViz()
						new visualizer(viz['update'], analyser)
						document.getElementById('instructions').innerHTML = ''
				 })
			}

			function visualizer(visualization, analyser) {
				 var self = this
				 this.visualization = visualization
				 var last = Date.now()
				 var loop = function() {
						var dt = Date.now() - last
						var byteFreq = new Uint8Array(analyser.frequencyBinCount)
						analyser.getByteFrequencyData(byteFreq)
						last = Date.now()
						self.visualization(byteFreq, dt)
						requestAnimationFrame(loop)
				 }
				 requestAnimationFrame(loop)
			}

			function simpleViz(canvas) {
				 var self = this
				 this.canvas = document.getElementById('canvas')
				 this.ctx = this.canvas.getContext("2d")
				 this.copyCtx = document.getElementById('canvas-copy').getContext("2d")
				 this.ctx.fillStyle = '#fff'
				 this.barWidth = 10
				 this.barGap = 4
				 this.bars = Math.floor(this.canvas.width / (this.barWidth + this.barGap))
				 this.update = function(byteFreq) {
						self.ctx.clearRect(0, 0, self.canvas.width, self.canvas.height)
						var step = Math.floor(byteFreq.length / self.bars)
						for (var i = 0; i < self.bars; i++) {
							 var barHeight = byteFreq[i * step]
							 self.ctx.fillRect(i * (self.barWidth + self.barGap), self.canvas.height - barHeight, self.barWidth, barHeight)
							 self.copyCtx.clearRect(0, 0, self.canvas.width, self.canvas.height)
							 self.copyCtx.drawImage(self.canvas, 0, 0)
						}
				 }
			}
	 </script>
</body>
</html>

当我们运行上述代码时,它将生成一个输出,其中包含应用了 CSS 的文本,指示拖动本地 MP3 文件来播放音乐。

带播放列表的本地音频播放器

考虑以下示例,其中我们允许用户上传充当播放列表的多个本地 MP3。


<!DOCTYPE html>
<html>
<body style="background-color:#ABEBC6;">
	 <audio controls id="y" autoplay></audio>
	 <br>
	 <br>
	 <br>
	 <input type="file" id="x" multiple>
	 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
	 <script>
			var x = document.getElementById("x"),
				 y = document.getElementById("y");

			function next(n) {
				 var a = URL.createObjectURL(z[n]);
				 y.setAttribute('src', a);
				 y.play();
			}
			var _next = 0,
				 z,
				 len;
			x.addEventListener('Change', function() {
				 z = x.z;
				 len = z.length;
				 if (len) {
						next(_next);
				 }
			});
			y.addEventListener("Completed", function() {
				 _next += 1;
				 next(_next);
				 console.log(len, _next);
				 if ((len - 1) == _next) {
						_next = -1;
				 }
			});
	 </script>
</body>
</html>

运行上述代码后,将弹出输出窗口,允许用户上传多个 mp3 文件并在网页上自动播放。