drawSpectrum = (analyser) => { let canvas = $Canvas标签对象, cwidth = canvas.width, cheight = canvas.height - 2, meterWidth = 10, //width of the meters in the spectrum capHeight = 2, capStyle = '#fff', meterNum = 800 / (2), //count of the meters capYPositionArray = []; ////store the vertical position of hte caps for the preivous frame const ctx = canvas.getContext('2d'), gradient = ctx.createLinearGradient(0, 0, 0, 300); gradient.addColorStop(1, '#0f0'); gradient.addColorStop(0.5, '#ff0'); gradient.addColorStop(0, '#f00'); const drawMeter = () => { let array = newUint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(array); if (this.state.status === 0) { //fix when some sounds end the value still not back to zero for (let i = array.length - 1; i >= 0; i--) { array[i] = 0; } let allCapsReachBottom = true; for (let i = capYPositionArray.length - 1; i >= 0; i--) { allCapsReachBottom = allCapsReachBottom && (capYPositionArray[i] === 0); } if (allCapsReachBottom) { window.cancelAnimationFrame(this.state.animationId); //since the sound is stoped and animation finished, stop the requestAnimation to prevent potential memory leak,THIS IS VERY IMPORTANT! return; } } let step = Math.round(array.length / meterNum); //sample limited data from the total array ctx.clearRect(0, 0, cwidth, cheight); for (let i = 0; i < meterNum; i++) { let value = array[i * step]; // console.log(JSON.stringify(array.slice(0, 50))); if (capYPositionArray.length < Math.round(meterNum)) { capYPositionArray.push(value); } ctx.fillStyle = capStyle; //draw the cap, with transition effect if (value < capYPositionArray[i]) { ctx.fillRect(i * 12, cheight - (--capYPositionArray[i]), meterWidth, capHeight); } else { ctx.fillRect(i * 12, cheight - value, meterWidth, capHeight); capYPositionArray[i] = value; } ctx.fillStyle = gradient; //set the filllStyle to gradient for a better look ctx.fillRect(i * 12/*meterWidth+gap*/ , cheight - value + capHeight, meterWidth, cheight); //the meter } this.state.animationId = window.requestAnimationFrame(drawMeter); }; this.state.animationId = window.requestAnimationFrame(drawMeter); };