欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于JavaScript實(shí)現(xiàn)簡(jiǎn)單的音樂(lè)音譜圖效果

 更新時(shí)間:2023年11月16日 16:05:03   作者:小不點(diǎn)灬  
我們經(jīng)常看到在聽(tīng)樂(lè)音的時(shí)候,會(huì)有音譜圖隨著音樂(lè)的節(jié)奏不斷變化給人視覺(jué)上的享受,那么本文我們就來(lái)通過(guò)JavaScript來(lái)實(shí)現(xiàn)這一效果,感興趣的可以了解下

我們經(jīng)常看到在聽(tīng)樂(lè)音的時(shí)候,會(huì)有音譜圖隨著音樂(lè)的節(jié)奏不斷變化給人視覺(jué)上的享受,那么我們通過(guò)js來(lái)實(shí)現(xiàn)以下這個(gè)效果,下面是簡(jiǎn)單的效果圖

首先我們需要有一個(gè)繪制音頻的函數(shù)

function draw() {    
    // 請(qǐng)求下一幀動(dòng)畫(huà)    
    animationId = requestAnimationFrame(draw);
    // 獲取音頻頻譜數(shù)據(jù)    
    analyser.getByteFrequencyData(dataArray);
    // 清空畫(huà)布    
    ctx.fillStyle = 'black';    
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    // 計(jì)算每個(gè)頻譜條的寬度    
    var barWidth = (canvas.width / bufferLength) * 2.5;    
    var barHeight;    
    var x = 0;
    // 遍歷頻譜數(shù)據(jù)數(shù)組,繪制頻譜條    
    for (var i = 0; i < bufferLength; i++) {        
        // 計(jì)算頻譜條的高度        
        barHeight = dataArray[i] / 255 * canvas.height;
        // 根據(jù)頻譜條的索引值計(jì)算顏色(彩虹色)        
        var hue = i / bufferLength * 360;        
        ctx.fillStyle = 'hsl(' + hue + ', 100%, 50%)';
        // 繪制頻譜條矩形       
        ctx.fillRect(x, canvas.height - barHeight, barWidth, barHeight);
        // 更新下一個(gè)頻譜條的起始位置        
        x += barWidth + 1;    
        
    }
    
}

這個(gè)函數(shù)是用于繪制頻譜圖的核心部分。它使用requestAnimationFrame()方法來(lái)請(qǐng)求下一幀動(dòng)畫(huà),并將自身作為回調(diào)函數(shù)。這樣可以不斷更新頻譜圖。

在函數(shù)內(nèi)部,analyser.getByteFrequencyData(dataArray)用于獲取當(dāng)前的音頻頻譜數(shù)據(jù),將數(shù)據(jù)存儲(chǔ)在dataArray數(shù)組中。

然后,畫(huà)布被清空,使用黑色填充整個(gè)畫(huà)布。

接下來(lái),通過(guò)計(jì)算每個(gè)頻譜條的寬度,以及根據(jù)頻譜數(shù)據(jù)計(jì)算每個(gè)頻譜條的高度,來(lái)確定頻譜條的繪制參數(shù)。

然后,使用彩虹色調(diào)的漸變來(lái)設(shè)置頻譜條的顏色,顏色的HSL值根據(jù)頻譜條的索引值計(jì)算。

最后,在畫(huà)布上繪制每個(gè)頻譜條的矩形,每個(gè)矩形之間留有間距。

通過(guò)不斷調(diào)用requestAnimationFrame()方法并在每一幀更新頻譜圖,可以實(shí)現(xiàn)連續(xù)的動(dòng)畫(huà)效果。

接下來(lái)我們需要分析一下音頻

document.getElementById('playButton').addEventListener('click', function() {
            if (!audioContext) {
                audioContext = new (window.AudioContext || window.webkitAudioContext)();
                analyser = audioContext.createAnalyser();
                analyser.fftSize = 2048;

                audioElement = document.createElement('audio');
                audioElement.src = '1.mp3';
                audioElement.controls = true;
                audioElement.style.display = 'none';

                document.body.appendChild(audioElement);

                var source = audioContext.createMediaElementSource(audioElement);
                source.connect(analyser);
                analyser.connect(audioContext.destination);

                bufferLength = analyser.frequencyBinCount;
                dataArray = new Uint8Array(bufferLength);
            }

            audioElement.play();
            draw();
        });

        document.getElementById('pauseButton').addEventListener('click', function() {
            audioElement.pause();
            cancelAnimationFrame(animationId);
        });

當(dāng)用戶點(diǎn)擊"播放"按鈕時(shí),創(chuàng)建一個(gè)新的AudioContext對(duì)象用于處理音頻,創(chuàng)建一個(gè)AnalyserNode對(duì)象用于分析音頻頻譜。然后創(chuàng)建一個(gè)audio元素并將其設(shè)置為要播放的音頻文件。將audio元素連接到AnalyserNode,將AnalyserNode連接到AudioContext的目標(biāo)(通常是揚(yáng)聲器)。設(shè)置頻率分析器的參數(shù),包括FFT大小。

