给Jplayer加上声音可视化效果

前一阵子有个网友通过之前写的一篇音频可视化的文章找到我,让我帮忙给他的音乐网站加个播放效果,自己正好没啥事做欣然答应。

由于疏于学习,基础掌握的不好,我一直以为音频可视化是通过Web audio API实现的,脑子不会转弯,总觉得只能通过这种方法载入音频:

	var audio = new Audio("hello.mp4");

然后打一套API的组合拳来读取音频数据:

	AudioContext = AudioContext || webkitAudioContext;
	context = new AudioContext;
	//加载媒体
	
	//创建节点
	source = context.createMediaElementSource(audio);
	analyser = context.createAnalyser();
	//连接:source → analyser → destination
	source.connect(analyser);
	analyser.connect(context.destination);

直到看到另一个使用Jplayer的网站才恍然大悟,完全可以获取页面上已有的audio控件来载入音频:

var audio= document.getElementById('audio');

source = context.createMediaElementSource(audio);

下面以JYMUSIC这套程序为例,写一下大概实现原理。

先在\resources\web\default\home目录的player_default.html里面加一个canvas层:

<canvas id="canvas" width="500" height="350">canvas>

然后找到\resources\web\default\assets\js目录下面的player.js,加入如下代码:


    /*音频可视化*/
    function initVisualizer(){
        window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext||window.oAudioContext;
        var player = document.getElementById('jp_audio_0');
        try {
            var audioContext = new window.AudioContext();
        } catch (e) {
            alert('你的浏览器不支持AudioContext。错误:'+e);
        }
        playerAnalyser = audioContext.createAnalyser();
        playerSource = audioContext.createMediaElementSource(player);
        canvas = document.getElementById('canvas');
        context = canvas.getContext('2d');
        capStyle = 'rgba(0,255,0,.6)';//频谱颜色
        CANVAS_WIDTH = canvas.clientWidth;
        CANVAS_HEIGHT = canvas.clientHeight;
        cheight = canvas.height - 2;
        
        capYPositionArray = [];
        //以上为变量
        playerAnalyser.connect(audioContext.destination);//声音连接到扬声器
        playerSource.connect(playerAnalyser);//截取音频信号

        playerFrequencyData = new Uint8Array(playerAnalyser.frequencyBinCount);//得到音频能量值
        
        var gradient,topXy,capHeight=2;
        var meterWidth = 8, //能量条的宽度
        gap = 4, //能量条间的间距
        steplength = meterWidth + gap,
        meterNum = CANVAS_WIDTH / steplength; //计算当前画布上能画多少条

        process();


        function process() {
playerAnalyser.getByteFrequencyData(playerFrequencyData);//得到音频能量值
playerTimeDomainData = new Uint8Array(playerAnalyser.fftSize);
requestAnimationFrame(process)
context.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
        var step = Math.floor((playerFrequencyData.length-200)/ meterNum); //计算从analyser中的采样步
        context.beginPath();
        for (var i = 0; i < meterNum; i++) {
            var value = playerFrequencyData[i * step];
            topXy = cheight - value;
            if(topXy==cheight){
                continue;
            }
            if (capYPositionArray.length < Math.round(meterNum)) {
                capYPositionArray.push(topXy); //初始化保存帽头位置的数组,将第一个画面的数据压入其中
            };
            context.fillStyle = "#fff";
            
            //定义一个渐变样式用于画图
            gradient = context.createLinearGradient(i * steplength , topXy+capHeight, i * steplength, cheight);
            gradient.addColorStop(0, 'rgba(255,0,0,.7)');
            gradient.addColorStop(1, 'rgba(61,247,0,.5)');
            context.fillStyle=gradient;
            context.fillRect(i * 12 , topXy+capHeight, meterWidth, cheight);
        }
        context.closePath();
    }
}

最终自己添加一下CSS就可以了,我用的是:

#canvas {
    position: absolute;
    bottom: 51px;
    left: 0;
    right: 0;
    margin: auto;
    transform: translateX(50%);
    box-reflect: left -2px;
    -moz-box-reflect: left -2px;
    -webkit-box-reflect: left 2px;
    -ms-box-reflect: left 2px;
    -o-box-reflect: left 2px;
    -moz-transform: rotateY(180deg);
    -o-transform: rotateY(180deg);
    pointer-events: none;
}

效果如图:
给Jplayer加上声音可视化效果_第1张图片

至于代码逻辑,可以看我前一篇文章的分析。
帮这位朋友加上效果还得到了一大笔打赏,实在是受宠若惊,这也是第一次通过博客内容收到打赏,坚定了我分享一些觉得还有用的东西的决心。

你可能感兴趣的:(HTML5)