music, let's go
最近研究个新玩意,叫window.AudioContext;不懂?没关系,我也是才接触,这完全可以说个全新领域,
这玩意干啥的?顾名思义,媒体上下文,也就是你媒体的数据分析,就是一串数据啊?那有啥用呢?对,单纯的数据毫无意义,但是如果把数据结合canvas,就会产生神奇的效果(比如百度的echart),这里的AudioContext结合canvas就能产生一个音乐可视化的效果,就是那种手机MP3播放器的效果,又叫音乐可视化;
首先原理:
前端获取到buffer数据,然后运用解析对象,把数据解析,把解析结果放到数组里面,然后连接,最后用canvas画出来;
后台代码
const express = require('express'); const fs = require('fs'); const app = express(); app.get('/app/test', function(req,res) { fs.readFile('Maksim-克罗地亚狂想曲.mp3', (err, name) => { if (err) return res.send(name) }) })
html部分
<body> <input type="range" id="radio"> //改变音量的 <canvas id="mycanvas"></canvas> </body>
首先前端发起请求,请求音乐的流
function getdata () { var xhr = new XMLHttpRequest() xhr.open('get', '/app/test'); xhr.responseType = 'arraybuffer'; xhr.onload = function () { // 解析后台传来的数据,然后把数据复制到前端的buffer上; 第一个链接的必须是分析者,分析者获取原始数据 ac.decodeAudioData(xhr.response, function (buffer){ var buffesource = ac.createBufferSource();// 创建数据,其中buffersource还有个属性是loop就是音乐是不是循环播放
buffesource.buffer = buffer buffesource.connect(analyser) buffesource.start(0) //这里star可以三个参数,一次意思是,等待多久播放,从哪里开始播放,播放多久 }, function (err) { console.log(err) }) } xhr.send() }
然后创建音频控制对象
var ac = new (window.AudioContext || window.webkitAudioContext)() //这是兼容浏览器的写法 var gainNode = ac[ac.createGain ? 'createGain' : 'createGainNode']() 这个老式和新式api不同 var analyser = ac.createAnalyser() //创建分析者 var size = 128 analyser.fftSize = size * 2;// 这里获取柱子个数就是ffsize的一半 analyser.connect(gainNode) gainNode.connect(ac.destination)
初始化canvas
function caninit () { var line = ctx.createLinearGradient(0,0,0,600) line.addColorStop(0,'red') line.addColorStop(.5, 'yellow') line.addColorStop(1, 'green') ctx.fillStyle = line } caninit()
赋值原始数据到数组
function asyc () { var arr = new Uint8Array(analyser.frequencyBinCount) analyser.getByteFrequencyData(arr) draw(arr) nextFrame(asyc) } 定一个unit8数组,然后把数据赋值进去.注意这里不是不是8位无符号数组,那么analyser.getByteFrequencyData这个方法会报错,说第一个参数必须uint8array
最后画出效果
function draw (arr) { ctx.clearRect(0, 0, width, height) var w = width / size for (var i = 0; i < arr.length; i++) { var h = (arr[i] / 512) * height; ctx.fillRect(w * i, height - h, w *.6, h) } }
ok可以了,页面效果是这样的
全部代码正在整理上传,各位有兴趣可以写几个echart的类型表玩玩啊