视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
H5的Canvas如何实现绘制音乐环形频谱图
2020-11-27 20:01:18 责编:小采
文档
 这次给大家带来H5的Canvas如何实现绘制音乐环形频谱图,H5Canvas实现绘制音乐环形频谱图的注意事项有哪些,下面就是实战案例,一起来看一下。

在B站我们有很多的小伙伴们应该都看到过用AE做的可视化音乐播放器播放音乐的视频,看着特别酷炫带感有木有。

所以今天我就用 Canvas 做个简单 环形频谱图。

那么~ ヾ(o?ω?)? 开始吧!

1.首先绘制静态的效果

静态效果

绘制静态效果很简单,我们只要从一点出发根据一定角度绘制线条,然后画个圆从中点开始覆盖线条就行了

<canvas id="wrap" height="800" width="800"></canvas><script>
 var wrap = document.getElementById("wrap"); var cxt = wrap.getContext("2d");
 (function drawSpectrum() {
 cxt.clearRect(0, 0, wrap.width, wrap.height); //画线条
 for (var i = 0; i < 360; i++) { var value = 8;
 cxt.beginPath();
 cxt.lineWidth = 2;
 cxt.moveTo(300, 300); //R * cos (PI/180*一次旋转的角度数) ,-R * sin (PI/180*一次旋转的角度数)
 cxt.lineTo(Math.cos((i * 1) / 180 * Math.PI) * (200 + value) + 300, (- Math.sin((i * 1) / 180 * Math.PI) * (200 + value) + 300));
 cxt.stroke();
 } //画一个小圆,将线条覆盖
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.arc(300, 300, 200, 0, 2 * Math.PI, false); 
 cxt.fillStyle = "#fff";
 cxt.stroke();
 cxt.fill(); 
 })();</script>

2.调用AudioAPI,绘制音乐的频谱图

绘制音乐的频谱图

第一步完成后,第二步就很简单了,通过调用AudioAPI获取音频变化来改变线条长度。

注意!!!最新chrome浏览器可能需要在http服务器上运行~

你可以参考文章绘制音乐的频谱图(使用Analyser节点)

<input type="button" onclick="audio.play()" value="播放" /><input type="button" onclick="audio.pause()" value="暂停" /><canvas id="wrap" height="800" width="800"></canvas><script> 
 var wrap = document.getElementById("wrap"); var cxt = wrap.getContext("2d"); //获取API
 var AudioContext = AudioContext || webkitAudioContext; var context = new AudioContext; //加载媒体
 var audio = new Audio("demo.mp3"); //创建节点
 var source = context.createMediaElementSource(audio); var analyser = context.createAnalyser(); //连接:source → analyser → destination
 source.connect(analyser);
 analyser.connect(context.destination); //创建数据
 var output = new Uint8Array(360);
 (function drawSpectrum() {
 analyser.getByteFrequencyData(output);//获取频域数据
 cxt.clearRect(0, 0, wrap.width, wrap.height); //画线条
 for (var i = 0; i < 360; i++) { var value = output[i] / 8;//<===获取数据
 cxt.beginPath();
 cxt.lineWidth = 2;
 cxt.moveTo(300, 300); //R * cos (PI/180*一次旋转的角度数) ,-R * sin (PI/180*一次旋转的角度数)
 cxt.lineTo(Math.cos((i * 1) / 180 * Math.PI) * (200 + value) + 300, (- Math.sin((i * 1) / 180 * Math.PI) * (200 + value) + 300));
 cxt.stroke();
 } //画一个小圆,将线条覆盖
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.arc(300, 300, 200, 0, 2 * Math.PI, false);
 cxt.fillStyle = "#fff";
 cxt.stroke();
 cxt.fill(); //请求下一帧
 requestAnimationFrame(drawSpectrum);
 })();</script>

3.环形左右同步显示

实习步骤2后其实已经完成一大半了,不过细心的小伙伴们会发现环形最右端点上的线条间差了好多。

处理办法很多,我们用其中一个简单的办法处理,那就是让其左右对称的显示。

