<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5 Canvas酷炫可视化音频动画特效</title>
<link rel="stylesheet" type="text/css" href="css/css.css">
</head>
<body>
<div id="menu">
<a id="btStartAudioVisualization" class="bt">启动音频可视化</a>
<input id="btLoadAudio" type="file" accept="audio/*"><label id="labelLoadAudio" for="btLoadAudio" class="bt">加载音频</label>
</div>
<p id="txtStatus"></p>
<script>
var audio, audioContext, audioSrc;
var analyser, analyserBufferLength;
var audioInfo = 'Song: LAKEY INSPIRED - Chill Day';
//---
var MATHPI2 = Math.PI * 2;
//---
var w;
var h;
var btStart;
var btLoadAudio;
var labelLoadAudio;
var txtStatus;
var canvas;
var context;
var imageData;
var data;
var mouseActive = false;
var mouseDown = false;
var mousePos = { x:0, y:0 };
var fov = 250;
var speed = 0.75;//0.25;
var cubeMinHeight = 2;
var frequencyDamp = 25;
var smoothingTimeConstant = 0.65;
var fftSize = 8192;//32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768
var circleHolder = [];
var time = 0;
var colorInvertValue = 0;
var rgb = {};
rgb.r = Math.random() * MATHPI2;
rgb.g = Math.random() * MATHPI2;
rgb.b = Math.random() * MATHPI2;
var rgb2 = {};
rgb2.r = Math.random() * MATHPI2;
rgb2.g = Math.random() * MATHPI2;
rgb2.b = Math.random() * MATHPI2;
//---
/*
function getRGBColor() {
var r = Math.sin( rgb.r += 0.010 ) * 1 + 1;
var g = Math.sin( rgb.g += 0.007 ) * 1 + 1;
var b = Math.sin( rgb.b += 0.013 ) * 1 + 1;
//var r = Math.sin( rgb.r += 0.040 ) * 1 + 1;
//var g = Math.sin( rgb.g += 0.028 ) * 1 + 1;
//var b = Math.sin( rgb.b += 0.052 ) * 1 + 1;
return { r:r, g:g, b:b };
};*/
function getRGBColor( color ) {
var r = Math.sin( color.r += 0.010 ) * 1 + 1;
var g = Math.sin( color.g += 0.007 ) * 1 + 1;
var b = Math.sin( color.b += 0.013 ) * 1 + 1;
//var r = Math.sin( color.r += 0.040 ) * 1 + 1;
//var g = Math.sin( color.g += 0.028 ) * 1 + 1;
//var b = Math.sin( color.b += 0.052 ) * 1 + 1;
return { r:r, g:g, b:b };
};
function getRGBColor2( color ) {
//var r = Math.sin( color.r += 0.010 ) * 1 + 1;
//var g = Math.sin( color.g += 0.007 ) * 1 + 1;
//var b = Math.sin( color.b += 0.013 ) * 1 + 1;
var r = Math.sin( color.r += 0.040 ) * 1 + 1;
var g = Math.sin( color.g += 0.028 ) * 1 + 1;
var b = Math.sin( color.b += 0.052 ) * 1 + 1;
return { r:r, g:g, b:b };
};
function limitRGBColor( color, percent = 0.45 ) {
if ( color.r < percent ) {
color.r = percent;
}
if ( color.g < percent ) {
color.g = percent;
}
if ( color.b < percent ) {
color.b = percent;
}
};
function init() {
canvas = document.createElement( 'canvas' );
canvas.addEventListener( 'mousedown', mouseDownHandler, false );
canvas.addEventListener( 'mouseup', mouseUpHandler, false );
canvas.addEventListener( 'mousemove', mouseMoveHandler, false );
canvas.addEventListener( 'mouseenter', mouseEnterHandler, false );
canvas.addEventListener( 'mouseleave', mouseLeaveHandler, false );
document.body.appendChild( canvas );
context = canvas.getContext( '2d' );
window.addEventListener( 'resize', onResize, false );
onResize();
addCircles();
render();
clearImageData();
render();
context.putImageData( imageData, 0, 0 );
btStart = document.getElementById( 'btStartAudioVisualization' );
btStart.addEventListener( 'mousedown', userStart, false );
btLoadAudio = document.getElementById( 'btLoadAudio' );
btLoadAudio.addEventListener( 'change', loadAudioFileHandler, false );
labelLoadAudio = document.getElementById( 'labelLoadAudio' );
labelLoadAudio.style.display = 'none';
txtStatus = document.getElementById( 'txtStatus' );
txtStatus.innerHTML = 'Waiting Patiently For You... Please Click the Start Button.';
};
//---
function userStart() {
btStart.removeEventListener( 'mousedown', userStart );
btStart.addEventListener( 'mousedown', audioBtHandler, false );
btStart.innerHTML = 'Pause Audio';
btStart.style.display = 'none';
txtStatus.innerHTML = 'Loading Audio...';
audioSetup( 'audio/ak.mp3' );
animate();
};
//---
function audioSetup( url ) {
if ( audio ) {
audio.pause();
}
audio = new Audio();
audio.src = url;
audio.controls = false;
audio.loop = true;
audio.autoplay = true;
audio.crossOrigin = 'anonymous';
audio.addEventListener( 'canplaythrough', audioLoaded, false );
audioContext = new ( window.AudioContext || window.webkitAudioContext )();
analyser = audioContext.createAnalyser();
analyser.connect( audioContext.destination );
analyser.smoothingTimeConstant = smoothingTimeConstant;
analyser.fftSize = fftSize;
analyserBufferLength = analyser.frequencyBinCount;
audioSrc = audioContext.createMediaElementSource( audio );
audioSrc.connect( analyser );
};
function audioLoaded( e ) {
txtStatus.innerHTML = audioInfo;
btStart.style.display = 'inline-block';
labelLoadAudio.style.display = 'inline-block';
};
function loadAudioFileHandler( e ) {
loadFile( e );
};
function loadFile( e ) {
var input = e.target;
var reader = new FileReader();
audioInfo = input.files[ 0 ].name;
audioSetup( URL.createObjectURL( input.files[ 0 ] ) );
};
//---
function clearImageData() {
for ( var i = 0, l = data.length; i < l; i += 4 ) {
data[ i ] = 0;
data[ i + 1 ] = 0;
data[ i + 2 ] = 0;
data[ i + 3 ] = 255;
}
};
function setPixel( x, y, r, g, b, a ) {
var i = ( x + y * imageData.width ) * 4;
data[ i ] = r;
data[ i + 1 ] = g;
data[ i + 2 ] = b;
data[ i + 3 ] = a;
};
//---
function drawLine( x1, y1, x2, y2, r, g, b, a ) {
var dx = Math.abs( x2 - x1 );
var dy = Math.abs( y2 - y1 );
var sx = ( x1 < x2 ) ? 1 : -1;
var sy = ( y1 < y2 ) ? 1 : -1;
var err = dx - dy;
var lx = x1;
var ly = y1;
while ( true ) {
if ( lx > 0 && lx < w && ly > 0 && ly < h ) {
setPixel( lx, ly, r, g, b, a );
}
if ( ( lx === x2 ) && ( ly === y2 ) )
break;
var e2 = 2 * err;
if ( e2 > -dx ) {
err -= dy;
lx += sx;
}
if ( e2 < dy ) {
err += dx;
ly += sy;
}
}
};
//---
function getCirclePosition( centerX, centerY, radius, index, segments ) {
var angle = index * ( MATHPI2 / segments ) + time;
var x = centerX + Math.cos( angle ) * radius;
var y = centerY + Math.sin( angle ) * radius;
return { x:x, y:y };
};
function drawCircle( centerPosition, radius, segments ) {
var coordinates = [];
var radiusSave;
var diff = 0;//Math.floor( Math.random() * segments );
for ( var i = 0; i <= segments; i++ ) {
//var radiusRandom = radius + Math.random() * ( radius / 8 );
//var radiusRandom = radius + Math.random() * ( radius / 32 );
var radiusRandom = radius;// + ( radius / 8 );
if ( i === 0 ) {
radiusSave = radiusRandom;
}
if ( i === segments ) {
radiusRandom = radiusSave;
}
var centerX = centerPosition.x;
var centerY = centerPosition.y;
var position = getCirclePosition( centerX, centerY, radiusRandom, i, segments );
coordinates.push( { x:position.x, y:position.y, index:i + diff, radius:radiusRandom, segments:segments } );
}
return coordinates;
};
function addCircleSegment( x, y, z, audioBufferIndex ) {
var circleSegment = {};
circleSegment.x = x;
circleSegment.y = y;
//circleSegment.z = z;
circleSegment.x2d = 0;
circleSegment.y2d