Web前端最新vue 音频可视化,【面试总结】
全网独播-价值千万金融项目前端架构实战从两道网易面试题-分析JavaScript底层机制RESTful架构在Nodejs下的最佳实践开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】一线互联网企业如何初始化项目-做一个自己的vue-cli思维无价,看我用Nodejs实现MVC代码优雅的秘诀-用观察者模式深度解耦模块前端高级实战,如何封装属于自己的JS库VUE组件库级组件
最后
全网独播-价值千万金融项目前端架构实战
从两道网易面试题-分析JavaScript底层机制
RESTful架构在Nodejs下的最佳实践
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
一线互联网企业如何初始化项目-做一个自己的vue-cli
思维无价,看我用Nodejs实现MVC
代码优雅的秘诀-用观察者模式深度解耦模块
前端高级实战,如何封装属于自己的JS库
VUE组件库级组件封装-高复用弹窗组件
2,当音频播放时 初始化分析器
根据MDN的文档,AudioContext
是一个专门用于音频处理的接口,并且工作原理是将AudioContext
创建出来的各种节点(AudioNode
)相互连接,音频数据流经这些节点并作出相应处理。
AudioContext()
构造方法创建了一个新的 AudioContext 对象 它代表了一个由音频模块链接而成的音频处理图,每一个模块由 AudioNode 表示。
AudioContext的createAnalyser()
方法能创建一个AnalyserNode,可以用来获取音频时间和频率数据,以及实现数据可视化。
onPlay() {
if (this.isInit) {
return;
}
let audioEle = document.getElementById("myAudio");
//初始化
var audCtx = new AudioContext(); //创建音频上下文
this.analyser = audCtx.createAnalyser();
const source = audCtx.createMediaElementSource(audioEle); //创建音频源节点
this.analyser.fftSize = 512; //一个无符号长整形 (unsigned long) 的值,代表了快速傅里叶变换(分析器)的窗口大小
//创建数组,用于接受节点分析器分析的数据
this.dataArry = new Uint8Array(this.analyser.frequencyBinCount); //这里并不是声明一个普通数组,而是需要声明一个无符号的八位整数,刚好是一个字节。并且数组长度需要刚好等于频谱图横坐标长度
source.connect(this.analyser);
this.analyser.connect(audCtx.destination);
this.isInit = true;
},
3.绘制分析器分析的结果数据
代码如下(示例):
//把分析器分析的数据不断绘制到canvas
draw() {
let cvs = document.getElementById("myCanvas");
let ctx = cvs.getContext("2d");
requestAnimationFrame(this.draw);
//清空画布
const { width, height } = cvs;
ctx.clearRect(0, 0, width, height);
//判断分析器是否初始化
if (!this.isInit) {
return;
}
//分析器节点分析出数据到数组中
this.analyser.getByteFrequencyData(this.dataArry); //让分析器节点分析当前音频源数据,把分析结果添加到数组
const len = this.dataArry.length;
const barWidth = width / len / 2;
ctx.fillStyle = "#41b883";
for (let i = 0; i < len; i++) {
const data = this.dataArry[i]; //<256
const barHeight = (data / 255) * height;
const x1 = i * barWidth + width / 2;
const x2 = width / 2 - (i + 1) * barWidth;
const y = height - barHeight;
ctx.fillRect(x1, y, barWidth, barHeight);
ctx.fillRect(x2, y, barWidth, barHeight);
}
},
[window.requestAnimationFrame()]( )")
告诉浏览器,你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
备注: 若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用 window.requestAnimationFrame(callback)
兼容说明
由于是用的是实验API,此功能某些浏览器尚在开发中,请参考浏览器兼容性表格以得到在不同浏览器中适合使用的前缀。由于该功能对应的标准文档可能被重新修订,所以在未来版本的浏览器中该功能的语法和行为可能随之改变。
歌词滚动+音频可视化全部代码
<template>
<div class="hello">
<audio
:src="music"
@timeupdate="audioTime"
controls
@play="onPlay"
id="myAudio"
></audio>
<div
:class="className"
:style="{ 'animation-duration': `${lrcTime}000ms` }"
>
{{ dataWords }}
</div>
<canvas
id="myCanvas"
style="width: 600px; height: 100px"
>
</canvas>
</div>
</template>
<script>
import music from "../assets/music.mp3";
export default {
data() {
return {
isInit: false,
className: "text load",
lrcTime: "",
music,
currenttime: "",
LRC: `[00:00.000] 作词 : 周耀辉/李焯雄
[00:01.000] 作曲 : 林健华
[00:02.000] 编曲 : 林健华
[00:15.000]忽然之间
[00:18.000]天昏地暗
[00:21.000]世界可以忽然什么都没有
[00:28.000]我想起了你
[00:32.000]再想到自己
[00:35.000]我为什么总在非常脆弱的时候
[00:40.000]怀念你
[00:43.000]''
[00:44.000]我明白太放不开你的爱
[00:49.000]太熟悉你的关怀分不开
[00:54.000]想你算是安慰还是悲哀
[00:58.000]而现在就算时针都停摆
[01:03.000]就算生命像尘埃分不开
[01:08.000]我们也许反而更相信爱
[01:24.000]''
[01:25.000]如果这天地
[01:29.000]最终会消失
[01:32.000]不想一路走来珍惜的回忆
[01:38.000]没有你
[01:40.000]''
[01:41.000]我明白太放不开你的爱
[01:46.000]太熟悉你的关怀分不开
[01:51.000]想你算是安慰还是悲哀
[01:55.000]而现在就算时针都停摆
[02:00.000]就算生命像尘埃分不开
[02:05.000]我们也许反而更相信爱
[02:34.000]''
[02:35.000]我明白太放不开你的爱
[02:40.000]太熟悉你的关怀分不开
[02:45.000]想你算是安慰还是悲哀
[02:49.000]而现在就算时针都停摆
[02:54.000]就算生命像尘埃分不开
[03:00.000]我们也许反而更相信爱`,
lrcData: "",
dataWords: "",
analyser: {},
dataArry: [],
};
},
name: "HelloWorld",
methods: {
// 当音频播放
onPlay() {
if (this.isInit) {
return;
}
let audioEle = document.getElementById("myAudio");
//初始化
var audCtx = new AudioContext(); //创建音频上下文
this.analyser = audCtx.createAnalyser();
const source = audCtx.createMediaElementSource(audioEle); //创建音频源节点
this.analyser.fftSize = 512; //一个无符号长整形 (unsigned long) 的值,代表了快速傅里叶变换(分析器)的窗口大小
//创建数组,用于接受节点分析器分析的数据
this.dataArry = new Uint8Array(this.analyser.frequencyBinCount); //这里并不是声明一个普通数组,而是需要声明一个无符号的八位整数,刚好是一个字节。并且数组长度需要刚好等于频谱图横坐标长度
source.connect(this.analyser);
this.analyser.connect(audCtx.destination);
this.isInit = true;
},
//把分析器分析的数据不断绘制到canvas
draw() {
let cvs = document.getElementById("myCanvas");
let ctx = cvs.getContext("2d");
requestAnimationFrame(this.draw);
//清空画布
const { width, height } = cvs;
ctx.clearRect(0, 0, width, height);
//判断分析器是否初始化
if (!this.isInit) {
return;
}
//分析器节点分析出数据到数组中
this.analyser.getByteFrequencyData(this.dataArry); //让分析器节点分析当前音频源数据,把分析结果添加到数组
const len = this.dataArry.length;
const barWidth = width / len / 2;
ctx.fillStyle = "#41b883";
for (let i = 0; i < len; i++) {
const data = this.dataArry[i]; //<256
const barHeight = (data / 255) * height;
const x1 = i * barWidth + width / 2;
const x2 = width / 2 - (i + 1) * barWidth;
const y = height - barHeight;
ctx.fillRect(x1, y, barWidth, barHeight);
ctx.fillRect(x2, y, barWidth, barHeight);
}
},
initCancas() {
let canvas = document.getElementById("myCanvas");
let ctx = canvas.getContext("2d");
#### 后话
-------------------------------------------------------------
**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**
对于面试,说几句个人观点。
面试,说到底是一种考试。正如我们一直批判应试教育脱离教育的本质,为了面试学习技术也脱离了技术的初心。但考试对于人才选拔的有效性是毋庸置疑的,几千年来一直如此。除非你有实力向公司证明你足够优秀,否则,还是得乖乖准备面试。这也并不妨碍你在通过面试之后按自己的方式学习。
其实在面试准备阶段,个人的收获是很大的,我也认为这是一种不错的学习方式。首先,面试问题大部分基础而且深入,这些是平时工作的基础。就好像我们之前一直不明白学习语文的意义,但它的意义就在每天的谈话间。
所谓面试造火箭,工作拧螺丝。面试往往有更高的要求,也迫使我们更专心更深入地去学习一些知识,也何尝不是一种好事。
更多推荐
所有评论(0)