diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..51d9923 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Chrome against localhost, with sourcemaps", + "type": "chrome", + "request": "launch", + "url": "file:///Users/peterwang/GitHub/MusicVisualizer/audio-test.html", + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + }, + { + "name": "Attach to Chrome, with sourcemaps", + "type": "chrome", + "request": "attach", + "port": 9222, + "sourceMaps": true, + "webRoot": "${workspaceRoot}" + } + ] +} \ No newline at end of file diff --git a/final/OrbitControls.js b/OrbitControls.js similarity index 100% rename from final/OrbitControls.js rename to OrbitControls.js diff --git a/final/animation.js b/animation.js similarity index 100% rename from final/animation.js rename to animation.js diff --git a/atomaudioviz b/atomaudioviz new file mode 160000 index 0000000..d6fd7a5 --- /dev/null +++ b/atomaudioviz @@ -0,0 +1 @@ +Subproject commit d6fd7a5152edf650103403560a1f510e0b7a67ad diff --git a/audio-test.html b/audio-test.html deleted file mode 100644 index df51ad6..0000000 --- a/audio-test.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - diff --git a/final/master.js b/final/master.js deleted file mode 100644 index b31b23e..0000000 --- a/final/master.js +++ /dev/null @@ -1,195 +0,0 @@ -$(document).ready(function() { - getElements(); - addEventListeners(); - initMp3Player(); - threeInit(); - frameLooper(); - loadAudioFromSC(DEFAULT_SC_MUSIC); -}); - -function getElements() { - soundcloudURL = document.getElementById("soundcloud-url"); - audio = document.getElementById("audio-player"); - volumeBar = document.getElementById("volumeBar"); - seekbar = document.getElementById("seekbar"); - pausePlay = document.getElementById("pause_play"); - currentTime = document.getElementById("currentTime"); - maxTime = document.getElementById("maxTime"); - micToggle = document.getElementById("mic_toggle"); - audioTitle = document.getElementById("audio-title"); - pulseToggle = document.getElementById("pulseToggle"); -} - -function addEventListeners() { - //event listener for when user presses enter, process the request - soundcloudURL.addEventListener("keypress", function(e) { - if(e.which === 13) { - loadAudioFromSC(soundcloudURL.value); - } - }); - - //event listeners to change the internal text - soundcloudURL.addEventListener("click", function(e) { - soundcloudURL.value = ""; - }); - soundcloudURL.addEventListener("blur", function(e) { - soundcloudURL.value = "Soundcloud URL"; - }); - - //fade in fade out of volume controls, seek bar, input div, pulse toggle - $("#volumeControl").hover(function() {$("#volumeslider").stop(true, false).fadeTo(500, 1);}, - function() {$("#volumeslider").stop(true, false).fadeTo(500, 0);}); - - $("#audio-controls").hover(function() {$("#timeControl").stop(true, false).fadeTo(500, 1);}, - function() {$("#timeControl").stop(true, false).fadeTo(500, 0);}); - - $("#audio-input").hover(function() {$("#audio-input").stop(true, false).fadeTo(500, 1);}, - function() {$("#audio-input").stop(true, false).fadeTo(500, 0); $("#soundcloud-url").trigger("blur");}); - - $("#pulseToggle").hover(function() {$("#pulseToggle").stop(true, false).fadeTo(500, 1);}, - function() {$("#pulseToggle").stop(true, false).fadeTo(500, 0);}); -} - -// animation loop -function frameLooper(){ - window.requestAnimationFrame(frameLooper); - fbc_array = new Uint8Array(analyser.frequencyBinCount); - analyser.getByteFrequencyData(fbc_array); - updateSphereSizeColor(); - cyclePulseSpheres(); - renderer.render(scene, camera); -} - -//initialize audio player and audio analyser -function initMp3Player(){ - context = new AudioContext(); - analyser = context.createAnalyser(); - analyser.fftSize = 256; - analyser.smoothingTimeConstant = smoothingConstant; - source = context.createMediaElementSource(document.getElementById("audio-player")); - source.connect(analyser); - analyser.connect(context.destination); -} - -//read audio upload from user -function readMusic(input) { - if(input.files && input.files[0]) { - audio.src = URL.createObjectURL(input.files[0]); - audioTitle.innerHTML = input.files[0].name.slice(0,-4); - playAudio(); - } -} - -//play/pause button -function toggleAudio() { - if(micToggle.dataset.state == "off") { //only allow toggling mic is off - (pausePlay.dataset.state == "pause") ? pauseAudio() : playAudio(); - } -} - -//play audio -function playAudio() { - audio.play(); - pausePlay.src = "img/pause.png"; - pausePlay.dataset.state = "pause"; -} - -//pause audio -function pauseAudio() { - audio.pause(); - pausePlay.src = "img/play.png"; - pausePlay.dataset.state = "play"; -} - -//change audio volume -function setVolume(volume) { - audio.volume = volume/100; -} - -//set max of seek bar when audio selected -function initSeekBar() { - seekbar.max = audio.duration; - maxTime.innerHTML = toMinSec(audio.duration); -} - -//update seek bar as music plays -function updateSeekBar() { - if(!mouseDown) { - seekbar.value = audio.currentTime; - currentTime.innerHTML = toMinSec(audio.currentTime); - } -} - -//jump to specified seekbar time -function seekBarMouseUp() { - audio.currentTime = seekbar.value; - mouseDown = false; -} - -//allow for seeking -function seekBarMouseDown() { - mouseDown = true; - currentTime.innerHTML = toMinSec(seekbar.value); -} - -//convert seconds to MIN:SEC format for display -function toMinSec(seconds) { - var minutes = Math.floor(seconds / 60); - var seconds = Math.floor(seconds % 60); - var results = minutes + ":" + ((seconds < 10) ? ("0" + seconds) : seconds); - return results; -} - -//load audio from soundcloud given url -function loadAudioFromSC(input) { - SC.initialize({client_id: SC_CLIENT_ID}); - SC.get("https://api.soundcloud.com/resolve", { url: input, client_id: SC_CLIENT_ID }, - function(sound) { - scData = sound; - try { - audio.src = sound.stream_url + '?client_id=' + SC_CLIENT_ID; - audioTitle.innerHTML = sound.title; - } catch(e) { - soundcloudURL.value = "Invalid Soundcloud URL"; - } - playAudio(); - }); -} - - -//toggle microphone -function toggleMic() { - if(micToggle.dataset.state == "off") { - micToggle.dataset.state = "on"; - navigator.mediaDevices.getUserMedia({audio: true, video: false}) - .then(initMicrophone) - .catch(function(e) {}); - } else { - micToggle.dataset.state = "off"; - turnOffMicrophone(); - } -} - -//initialize microphone by disconnecting audio souce from analyser and connecting mic source to the analyser -function initMicrophone(stream) { - micToggle.src = "img/mic-on.png"; - source.disconnect(); - micSource = context.createMediaStreamSource(stream); - micSource.connect(analyser); - analyser.disconnect(); //disconnects the analyser from the window audio output - pauseAudio(); //pause music if any playing -} - -//turns off microphone by disconnecting mic source and connecting audio source -function turnOffMicrophone() { - micToggle.src = "img/mic-off.png"; - micSource.disconnect(); - source.connect(analyser); - analyser.connect(context.destination); -} - -//enable/disable pulsing -function togglePulse() { - pulseToggle.innerHTML = radiusPulsingEnable ? "Pulsing Disabled" : "Pulsing Enabled"; - radiusPulsingEnable = radiusPulsingEnable ? false : true; -} diff --git a/final/index.html b/home.html similarity index 100% rename from final/index.html rename to home.html diff --git a/final/img/icon.png b/img/icon.png similarity index 100% rename from final/img/icon.png rename to img/icon.png diff --git a/final/img/mic-off.png b/img/mic-off.png similarity index 100% rename from final/img/mic-off.png rename to img/mic-off.png diff --git a/final/img/mic-on.png b/img/mic-on.png similarity index 100% rename from final/img/mic-on.png rename to img/mic-on.png diff --git a/final/img/pause.png b/img/pause.png similarity index 100% rename from final/img/pause.png rename to img/pause.png diff --git a/final/img/play.png b/img/play.png similarity index 100% rename from final/img/play.png rename to img/play.png diff --git a/final/img/volume.png b/img/volume.png similarity index 100% rename from final/img/volume.png rename to img/volume.png diff --git a/index.html b/index.html deleted file mode 100644 index 16f64ea..0000000 --- a/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - diff --git a/index.php b/index.php new file mode 100644 index 0000000..f6e1009 --- /dev/null +++ b/index.php @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/final/main.css b/main.css similarity index 97% rename from final/main.css rename to main.css index 54a11cb..8ebf772 100644 --- a/final/main.css +++ b/main.css @@ -76,8 +76,9 @@ Audio Controls } #audio-title { - margin-left: 40px; - margin-top: 5px; + position: absolute; + left: 35px; + padding-top: 5px; width: 800px; } diff --git a/master.js b/master.js index 2ffa8ca..b31b23e 100644 --- a/master.js +++ b/master.js @@ -1,37 +1,195 @@ -var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x, bar_width, bar_height; - $(document).ready(function() { - initMp3Player(); + getElements(); + addEventListeners(); + initMp3Player(); + threeInit(); + frameLooper(); + loadAudioFromSC(DEFAULT_SC_MUSIC); }); +function getElements() { + soundcloudURL = document.getElementById("soundcloud-url"); + audio = document.getElementById("audio-player"); + volumeBar = document.getElementById("volumeBar"); + seekbar = document.getElementById("seekbar"); + pausePlay = document.getElementById("pause_play"); + currentTime = document.getElementById("currentTime"); + maxTime = document.getElementById("maxTime"); + micToggle = document.getElementById("mic_toggle"); + audioTitle = document.getElementById("audio-title"); + pulseToggle = document.getElementById("pulseToggle"); +} + +function addEventListeners() { + //event listener for when user presses enter, process the request + soundcloudURL.addEventListener("keypress", function(e) { + if(e.which === 13) { + loadAudioFromSC(soundcloudURL.value); + } + }); + + //event listeners to change the internal text + soundcloudURL.addEventListener("click", function(e) { + soundcloudURL.value = ""; + }); + soundcloudURL.addEventListener("blur", function(e) { + soundcloudURL.value = "Soundcloud URL"; + }); + + //fade in fade out of volume controls, seek bar, input div, pulse toggle + $("#volumeControl").hover(function() {$("#volumeslider").stop(true, false).fadeTo(500, 1);}, + function() {$("#volumeslider").stop(true, false).fadeTo(500, 0);}); + + $("#audio-controls").hover(function() {$("#timeControl").stop(true, false).fadeTo(500, 1);}, + function() {$("#timeControl").stop(true, false).fadeTo(500, 0);}); + + $("#audio-input").hover(function() {$("#audio-input").stop(true, false).fadeTo(500, 1);}, + function() {$("#audio-input").stop(true, false).fadeTo(500, 0); $("#soundcloud-url").trigger("blur");}); + + $("#pulseToggle").hover(function() {$("#pulseToggle").stop(true, false).fadeTo(500, 1);}, + function() {$("#pulseToggle").stop(true, false).fadeTo(500, 0);}); +} + +// animation loop function frameLooper(){ window.requestAnimationFrame(frameLooper); fbc_array = new Uint8Array(analyser.frequencyBinCount); analyser.getByteFrequencyData(fbc_array); - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.fillStyle = "#00CCFF"; - bars = 100; - for (var i = 0; i < bars; i++){ - bar_x = i * 3; - bar_width = 2; - bar_height = -(fbc_array[i]/2); - ctx.fillRect(bar_x, canvas.height, bar_width, bar_height); - } + updateSphereSizeColor(); + cyclePulseSpheres(); + renderer.render(scene, camera); } +//initialize audio player and audio analyser function initMp3Player(){ context = new AudioContext(); analyser = context.createAnalyser(); - canvas = document.getElementById('analyser_render'); - ctx = canvas.getContext('2d'); + analyser.fftSize = 256; + analyser.smoothingTimeConstant = smoothingConstant; source = context.createMediaElementSource(document.getElementById("audio-player")); source.connect(analyser); analyser.connect(context.destination); - frameLooper(); } +//read audio upload from user function readMusic(input) { - var file = input.files[0]; - var objectUrl = URL.createObjectURL(file); - $("#audio-player").attr("src", objectUrl); + if(input.files && input.files[0]) { + audio.src = URL.createObjectURL(input.files[0]); + audioTitle.innerHTML = input.files[0].name.slice(0,-4); + playAudio(); + } +} + +//play/pause button +function toggleAudio() { + if(micToggle.dataset.state == "off") { //only allow toggling mic is off + (pausePlay.dataset.state == "pause") ? pauseAudio() : playAudio(); + } +} + +//play audio +function playAudio() { + audio.play(); + pausePlay.src = "img/pause.png"; + pausePlay.dataset.state = "pause"; +} + +//pause audio +function pauseAudio() { + audio.pause(); + pausePlay.src = "img/play.png"; + pausePlay.dataset.state = "play"; +} + +//change audio volume +function setVolume(volume) { + audio.volume = volume/100; +} + +//set max of seek bar when audio selected +function initSeekBar() { + seekbar.max = audio.duration; + maxTime.innerHTML = toMinSec(audio.duration); +} + +//update seek bar as music plays +function updateSeekBar() { + if(!mouseDown) { + seekbar.value = audio.currentTime; + currentTime.innerHTML = toMinSec(audio.currentTime); + } +} + +//jump to specified seekbar time +function seekBarMouseUp() { + audio.currentTime = seekbar.value; + mouseDown = false; +} + +//allow for seeking +function seekBarMouseDown() { + mouseDown = true; + currentTime.innerHTML = toMinSec(seekbar.value); +} + +//convert seconds to MIN:SEC format for display +function toMinSec(seconds) { + var minutes = Math.floor(seconds / 60); + var seconds = Math.floor(seconds % 60); + var results = minutes + ":" + ((seconds < 10) ? ("0" + seconds) : seconds); + return results; +} + +//load audio from soundcloud given url +function loadAudioFromSC(input) { + SC.initialize({client_id: SC_CLIENT_ID}); + SC.get("https://api.soundcloud.com/resolve", { url: input, client_id: SC_CLIENT_ID }, + function(sound) { + scData = sound; + try { + audio.src = sound.stream_url + '?client_id=' + SC_CLIENT_ID; + audioTitle.innerHTML = sound.title; + } catch(e) { + soundcloudURL.value = "Invalid Soundcloud URL"; + } + playAudio(); + }); +} + + +//toggle microphone +function toggleMic() { + if(micToggle.dataset.state == "off") { + micToggle.dataset.state = "on"; + navigator.mediaDevices.getUserMedia({audio: true, video: false}) + .then(initMicrophone) + .catch(function(e) {}); + } else { + micToggle.dataset.state = "off"; + turnOffMicrophone(); + } +} + +//initialize microphone by disconnecting audio souce from analyser and connecting mic source to the analyser +function initMicrophone(stream) { + micToggle.src = "img/mic-on.png"; + source.disconnect(); + micSource = context.createMediaStreamSource(stream); + micSource.connect(analyser); + analyser.disconnect(); //disconnects the analyser from the window audio output + pauseAudio(); //pause music if any playing +} + +//turns off microphone by disconnecting mic source and connecting audio source +function turnOffMicrophone() { + micToggle.src = "img/mic-off.png"; + micSource.disconnect(); + source.connect(analyser); + analyser.connect(context.destination); +} + +//enable/disable pulsing +function togglePulse() { + pulseToggle.innerHTML = radiusPulsingEnable ? "Pulsing Disabled" : "Pulsing Enabled"; + radiusPulsingEnable = radiusPulsingEnable ? false : true; } diff --git a/prelim/CanvasInput.js b/prelim/CanvasInput.js new file mode 100644 index 0000000..78b584c --- /dev/null +++ b/prelim/CanvasInput.js @@ -0,0 +1,10 @@ +/*! + * CanvasInput v1.2.3 + * http://goldfirestudios.com/blog/108/CanvasInput-HTML5-Canvas-Text-Input + * + * (c) 2013-2016, James Simpson of GoldFire Studios + * goldfirestudios.com + * + * MIT License + */ +!function(){var e=[],t=window.CanvasInput=function(t){var n=this;t=t?t:{},n._canvas=t.canvas||null,n._ctx=n._canvas?n._canvas.getContext("2d"):null,n._x=t.x||0,n._y=t.y||0,n._extraX=t.extraX||0,n._extraY=t.extraY||0,n._fontSize=t.fontSize||14,n._fontFamily=t.fontFamily||"Arial",n._fontColor=t.fontColor||"#000",n._placeHolderColor=t.placeHolderColor||"#bfbebd",n._fontWeight=t.fontWeight||"normal",n._fontStyle=t.fontStyle||"normal",n._fontShadowColor=t.fontShadowColor||"",n._fontShadowBlur=t.fontShadowBlur||0,n._fontShadowOffsetX=t.fontShadowOffsetX||0,n._fontShadowOffsetY=t.fontShadowOffsetY||0,n._readonly=t.readonly||!1,n._maxlength=t.maxlength||null,n._width=t.width||150,n._height=t.height||n._fontSize,n._padding=t.padding>=0?t.padding:5,n._borderWidth=t.borderWidth>=0?t.borderWidth:1,n._borderColor=t.borderColor||"#959595",n._borderRadius=t.borderRadius>=0?t.borderRadius:3,n._backgroundImage=t.backgroundImage||"",n._boxShadow=t.boxShadow||"1px 1px 0px rgba(255, 255, 255, 1)",n._innerShadow=t.innerShadow||"0px 0px 4px rgba(0, 0, 0, 0.4)",n._selectionColor=t.selectionColor||"rgba(179, 212, 253, 0.8)",n._placeHolder=t.placeHolder||"",n._value=(t.value||n._placeHolder)+"",n._onsubmit=t.onsubmit||function(){},n._onkeydown=t.onkeydown||function(){},n._onkeyup=t.onkeyup||function(){},n._onfocus=t.onfocus||function(){},n._onblur=t.onblur||function(){},n._cursor=!1,n._cursorPos=0,n._hasFocus=!1,n._selection=[0,0],n._wasOver=!1,n.boxShadow(n._boxShadow,!0),n._calcWH(),n._renderCanvas=document.createElement("canvas"),n._renderCanvas.setAttribute("width",n.outerW),n._renderCanvas.setAttribute("height",n.outerH),n._renderCtx=n._renderCanvas.getContext("2d"),n._shadowCanvas=document.createElement("canvas"),n._shadowCanvas.setAttribute("width",n._width+2*n._padding),n._shadowCanvas.setAttribute("height",n._height+2*n._padding),n._shadowCtx=n._shadowCanvas.getContext("2d"),"undefined"!=typeof t.backgroundGradient?(n._backgroundColor=n._renderCtx.createLinearGradient(0,0,0,n.outerH),n._backgroundColor.addColorStop(0,t.backgroundGradient[0]),n._backgroundColor.addColorStop(1,t.backgroundGradient[1])):n._backgroundColor=t.backgroundColor||"#fff",n._canvas&&(n._canvas.addEventListener("mousemove",function(e){e=e||window.event,n.mousemove(e,n)},!1),n._canvas.addEventListener("mousedown",function(e){e=e||window.event,n.mousedown(e,n)},!1),n._canvas.addEventListener("mouseup",function(e){e=e||window.event,n.mouseup(e,n)},!1)),window.addEventListener("mouseup",function(e){e=e||window.event,n._hasFocus&&!n._mouseDown&&n.blur()},!0),n._hiddenInput=document.createElement("input"),n._hiddenInput.type="text",n._hiddenInput.style.position="absolute",n._hiddenInput.style.opacity=0,n._hiddenInput.style.pointerEvents="none",n._hiddenInput.style.left=n._x+n._extraX+(n._canvas?n._canvas.offsetLeft:0)+"px",n._hiddenInput.style.top=n._y+n._extraY+(n._canvas?n._canvas.offsetTop:0)+"px",n._hiddenInput.style.width=n._width+"px",n._hiddenInput.style.height=n._height+"px",n._hiddenInput.style.zIndex=0,n._maxlength&&(n._hiddenInput.maxLength=n._maxlength),document.body.appendChild(n._hiddenInput),n._hiddenInput.value=n._value,n._hiddenInput.addEventListener("keydown",function(e){e=e||window.event,n._hasFocus&&n.keydown(e,n)}),n._hiddenInput.addEventListener("keyup",function(e){e=e||window.event,n._value=n._hiddenInput.value,n._cursorPos=n._hiddenInput.selectionStart,n._selection=[n._hiddenInput.selectionStart,n._hiddenInput.selectionEnd],n.render(),n._hasFocus&&n._onkeyup(e,n)}),e.push(n),n._inputsIndex=e.length-1,n.render()};t.prototype={canvas:function(e){var t=this;return"undefined"!=typeof e?(t._canvas=e,t._ctx=t._canvas.getContext("2d"),t.render()):t._canvas},x:function(e){var t=this;return"undefined"!=typeof e?(t._x=e,t.render()):t._x},y:function(e){var t=this;return"undefined"!=typeof e?(t._y=e,t.render()):t._y},extraX:function(e){var t=this;return"undefined"!=typeof e?(t._extraX=e,t.render()):t._extraX},extraY:function(e){var t=this;return"undefined"!=typeof e?(t._extraY=e,t.render()):t._extraY},fontSize:function(e){var t=this;return"undefined"!=typeof e?(t._fontSize=e,t.render()):t._fontSize},fontFamily:function(e){var t=this;return"undefined"!=typeof e?(t._fontFamily=e,t.render()):t._fontFamily},fontColor:function(e){var t=this;return"undefined"!=typeof e?(t._fontColor=e,t.render()):t._fontColor},placeHolderColor:function(e){var t=this;return"undefined"!=typeof e?(t._placeHolderColor=e,t.render()):t._placeHolderColor},fontWeight:function(e){var t=this;return"undefined"!=typeof e?(t._fontWeight=e,t.render()):t._fontWeight},fontStyle:function(e){var t=this;return"undefined"!=typeof e?(t._fontStyle=e,t.render()):t._fontStyle},fontShadowColor:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowColor=e,t.render()):t._fontShadowColor},fontShadowBlur:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowBlur=e,t.render()):t._fontShadowBlur},fontShadowOffsetX:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowOffsetX=e,t.render()):t._fontShadowOffsetX},fontShadowOffsetY:function(e){var t=this;return"undefined"!=typeof e?(t._fontShadowOffsetY=e,t.render()):t._fontShadowOffsetY},width:function(e){var t=this;return"undefined"!=typeof e?(t._width=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._width},height:function(e){var t=this;return"undefined"!=typeof e?(t._height=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._height},padding:function(e){var t=this;return"undefined"!=typeof e?(t._padding=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._padding},borderWidth:function(e){var t=this;return"undefined"!=typeof e?(t._borderWidth=e,t._calcWH(),t._updateCanvasWH(),t.render()):t._borderWidth},borderColor:function(e){var t=this;return"undefined"!=typeof e?(t._borderColor=e,t.render()):t._borderColor},borderRadius:function(e){var t=this;return"undefined"!=typeof e?(t._borderRadius=e,t.render()):t._borderRadius},backgroundColor:function(e){var t=this;return"undefined"!=typeof e?(t._backgroundColor=e,t.render()):t._backgroundColor},backgroundGradient:function(e){var t=this;return"undefined"!=typeof e?(t._backgroundColor=t._renderCtx.createLinearGradient(0,0,0,t.outerH),t._backgroundColor.addColorStop(0,e[0]),t._backgroundColor.addColorStop(1,e[1]),t.render()):t._backgroundColor},boxShadow:function(e,t){var n=this;if("undefined"==typeof e)return n._boxShadow;var o=e.split("px ");return n._boxShadow={x:"none"===n._boxShadow?0:parseInt(o[0],10),y:"none"===n._boxShadow?0:parseInt(o[1],10),blur:"none"===n._boxShadow?0:parseInt(o[2],10),color:"none"===n._boxShadow?"":o[3]},n._boxShadow.x<0?(n.shadowL=Math.abs(n._boxShadow.x)+n._boxShadow.blur,n.shadowR=n._boxShadow.blur+n._boxShadow.x):(n.shadowL=Math.abs(n._boxShadow.blur-n._boxShadow.x),n.shadowR=n._boxShadow.blur+n._boxShadow.x),n._boxShadow.y<0?(n.shadowT=Math.abs(n._boxShadow.y)+n._boxShadow.blur,n.shadowB=n._boxShadow.blur+n._boxShadow.y):(n.shadowT=Math.abs(n._boxShadow.blur-n._boxShadow.y),n.shadowB=n._boxShadow.blur+n._boxShadow.y),n.shadowW=n.shadowL+n.shadowR,n.shadowH=n.shadowT+n.shadowB,n._calcWH(),t?void 0:(n._updateCanvasWH(),n.render())},innerShadow:function(e){var t=this;return"undefined"!=typeof e?(t._innerShadow=e,t.render()):t._innerShadow},selectionColor:function(e){var t=this;return"undefined"!=typeof e?(t._selectionColor=e,t.render()):t._selectionColor},placeHolder:function(e){var t=this;return"undefined"!=typeof e?(t._placeHolder=e,t.render()):t._placeHolder},value:function(e){var t=this;return"undefined"!=typeof e?(t._value=e+"",t._hiddenInput.value=e+"",t._cursorPos=t._clipText().length,t.render(),t):t._value===t._placeHolder?"":t._value},onsubmit:function(e){var t=this;return"undefined"!=typeof e?(t._onsubmit=e,t):void t._onsubmit()},onkeydown:function(e){var t=this;return"undefined"!=typeof e?(t._onkeydown=e,t):void t._onkeydown()},onkeyup:function(e){var t=this;return"undefined"!=typeof e?(t._onkeyup=e,t):void t._onkeyup()},focus:function(t){var n=this;if(!n._hasFocus){n._onfocus(n);for(var o=0;o0||n._selection[1]>0;return n._hiddenInput.focus(),n._hiddenInput.selectionStart=r?n._selection[0]:n._cursorPos,n._hiddenInput.selectionEnd=r?n._selection[1]:n._cursorPos,n.render()},blur:function(e){var t=e||this;return t._onblur(t),t._cursorInterval&&clearInterval(t._cursorInterval),t._hasFocus=!1,t._cursor=!1,t._selection=[0,0],t._hiddenInput.blur(),""===t._value&&(t._value=t._placeHolder),t.render()},keydown:function(t,n){var o=t.which;t.shiftKey;if(!n._readonly&&n._hasFocus){if(n._onkeydown(t,n),65===o&&(t.ctrlKey||t.metaKey))return n.selectText(),t.preventDefault(),n.render();if(17===o||t.metaKey||t.ctrlKey)return n;if(13===o)t.preventDefault(),n._onsubmit(t,n);else if(9===o&&(t.preventDefault(),e.length>1)){var r=e[n._inputsIndex+1]?n._inputsIndex+1:0;n.blur(),setTimeout(function(){e[r].focus()},10)}return n._value=n._hiddenInput.value,n._cursorPos=n._hiddenInput.selectionStart,n._selection=[0,0],n.render()}},click:function(e,t){var n=t._mousePos(e),o=n.x,r=n.y;return t._endSelection?(delete t._endSelection,void delete t._selectionUpdated):t._canvas&&t._overInput(o,r)||!t._canvas?t._mouseDown?(t._mouseDown=!1,t.click(e,t),t.focus(t._clickPos(o,r))):void 0:t.blur()},mousemove:function(e,t){var n=t._mousePos(e),o=n.x,r=n.y,d=t._overInput(o,r);if(d&&t._canvas?(t._canvas.style.cursor="text",t._wasOver=!0):t._wasOver&&t._canvas&&(t._canvas.style.cursor="default",t._wasOver=!1),t._hasFocus&&t._selectionStart>=0){var a=t._clickPos(o,r),i=Math.min(t._selectionStart,a),_=Math.max(t._selectionStart,a);if(!d)return t._selectionUpdated=!0,t._endSelection=!0,delete t._selectionStart,void t.render();t._selection[0]===i&&t._selection[1]===_||(t._selection=[i,_],t.render())}},mousedown:function(e,t){var n=t._mousePos(e),o=n.x,r=n.y,d=t._overInput(o,r);t._mouseDown=d,t._hasFocus&&d&&(t._selectionStart=t._clickPos(o,r))},mouseup:function(e,t){var n=t._mousePos(e),o=n.x,r=n.y,d=t._clickPos(o,r)!==t._selectionStart;t._hasFocus&&t._selectionStart>=0&&t._overInput(o,r)&&d?(t._selectionUpdated=!0,delete t._selectionStart,t.render()):delete t._selectionStart,t.click(e,t)},selectText:function(e){var t=this,e=e||[0,t._value.length];return setTimeout(function(){t._selection=[e[0],e[1]],t._hiddenInput.selectionStart=e[0],t._hiddenInput.selectionEnd=e[1],t.render()},1),t},renderCanvas:function(){return this._renderCanvas},render:function(){var e=this,t=e._renderCtx,n=e.outerW,o=e.outerH,r=e._borderRadius,d=e._borderWidth,a=e.shadowW,i=e.shadowH;t&&(t.clearRect(0,0,t.canvas.width,t.canvas.height),t.shadowOffsetX=e._boxShadow.x,t.shadowOffsetY=e._boxShadow.y,t.shadowBlur=e._boxShadow.blur,t.shadowColor=e._boxShadow.color,e._borderWidth>0&&(t.fillStyle=e._borderColor,e._roundedRect(t,e.shadowL,e.shadowT,n-a,o-i,r),t.fill(),t.shadowOffsetX=0,t.shadowOffsetY=0,t.shadowBlur=0),e._drawTextBox(function(){t.shadowOffsetX=0,t.shadowOffsetY=0,t.shadowBlur=0;var _=e._clipText(),s=e._padding+e._borderWidth+e.shadowT;if(e._selection[1]>0){var u=e._textWidth(_.substring(0,e._selection[0])),l=e._textWidth(_.substring(e._selection[0],e._selection[1]));t.fillStyle=e._selectionColor,t.fillRect(s+u,s,l,e._height)}if(e._cursor){var h=e._textWidth(_.substring(0,e._cursorPos));t.fillStyle=e._fontColor,t.fillRect(s+h,s,1,e._height)}var f=e._padding+e._borderWidth+e.shadowL,c=Math.round(s+e._height/2);_=""===_&&e._placeHolder?e._placeHolder:_,t.fillStyle=""!==e._value&&e._value!==e._placeHolder?e._fontColor:e._placeHolderColor,t.font=e._fontStyle+" "+e._fontWeight+" "+e._fontSize+"px "+e._fontFamily,t.shadowColor=e._fontShadowColor,t.shadowBlur=e._fontShadowBlur,t.shadowOffsetX=e._fontShadowOffsetX,t.shadowOffsetY=e._fontShadowOffsetY,t.textAlign="left",t.textBaseline="middle",t.fillText(_,f,c);var v=e._innerShadow.split("px "),w="none"===e._innerShadow?0:parseInt(v[0],10),p="none"===e._innerShadow?0:parseInt(v[1],10),x="none"===e._innerShadow?0:parseInt(v[2],10),b="none"===e._innerShadow?"":v[3];if(x>0){var y=e._shadowCtx,S=y.canvas.width,g=y.canvas.height;y.clearRect(0,0,S,g),y.shadowBlur=x,y.shadowColor=b,y.shadowOffsetX=0,y.shadowOffsetY=p,y.fillRect(-1*n,-100,3*n,100),y.shadowOffsetX=w,y.shadowOffsetY=0,y.fillRect(S,-1*o,100,3*o),y.shadowOffsetX=0,y.shadowOffsetY=p,y.fillRect(-1*n,g,3*n,100),y.shadowOffsetX=w,y.shadowOffsetY=0,y.fillRect(-100,-1*o,100,3*o),e._roundedRect(t,d+e.shadowL,d+e.shadowT,n-2*d-a,o-2*d-i,r),t.clip(),t.drawImage(e._shadowCanvas,0,0,S,g,d+e.shadowL,d+e.shadowT,S,g)}return e._ctx&&(e._ctx.clearRect(e._x,e._y,t.canvas.width,t.canvas.height),e._ctx.drawImage(e._renderCanvas,e._x,e._y)),e}))},destroy:function(){var t=this,n=e.indexOf(t);-1!=n&&e.splice(n,1),t._hasFocus&&t.blur(),document.body.removeChild(t._hiddenInput),t._renderCanvas=null,t._shadowCanvas=null,t._renderCtx=null},_drawTextBox:function(e){var t=this,n=t._renderCtx,o=t.outerW,r=t.outerH,d=t._borderRadius,a=t._borderWidth,i=t.shadowW,_=t.shadowH;if(""===t._backgroundImage)n.fillStyle=t._backgroundColor,t._roundedRect(n,a+t.shadowL,a+t.shadowT,o-2*a-i,r-2*a-_,d),n.fill(),e();else{var s=new Image;s.src=t._backgroundImage,s.onload=function(){n.drawImage(s,0,0,s.width,s.height,a+t.shadowL,a+t.shadowT,o,r),e()}}},_clearSelection:function(){var e=this;if(e._selection[1]>0){var t=e._selection[0],n=e._selection[1];return e._value=e._value.substr(0,t)+e._value.substr(n),e._cursorPos=t,e._cursorPos=e._cursorPos<0?0:e._cursorPos,e._selection=[0,0],!0}return!1},_clipText:function(e){var t=this;e="undefined"==typeof e?t._value:e;var n=t._textWidth(e),o=n/(t._width-t._padding),r=o>1?e.substr(-1*Math.floor(e.length/o)):e;return r+""},_textWidth:function(e){var t=this,n=t._renderCtx;return n.font=t._fontStyle+" "+t._fontWeight+" "+t._fontSize+"px "+t._fontFamily,n.textAlign="left",n.measureText(e).width},_calcWH:function(){var e=this;e.outerW=e._width+2*e._padding+2*e._borderWidth+e.shadowW,e.outerH=e._height+2*e._padding+2*e._borderWidth+e.shadowH},_updateCanvasWH:function(){var e=this,t=e._renderCanvas.width,n=e._renderCanvas.height;e._renderCanvas.setAttribute("width",e.outerW),e._renderCanvas.setAttribute("height",e.outerH),e._shadowCanvas.setAttribute("width",e._width+2*e._padding),e._shadowCanvas.setAttribute("height",e._height+2*e._padding),e._ctx&&e._ctx.clearRect(e._x,e._y,t,n)},_roundedRect:function(e,t,n,o,r,d){2*d>o&&(d=o/2),2*d>r&&(d=r/2),e.beginPath(),e.moveTo(t+d,n),e.lineTo(t+o-d,n),e.quadraticCurveTo(t+o,n,t+o,n+d),e.lineTo(t+o,n+r-d),e.quadraticCurveTo(t+o,n+r,t+o-d,n+r),e.lineTo(t+d,n+r),e.quadraticCurveTo(t,n+r,t,n+r-d),e.lineTo(t,n+d),e.quadraticCurveTo(t,n,t+d,n),e.closePath()},_overInput:function(e,t){var n=this,o=e>=n._x+n._extraX,r=e<=n._x+n._extraX+n._width+2*n._padding,d=t>=n._y+n._extraY,a=t<=n._y+n._extraY+n._height+2*n._padding;return o&&r&&d&&a},_clickPos:function(e){var t=this,n=t._value;t._value===t._placeHolder&&(n="");var o=t._clipText(n),r=0,d=o.length;if(e-(t._x+t._extraX)=e-(t._x+t._extraX)){d=a;break}return d},_mousePos:function(e){var t=e.target,n=document.defaultView.getComputedStyle(t,void 0),o=parseInt(n.paddingLeft,10)||0,r=parseInt(n.paddingLeft,10)||0,d=parseInt(n.borderLeftWidth,10)||0,a=parseInt(n.borderLeftWidth,10)||0,i=document.body.parentNode.offsetTop||0,_=document.body.parentNode.offsetLeft||0,s=0,u=0;if("undefined"!=typeof t.offsetParent)do s+=t.offsetLeft,u+=t.offsetTop;while(t=t.offsetParent);return s+=o+d+_,u+=r+a+i,{x:e.pageX-s,y:e.pageY-u}}}}(); \ No newline at end of file diff --git a/testing/I See Fire (Kygo Remix).mp3 b/prelim/I See Fire (Kygo Remix).mp3 similarity index 100% rename from testing/I See Fire (Kygo Remix).mp3 rename to prelim/I See Fire (Kygo Remix).mp3 diff --git a/prelim/OrbitControls.js b/prelim/OrbitControls.js new file mode 100644 index 0000000..e7e1c6a --- /dev/null +++ b/prelim/OrbitControls.js @@ -0,0 +1,1115 @@ +/** + * @author qiao / https://github.com/qiao + * @author mrdoob / http://mrdoob.com + * @author alteredq / http://alteredqualia.com/ + * @author WestLangley / http://github.com/WestLangley + * @author erich666 / http://erichaines.com + */ +/*global THREE, console */ + +( function () { + + function OrbitConstraint ( object ) { + + this.object = object; + + // "target" sets the location of focus, where the object orbits around + // and where it pans with respect to. + this.target = new THREE.Vector3(); + + // Limits to how far you can dolly in and out ( PerspectiveCamera only ) + this.minDistance = 0; + this.maxDistance = Infinity; + + // Limits to how far you can zoom in and out ( OrthographicCamera only ) + this.minZoom = 0; + this.maxZoom = Infinity; + + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + this.minPolarAngle = 0; // radians + this.maxPolarAngle = Math.PI; // radians + + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + this.minAzimuthAngle = - Infinity; // radians + this.maxAzimuthAngle = Infinity; // radians + + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + this.enableDamping = false; + this.dampingFactor = 0.25; + + //////////// + // internals + + var scope = this; + + var EPS = 0.000001; + + // Current position in spherical coordinate system. + var theta; + var phi; + + // Pending changes + var phiDelta = 0; + var thetaDelta = 0; + var scale = 1; + var panOffset = new THREE.Vector3(); + var zoomChanged = false; + + // API + + this.getPolarAngle = function () { + + return phi; + + }; + + this.getAzimuthalAngle = function () { + + return theta; + + }; + + this.rotateLeft = function ( angle ) { + + thetaDelta -= angle; + + }; + + this.rotateUp = function ( angle ) { + + phiDelta -= angle; + + }; + + // pass in distance in world space to move left + this.panLeft = function() { + + var v = new THREE.Vector3(); + + return function panLeft ( distance ) { + + var te = this.object.matrix.elements; + + // get X column of matrix + v.set( te[ 0 ], te[ 1 ], te[ 2 ] ); + v.multiplyScalar( - distance ); + + panOffset.add( v ); + + }; + + }(); + + // pass in distance in world space to move up + this.panUp = function() { + + var v = new THREE.Vector3(); + + return function panUp ( distance ) { + + var te = this.object.matrix.elements; + + // get Y column of matrix + v.set( te[ 4 ], te[ 5 ], te[ 6 ] ); + v.multiplyScalar( distance ); + + panOffset.add( v ); + + }; + + }(); + + // pass in x,y of change desired in pixel space, + // right and down are positive + this.pan = function ( deltaX, deltaY, screenWidth, screenHeight ) { + + if ( scope.object instanceof THREE.PerspectiveCamera ) { + + // perspective + var position = scope.object.position; + var offset = position.clone().sub( scope.target ); + var targetDistance = offset.length(); + + // half of the fov is center to top of screen + targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); + + // we actually don't use screenWidth, since perspective camera is fixed to screen height + scope.panLeft( 2 * deltaX * targetDistance / screenHeight ); + scope.panUp( 2 * deltaY * targetDistance / screenHeight ); + + } else if ( scope.object instanceof THREE.OrthographicCamera ) { + + // orthographic + scope.panLeft( deltaX * ( scope.object.right - scope.object.left ) / screenWidth ); + scope.panUp( deltaY * ( scope.object.top - scope.object.bottom ) / screenHeight ); + + } else { + + // camera neither orthographic or perspective + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); + + } + + }; + + this.dollyIn = function ( dollyScale ) { + + if ( scope.object instanceof THREE.PerspectiveCamera ) { + + scale /= dollyScale; + + } else if ( scope.object instanceof THREE.OrthographicCamera ) { + + scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + + } + + }; + + this.dollyOut = function ( dollyScale ) { + + if ( scope.object instanceof THREE.PerspectiveCamera ) { + + scale *= dollyScale; + + } else if ( scope.object instanceof THREE.OrthographicCamera ) { + + scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) ); + scope.object.updateProjectionMatrix(); + zoomChanged = true; + + } else { + + console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); + + } + + }; + + this.update = function() { + + var offset = new THREE.Vector3(); + + // so camera.up is the orbit axis + var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) ); + var quatInverse = quat.clone().inverse(); + + var lastPosition = new THREE.Vector3(); + var lastQuaternion = new THREE.Quaternion(); + + return function () { + + var position = this.object.position; + + offset.copy( position ).sub( this.target ); + + // rotate offset to "y-axis-is-up" space + offset.applyQuaternion( quat ); + + // angle from z-axis around y-axis + + theta = Math.atan2( offset.x, offset.z ); + + // angle from y-axis + + phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y ); + + theta += thetaDelta; + phi += phiDelta; + + // restrict theta to be between desired limits + theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) ); + + // restrict phi to be between desired limits + phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) ); + + // restrict phi to be betwee EPS and PI-EPS + phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) ); + + var radius = offset.length() * scale; + + // restrict radius to be between desired limits + radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) ); + + // move target to panned location + this.target.add( panOffset ); + + offset.x = radius * Math.sin( phi ) * Math.sin( theta ); + offset.y = radius * Math.cos( phi ); + offset.z = radius * Math.sin( phi ) * Math.cos( theta ); + + // rotate offset back to "camera-up-vector-is-up" space + offset.applyQuaternion( quatInverse ); + + position.copy( this.target ).add( offset ); + + this.object.lookAt( this.target ); + + if ( this.enableDamping === true ) { + + thetaDelta *= ( 1 - this.dampingFactor ); + phiDelta *= ( 1 - this.dampingFactor ); + + } else { + + thetaDelta = 0; + phiDelta = 0; + + } + + scale = 1; + panOffset.set( 0, 0, 0 ); + + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + + if ( zoomChanged || + lastPosition.distanceToSquared( this.object.position ) > EPS || + 8 * ( 1 - lastQuaternion.dot( this.object.quaternion ) ) > EPS ) { + + lastPosition.copy( this.object.position ); + lastQuaternion.copy( this.object.quaternion ); + zoomChanged = false; + + return true; + + } + + return false; + + }; + + }(); + + }; + + + // This set of controls performs orbiting, dollying (zooming), and panning. It maintains + // the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is + // supported. + // + // Orbit - left mouse / touch: one finger move + // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish + // Pan - right mouse, or arrow keys / touch: three finter swipe + + THREE.OrbitControls = function ( object, domElement ) { + + var constraint = new OrbitConstraint( object ); + + this.domElement = ( domElement !== undefined ) ? domElement : document; + + // API + + Object.defineProperty( this, 'constraint', { + + get: function() { + + return constraint; + + } + + } ); + + this.getPolarAngle = function () { + + return constraint.getPolarAngle(); + + }; + + this.getAzimuthalAngle = function () { + + return constraint.getAzimuthalAngle(); + + }; + + // Set to false to disable this control + this.enabled = true; + + // center is old, deprecated; use "target" instead + this.center = this.target; + + // This option actually enables dollying in and out; left as "zoom" for + // backwards compatibility. + // Set to false to disable zooming + this.enableZoom = true; + this.zoomSpeed = 1.0; + + // Set to false to disable rotating + this.enableRotate = true; + this.rotateSpeed = 1.0; + + // Set to false to disable panning + this.enablePan = true; + this.keyPanSpeed = 7.0; // pixels moved per arrow key push + + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + this.autoRotate = false; + this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + + // Set to false to disable use of the keys + this.enableKeys = true; + + // The four arrow keys + this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + + // Mouse buttons + this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT }; + + //////////// + // internals + + var scope = this; + + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + + var panStart = new THREE.Vector2(); + var panEnd = new THREE.Vector2(); + var panDelta = new THREE.Vector2(); + + var dollyStart = new THREE.Vector2(); + var dollyEnd = new THREE.Vector2(); + var dollyDelta = new THREE.Vector2(); + + var STATE = { NONE : - 1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 }; + + var state = STATE.NONE; + + // for reset + + this.target0 = this.target.clone(); + this.position0 = this.object.position.clone(); + this.zoom0 = this.object.zoom; + + // events + + var changeEvent = { type: 'change' }; + var startEvent = { type: 'start' }; + var endEvent = { type: 'end' }; + + // pass in x,y of change desired in pixel space, + // right and down are positive + function pan( deltaX, deltaY ) { + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + constraint.pan( deltaX, deltaY, element.clientWidth, element.clientHeight ); + + } + + this.update = function () { + + if ( this.autoRotate && state === STATE.NONE ) { + + constraint.rotateLeft( getAutoRotationAngle() ); + + } + + if ( constraint.update() === true ) { + + this.dispatchEvent( changeEvent ); + + } + + }; + + this.reset = function () { + + state = STATE.NONE; + + this.target.copy( this.target0 ); + this.object.position.copy( this.position0 ); + this.object.zoom = this.zoom0; + + this.object.updateProjectionMatrix(); + this.dispatchEvent( changeEvent ); + + this.update(); + + }; + + function getAutoRotationAngle() { + + return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; + + } + + function getZoomScale() { + + return Math.pow( 0.95, scope.zoomSpeed ); + + } + + function onMouseDown( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + if ( event.button === scope.mouseButtons.ORBIT ) { + + if ( scope.enableRotate === false ) return; + + state = STATE.ROTATE; + + rotateStart.set( event.clientX, event.clientY ); + + } else if ( event.button === scope.mouseButtons.ZOOM ) { + + if ( scope.enableZoom === false ) return; + + state = STATE.DOLLY; + + dollyStart.set( event.clientX, event.clientY ); + + } else if ( event.button === scope.mouseButtons.PAN ) { + + if ( scope.enablePan === false ) return; + + state = STATE.PAN; + + panStart.set( event.clientX, event.clientY ); + + } + + if ( state !== STATE.NONE ) { + + document.addEventListener( 'mousemove', onMouseMove, false ); + document.addEventListener( 'mouseup', onMouseUp, false ); + scope.dispatchEvent( startEvent ); + + } + + } + + function onMouseMove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + if ( state === STATE.ROTATE ) { + + if ( scope.enableRotate === false ) return; + + rotateEnd.set( event.clientX, event.clientY ); + rotateDelta.subVectors( rotateEnd, rotateStart ); + + // rotating across whole screen goes 360 degrees around + constraint.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); + + // rotating up and down along whole screen attempts to go 360, but limited to 180 + constraint.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); + + rotateStart.copy( rotateEnd ); + + } else if ( state === STATE.DOLLY ) { + + if ( scope.enableZoom === false ) return; + + dollyEnd.set( event.clientX, event.clientY ); + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + constraint.dollyIn( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + constraint.dollyOut( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + } else if ( state === STATE.PAN ) { + + if ( scope.enablePan === false ) return; + + panEnd.set( event.clientX, event.clientY ); + panDelta.subVectors( panEnd, panStart ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + } + + if ( state !== STATE.NONE ) scope.update(); + + } + + function onMouseUp( /* event */ ) { + + if ( scope.enabled === false ) return; + + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + scope.dispatchEvent( endEvent ); + state = STATE.NONE; + + } + + function onMouseWheel( event ) { + + if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return; + + event.preventDefault(); + event.stopPropagation(); + + var delta = 0; + + if ( event.wheelDelta !== undefined ) { + + // WebKit / Opera / Explorer 9 + + delta = event.wheelDelta; + + } else if ( event.detail !== undefined ) { + + // Firefox + + delta = - event.detail; + + } + + if ( delta > 0 ) { + + constraint.dollyOut( getZoomScale() ); + + } else if ( delta < 0 ) { + + constraint.dollyIn( getZoomScale() ); + + } + + scope.update(); + scope.dispatchEvent( startEvent ); + scope.dispatchEvent( endEvent ); + + } + + function onKeyDown( event ) { + + if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; + + switch ( event.keyCode ) { + + case scope.keys.UP: + pan( 0, scope.keyPanSpeed ); + scope.update(); + break; + + case scope.keys.BOTTOM: + pan( 0, - scope.keyPanSpeed ); + scope.update(); + break; + + case scope.keys.LEFT: + pan( scope.keyPanSpeed, 0 ); + scope.update(); + break; + + case scope.keys.RIGHT: + pan( - scope.keyPanSpeed, 0 ); + scope.update(); + break; + + } + + } + + function touchstart( event ) { + + if ( scope.enabled === false ) return; + + switch ( event.touches.length ) { + + case 1: // one-fingered touch: rotate + + if ( scope.enableRotate === false ) return; + + state = STATE.TOUCH_ROTATE; + + rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + break; + + case 2: // two-fingered touch: dolly + + if ( scope.enableZoom === false ) return; + + state = STATE.TOUCH_DOLLY; + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + var distance = Math.sqrt( dx * dx + dy * dy ); + dollyStart.set( 0, distance ); + break; + + case 3: // three-fingered touch: pan + + if ( scope.enablePan === false ) return; + + state = STATE.TOUCH_PAN; + + panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + break; + + default: + + state = STATE.NONE; + + } + + if ( state !== STATE.NONE ) scope.dispatchEvent( startEvent ); + + } + + function touchmove( event ) { + + if ( scope.enabled === false ) return; + + event.preventDefault(); + event.stopPropagation(); + + var element = scope.domElement === document ? scope.domElement.body : scope.domElement; + + switch ( event.touches.length ) { + + case 1: // one-fingered touch: rotate + + if ( scope.enableRotate === false ) return; + if ( state !== STATE.TOUCH_ROTATE ) return; + + rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + rotateDelta.subVectors( rotateEnd, rotateStart ); + + // rotating across whole screen goes 360 degrees around + constraint.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed ); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + constraint.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed ); + + rotateStart.copy( rotateEnd ); + + scope.update(); + break; + + case 2: // two-fingered touch: dolly + + if ( scope.enableZoom === false ) return; + if ( state !== STATE.TOUCH_DOLLY ) return; + + var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; + var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; + var distance = Math.sqrt( dx * dx + dy * dy ); + + dollyEnd.set( 0, distance ); + dollyDelta.subVectors( dollyEnd, dollyStart ); + + if ( dollyDelta.y > 0 ) { + + constraint.dollyOut( getZoomScale() ); + + } else if ( dollyDelta.y < 0 ) { + + constraint.dollyIn( getZoomScale() ); + + } + + dollyStart.copy( dollyEnd ); + + scope.update(); + break; + + case 3: // three-fingered touch: pan + + if ( scope.enablePan === false ) return; + if ( state !== STATE.TOUCH_PAN ) return; + + panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); + panDelta.subVectors( panEnd, panStart ); + + pan( panDelta.x, panDelta.y ); + + panStart.copy( panEnd ); + + scope.update(); + break; + + default: + + state = STATE.NONE; + + } + + } + + function touchend( /* event */ ) { + + if ( scope.enabled === false ) return; + + scope.dispatchEvent( endEvent ); + state = STATE.NONE; + + } + + function contextmenu( event ) { + + event.preventDefault(); + + } + + this.dispose = function() { + + this.domElement.removeEventListener( 'contextmenu', contextmenu, false ); + this.domElement.removeEventListener( 'mousedown', onMouseDown, false ); + this.domElement.removeEventListener( 'mousewheel', onMouseWheel, false ); + this.domElement.removeEventListener( 'MozMousePixelScroll', onMouseWheel, false ); // firefox + + this.domElement.removeEventListener( 'touchstart', touchstart, false ); + this.domElement.removeEventListener( 'touchend', touchend, false ); + this.domElement.removeEventListener( 'touchmove', touchmove, false ); + + document.removeEventListener( 'mousemove', onMouseMove, false ); + document.removeEventListener( 'mouseup', onMouseUp, false ); + + window.removeEventListener( 'keydown', onKeyDown, false ); + + } + + this.domElement.addEventListener( 'contextmenu', contextmenu, false ); + + this.domElement.addEventListener( 'mousedown', onMouseDown, false ); + this.domElement.addEventListener( 'mousewheel', onMouseWheel, false ); + this.domElement.addEventListener( 'MozMousePixelScroll', onMouseWheel, false ); // firefox + + this.domElement.addEventListener( 'touchstart', touchstart, false ); + this.domElement.addEventListener( 'touchend', touchend, false ); + this.domElement.addEventListener( 'touchmove', touchmove, false ); + + window.addEventListener( 'keydown', onKeyDown, false ); + + // force an update at start + this.update(); + + }; + + THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype ); + THREE.OrbitControls.prototype.constructor = THREE.OrbitControls; + + Object.defineProperties( THREE.OrbitControls.prototype, { + + object: { + + get: function () { + + return this.constraint.object; + + } + + }, + + target: { + + get: function () { + + return this.constraint.target; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: target is now immutable. Use target.set() instead.' ); + this.constraint.target.copy( value ); + + } + + }, + + minDistance : { + + get: function () { + + return this.constraint.minDistance; + + }, + + set: function ( value ) { + + this.constraint.minDistance = value; + + } + + }, + + maxDistance : { + + get: function () { + + return this.constraint.maxDistance; + + }, + + set: function ( value ) { + + this.constraint.maxDistance = value; + + } + + }, + + minZoom : { + + get: function () { + + return this.constraint.minZoom; + + }, + + set: function ( value ) { + + this.constraint.minZoom = value; + + } + + }, + + maxZoom : { + + get: function () { + + return this.constraint.maxZoom; + + }, + + set: function ( value ) { + + this.constraint.maxZoom = value; + + } + + }, + + minPolarAngle : { + + get: function () { + + return this.constraint.minPolarAngle; + + }, + + set: function ( value ) { + + this.constraint.minPolarAngle = value; + + } + + }, + + maxPolarAngle : { + + get: function () { + + return this.constraint.maxPolarAngle; + + }, + + set: function ( value ) { + + this.constraint.maxPolarAngle = value; + + } + + }, + + minAzimuthAngle : { + + get: function () { + + return this.constraint.minAzimuthAngle; + + }, + + set: function ( value ) { + + this.constraint.minAzimuthAngle = value; + + } + + }, + + maxAzimuthAngle : { + + get: function () { + + return this.constraint.maxAzimuthAngle; + + }, + + set: function ( value ) { + + this.constraint.maxAzimuthAngle = value; + + } + + }, + + enableDamping : { + + get: function () { + + return this.constraint.enableDamping; + + }, + + set: function ( value ) { + + this.constraint.enableDamping = value; + + } + + }, + + dampingFactor : { + + get: function () { + + return this.constraint.dampingFactor; + + }, + + set: function ( value ) { + + this.constraint.dampingFactor = value; + + } + + }, + + // backward compatibility + + noZoom: { + + get: function () { + + console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); + return ! this.enableZoom; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); + this.enableZoom = ! value; + + } + + }, + + noRotate: { + + get: function () { + + console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); + return ! this.enableRotate; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); + this.enableRotate = ! value; + + } + + }, + + noPan: { + + get: function () { + + console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); + return ! this.enablePan; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); + this.enablePan = ! value; + + } + + }, + + noKeys: { + + get: function () { + + console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); + return ! this.enableKeys; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); + this.enableKeys = ! value; + + } + + }, + + staticMoving : { + + get: function () { + + console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); + return ! this.constraint.enableDamping; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); + this.constraint.enableDamping = ! value; + + } + + }, + + dynamicDampingFactor : { + + get: function () { + + console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); + return this.constraint.dampingFactor; + + }, + + set: function ( value ) { + + console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); + this.constraint.dampingFactor = value; + + } + + } + + } ); + +}() ); \ No newline at end of file diff --git a/prelim/analysis.js b/prelim/analysis.js new file mode 100644 index 0000000..e465ac9 --- /dev/null +++ b/prelim/analysis.js @@ -0,0 +1,8 @@ +var audioCtx = new (window.AudioContext || window.webkitAudioContext); +var analyser = audioCtx.createAnalyser(); +analyser.fftSize = 256; + +var audioSrc = document.getElementById('music'); + +audioSrc.connect(analyser); + diff --git a/audio-control-working/index.html b/prelim/audio-control-working/index.html similarity index 100% rename from audio-control-working/index.html rename to prelim/audio-control-working/index.html diff --git a/audio-control-working/master.js b/prelim/audio-control-working/master.js similarity index 100% rename from audio-control-working/master.js rename to prelim/audio-control-working/master.js diff --git a/prelim/audio-test.html b/prelim/audio-test.html new file mode 100644 index 0000000..f94ff71 --- /dev/null +++ b/prelim/audio-test.html @@ -0,0 +1,56 @@ + + + + + Audio Visualizer + + + + + + + + + + + +
+
+ Soundcloud: +
+
+
+ I See Fire (Kygo Remix).mp3 +
+
+
+ File: +
+ + + +
+
+ +
+
+ + +
+
+
+ Volume + 100 +
+
+ +
+ 0:00 + + 0:00 +
+ + + diff --git a/fft-working/index.html b/prelim/fft-working/index.html similarity index 100% rename from fft-working/index.html rename to prelim/fft-working/index.html diff --git a/fft-working/master.js b/prelim/fft-working/master.js similarity index 100% rename from fft-working/master.js rename to prelim/fft-working/master.js diff --git a/prelim/main.css b/prelim/main.css new file mode 100644 index 0000000..c715464 --- /dev/null +++ b/prelim/main.css @@ -0,0 +1,71 @@ +html, body { + margin: 0; + padding: 0; + font-family: 'Helvetica'; + font-weight: 100; + color: #FFF; +} + +#input { + position: absolute; + padding-top: 10px; +} + +[contentEditable=true]:empty:not(:focus):before { + content:attr(data-ph); +} + +input[type=range]:focus { + outline: none; +} + +input[type=range]::-webkit-slider-runnable-track { + width: 300px; + height: 2px; + background: #cdd7dd; + border: none; + border-radius: 3px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 12px; + width: 12px; + border-radius: 50%; + margin-top: -5px; + background: #fafbfb; +} + +#sc-url { + min-width: 500px; + border-bottom: #cdd7dd 1px solid; + z-index: 1; +} + +#canvas { + position: absolute; + top: 15%; +} + +#controls { + position: absolute; + top: 20%; +} + +#volumeControl { + position: absolute; + bottom: 10px; + z-index: 1; +} + +#timeControl { + position: absolute; + bottom: 5px; + left: 50%; + z-index: 1; +} + +#soundcloud-url { + min-width: 500px; +} \ No newline at end of file diff --git a/prelim/master.js b/prelim/master.js new file mode 100644 index 0000000..cf49810 --- /dev/null +++ b/prelim/master.js @@ -0,0 +1,168 @@ +$(document).ready(function() { + threeInit(); + initMp3Player(); + getElements(); + +}); + +function getElements() { + audio = document.getElementById("audio-player"); + volumeBar = document.getElementById("volumeBar"); + seekbar = document.getElementById("seekbar"); + pausePlay = document.getElementById("pause_play"); + currentTime = document.getElementById("currentTime"); + maxTime = document.getElementById("maxTime"); + volumeValue = document.getElementById("volumeValue"); + repeatToggle = document.getElementById("repeat_toggle"); + + soundcloudURL = document.getElementById("sc-url"); + $("#sc-url").hover(function() {$("#sc-url").focus();}, + function() {$("#sc-url").blur();}); + $("#volumeslider").click(function() {$("#volumeslider").focus();}); + $("#seekbar").click(function() {$("#seekbar").focus();}); + + //event listener for when user presses enter + soundcloudURL.addEventListener("keypress", function(e) { + if(e.which === 13) { + loadAudioFromSC($("#sc-url").text()); + console.log($("#sc-url").text()) + e.preventDefault(); + } + }); +} + +// animation loop +function frameLooper(){ + window.requestAnimationFrame(frameLooper); + fbc_array = new Uint8Array(analyser.frequencyBinCount); + analyser.getByteFrequencyData(fbc_array); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.fillStyle = "#00CCFF"; + bars = 128; + for (var i = 0; i < bars; i++){ + bar_x = i * 3; + bar_width = 2; + bar_height = -(fbc_array[i*2]/2); + ctx.fillRect(bar_x, canvas.height, bar_width, bar_height); + } + updateSpheres(); +} + +function updateSpheres() { + var len = spheres.length; + var change = function(i) { + var val = fbc_array[i] == 0 ? 50 : fbc_array[i]; + var val2 = fbc_array[i+10] == 0 ? 100 : fbc_array[i+10]; + var val3 = fbc_array[i+20] == 0 ? 150 : fbc_array[i+20]; + // hex = (val << 16) + (val << 8) + val; + // spheres[i].material.color = new THREE.Color(hex); + spheres[i].material.color = new THREE.Color(val/300, val2/300, val3/300); + // var size = val == 0 ? 0.9 : Math.log(Math.log(val)); + var size = val == 0 ? 0.9 : val/240; + spheres[i].scale.set(size, size, size); + } + for (var i=0; i + + My first Three.js app + + + + + + + \ No newline at end of file diff --git a/prelim/vars.js b/prelim/vars.js new file mode 100644 index 0000000..0985d3e --- /dev/null +++ b/prelim/vars.js @@ -0,0 +1,13 @@ +// node analysis +var canvas, ctx, source, context, analyser, fbc_array, bars, bar_x, bar_width, bar_height; + +// three.js +var scene, aspectRatio, camera, renderer, spheres, controls; + +// player +var audio, volumeBar, seekBar, pausePlay, currentTime, maxTime, volumeValue, repeatToggle; +var mouseDown = false; + +// SoundCloud +var SC_CLIENT_ID = "57752f80398a70ff5cacb186de7e75d4"; +var scData; \ No newline at end of file diff --git a/youtube-audio-test.html b/prelim/youtube-audio-test.html similarity index 100% rename from youtube-audio-test.html rename to prelim/youtube-audio-test.html diff --git a/final/threesetup.js b/threesetup.js similarity index 100% rename from final/threesetup.js rename to threesetup.js diff --git a/final/vars.js b/vars.js similarity index 100% rename from final/vars.js rename to vars.js