<input type="button" onclick="audio.play()" value="播放" /><input type="button" onclick="audio.pause()" value="暂停" /><canvas id="wrap" height="550" width="800"></canvas><script> 
 var wrap = document.getElementById("wrap"); var cxt = wrap.getContext("2d"); //获取API
 var AudioContext = AudioContext || webkitAudioContext; var context = new AudioContext; //加载媒体
 var audio = new Audio("demo.mp3"); //创建节点
 var source = context.createMediaElementSource(audio); var analyser = context.createAnalyser(); //连接:source → analyser → destination
 source.connect(analyser);
 analyser.connect(context.destination); //创建数据
 var output = new Uint8Array(361);
 (function drawSpectrum() {
 analyser.getByteFrequencyData(output);//获取频域数据
 cxt.clearRect(0, 0, wrap.width, wrap.height); //画线条
 for (var i = 0; i < output.length; i++) { var value = output[i] / 10; //绘制左半边
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.moveTo(300, 300);
 cxt.lineTo(Math.cos((i *0.5 + 90) / 180 * Math.PI) * (200 + value) + 300, (- Math.sin((i *0.5 + 90) / 180 * Math.PI) * (200 + value) + 300));
 cxt.stroke(); //绘制右半边
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.moveTo(300, 300);
 cxt.lineTo( (Math.sin((i *0.5) / 180 * Math.PI) * (200 + value) + 300),-Math.cos((i *0.5) / 180 * Math.PI) * (200 + value) + 300);
 cxt.stroke();
 } //画一个小圆,将线条覆盖
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.arc(300, 300, 200, 0, 2 * Math.PI, false);
 cxt.fillStyle = "#fff";
 cxt.stroke();
 cxt.fill(); //请求下一帧
 requestAnimationFrame(drawSpectrum);
 })();</script>

4.添加波形图

最后我们来尝试在圈内,添加一个波形图

你可以参考文章绘制音乐的波形图(使用Analyser节点)

示例

<input type="button" onclick="audio.play()" value="播放" /><input type="button" onclick="audio.pause()" value="暂停" /><canvas id="wrap" height="550" width="800"></canvas><script> 
 var wrap = document.getElementById("wrap"); var cxt = wrap.getContext("2d"); //获取API
 var AudioContext = AudioContext || webkitAudioContext; var context = new AudioContext; //加载媒体
 var audio = new Audio("demo.mp3"); //创建节点
 var source = context.createMediaElementSource(audio); var analyser = context.createAnalyser(); //连接:source → analyser → destination
 source.connect(analyser);
 analyser.connect(context.destination); //创建数据
 var output = new Uint8Array(361); //计算出采样频率44100所需的缓冲区长度
 var length = analyser.frequencyBinCount * 44100 / context.sampleRate | 0; //创建数据 
 var output2 = new Uint8Array(length);
 (function drawSpectrum() {
 analyser.getByteFrequencyData(output);//获取频域数据
 cxt.clearRect(0, 0, wrap.width, wrap.height); //画线条
 for (var i = 0; i < output.length; i++) { var value = output[i] / 10; //绘制左半边
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.moveTo(300, 300);
 cxt.lineTo(Math.cos((i * 0.5 + 90) / 180 * Math.PI) * (200 + value) + 300, (- Math.sin((i * 0.5 + 90) / 180 * Math.PI) * (200 + value) + 300));
 cxt.stroke(); //绘制右半边
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.moveTo(300, 300);
 cxt.lineTo((Math.sin((i * 0.5) / 180 * Math.PI) * (200 + value) + 300), -Math.cos((i * 0.5) / 180 * Math.PI) * (200 + value) + 300);
 cxt.stroke();
 } //画一个小圆,将线条覆盖
 cxt.beginPath();
 cxt.lineWidth = 1;
 cxt.arc(300, 300, 200, 0, 2 * Math.PI, false);
 cxt.fillStyle = "#fff";
 cxt.stroke();
 cxt.fill(); //将缓冲区的数据绘制到Canvas上 
 analyser.getByteTimeDomainData(output2); var height = 100, width = 400;
 cxt.beginPath(); for (var i = 0; i < width; i++) {
 cxt.lineTo(i + 100, 300 - (height / 2 * (output2[output2.length * i / width | 0] / 256 - 0.5)));
 }
 cxt.stroke(); //请求下一帧
 requestAnimationFrame(drawSpectrum);
 })();</script>

相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!

相关阅读:

如何使用canvas来制作好用的涂鸦画板

如何使用s-xlsx实现Excel 文件导入和导出(下)

下载本文
显示全文
专题