當(dāng)用戶點(diǎn)擊"播放"按鈕時(shí),音頻開(kāi)始播放,并且在draw()函數(shù)中的requestAnimationFrame(draw)中調(diào)用的循環(huán)中,更新頻譜數(shù)據(jù)并繪制頻譜圖。首先,使用analyser.getByteFrequencyData(dataArray)獲取音頻頻譜數(shù)據(jù)。然后,通過(guò)遍歷數(shù)據(jù)數(shù)組,計(jì)算每個(gè)頻譜條的高度,并根據(jù)頻譜條的位置在畫(huà)布上繪制矩形。顏色根據(jù)頻譜條的索引值計(jì)算,使得頻譜圖呈現(xiàn)彩虹色的效果。

當(dāng)用戶點(diǎn)擊"暫停"按鈕時(shí),音頻暫停播放,并調(diào)用cancelAnimationFrame(animationId)來(lái)停止繪制頻譜圖。

請(qǐng)確保將audioElement.src中的路徑替換為你要播放的實(shí)際音頻文件的路徑。

當(dāng)然修改draw函數(shù)可以得到其他的音頻圖,比如波形圖

具體的draw代碼如下

這個(gè)函數(shù)主要用于繪制音頻的時(shí)域波形圖。它也使用了requestAnimationFrame()方法來(lái)請(qǐng)求下一幀動(dòng)畫(huà),并將自身作為回調(diào)函數(shù)。

在函數(shù)內(nèi)部,analyser.getByteTimeDomainData(dataArray)用于獲取當(dāng)前的音頻時(shí)域數(shù)據(jù),將數(shù)據(jù)存儲(chǔ)在dataArray數(shù)組中。

然后,畫(huà)布被清空,并將背景顏色設(shè)置為lime。

接下來(lái),設(shè)置線條的寬度和顏色。

然后,開(kāi)始繪制路徑。

通過(guò)計(jì)算每個(gè)數(shù)據(jù)片段的寬度,以及根據(jù)時(shí)域數(shù)據(jù)計(jì)算每個(gè)點(diǎn)的縱坐標(biāo),確定波形圖的繪制參數(shù)。

然后,根據(jù)波形點(diǎn)的位置,使用moveTo()方法將繪制路徑移動(dòng)到第一個(gè)點(diǎn)的位置,并使用lineTo()方法連接到下一個(gè)點(diǎn)的位置。這樣就形成了一條完整的波形路徑。

在遍歷完所有的數(shù)據(jù)點(diǎn)后,使用lineTo()方法將最后一個(gè)點(diǎn)連接到畫(huà)布的右側(cè)中點(diǎn),以形成閉合路徑。

最后,使用stroke()方法繪制路徑。

通過(guò)不斷調(diào)用requestAnimationFrame()方法并在每一幀更新波形圖,可以實(shí)現(xiàn)連續(xù)的動(dòng)畫(huà)效果。

function draw() {
// 請(qǐng)求下一幀動(dòng)畫(huà)
animationId = requestAnimationFrame(draw);

            // 獲取音頻時(shí)域數(shù)據(jù)
            analyser.getByteTimeDomainData(dataArray);


            // 清空畫(huà)布并設(shè)置背景顏色為lime
            ctx.fillStyle = 'lime';
            ctx.fillRect(0, 0, canvas.width, canvas.height);


            // 設(shè)置線條寬度和顏色
            ctx.lineWidth = 2;
            ctx.strokeStyle = 'black';


            // 開(kāi)始繪制路徑
            ctx.beginPath();


            // 計(jì)算每個(gè)數(shù)據(jù)片段的寬度
            var sliceWidth = canvas.width * 1.0 / bufferLength;
            var x = 0;


            // 遍歷時(shí)域數(shù)據(jù)數(shù)組,繪制波形
            for (var i = 0; i < bufferLength; i++) {
                // 將數(shù)據(jù)歸一化到范圍[-1, 1]
                var v = dataArray[i] / 128.0;
                // 計(jì)算波形點(diǎn)的縱坐標(biāo)
                var y = v * canvas.height / 2;


                if (i === 0) {
                    // 移動(dòng)到第一個(gè)點(diǎn)的位置
                    ctx.moveTo(x, y);
                } else {
                    // 連接到下一個(gè)點(diǎn)的位置
                    ctx.lineTo(x, y);
                }


                // 更新下一個(gè)點(diǎn)的橫坐標(biāo)
                x += sliceWidth;
            }


            // 連接最后一個(gè)點(diǎn)到畫(huà)布右側(cè)中點(diǎn),形成閉合路徑
            ctx.lineTo(canvas.width, canvas.height / 2);


    // 繪制路徑
   ctx.stroke();
        }

到此這篇關(guān)于基于JavaScript實(shí)現(xiàn)簡(jiǎn)單的音樂(lè)音譜圖效果的文章就介紹到這了,更多相關(guān)JavaScript音譜圖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論