summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJules Laplace <jules@okfoc.us>2016-09-11 15:49:18 -0400
committerJules Laplace <jules@okfoc.us>2016-09-11 15:49:18 -0400
commit642a0e99cfb4aeaa71cc1ac51739608ef6225b99 (patch)
tree450d97fa941216306471f5a99f55c291f3e39bd0
parent5d18cc7380a076a0b02dff6ef47c85685d317d7e (diff)
js/vendor/StartAudioContext.js
-rw-r--r--env.js12
-rw-r--r--index.html30
-rw-r--r--js/vendor/StartAudioContext.js180
3 files changed, 220 insertions, 2 deletions
diff --git a/env.js b/env.js
index 04fb6fb..ddfef4a 100644
--- a/env.js
+++ b/env.js
@@ -23,6 +23,18 @@ var environment = (function(){
environment.ready = function(){
environment.build()
environment.bind()
+ if (is_mobile) {
+ environment.request_audio_context()
+ }
+ }
+ environment.request_audio_context = function(){
+ var element = $("<div>", {"id" : "MobileStart"}).appendTo("body")
+ var button = $("<div>").attr("id", "Button").text("Enter").appendTo(element)
+ StartAudioContext.setContext(Tone.context)
+ StartAudioContext.on(button)
+ StartAudioContext.onStarted(function(){
+ element.remove()
+ })
}
environment.build = function(){
environment.scale()
diff --git a/index.html b/index.html
index fcec2b2..91b0e3a 100644
--- a/index.html
+++ b/index.html
@@ -11,6 +11,31 @@ circle { cursor: pointer }
input[type=text] { width: 30px }
#mobile_controls { display: none }
.mobile #mobile_controls { display: inline }
+
+#MobileStart {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: 10000;
+ top: 0px;
+ left: 0px;
+ background-color: rgba(0, 0, 0, 0.8);
+}
+#MobileStart #Button {
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ background-color: #7F33ED;
+ color: white;
+ font-family: monospace;
+ border-radius: 3px;
+ margin-top: -40px;
+ margin-left: -40px;
+ width: 80px;
+ height: 80px;
+ text-align: center;
+ line-height: 80px; }
+
</style>
</head>
<body class="loading">
@@ -53,13 +78,14 @@ input[type=text] { width: 30px }
<script src="./js/vendor/oktween.js"></script>
<script src="./js/vendor/util.js"></script>
<script src="./js/vendor/wheel.js"></script>
+<script src="./js/vendor/Tone.min.js"></script>
+<script src="./js/vendor/intersect.js"></script>
+<script src="./js/vendor/StartAudioContext.js"></script>
<script src="./js/mx/mx.js"></script>
<script src="./js/mx/mx.scene.js"></script>
<script src="./js/mx/mx.followingOrbitCamera.js"></script>
<script src="./js/lib/canvas_loader.js"></script>
<script src="./js/lib/snapmx.js"></script>
-<script src="./js/vendor/Tone.min.js"></script>
-<script src="./js/vendor/intersect.js"></script>
<script src="env.js"></script>
<script src="./js/lib/app.js"></script>
</html>
diff --git a/js/vendor/StartAudioContext.js b/js/vendor/StartAudioContext.js
new file mode 100644
index 0000000..905878a
--- /dev/null
+++ b/js/vendor/StartAudioContext.js
@@ -0,0 +1,180 @@
+/**
+ * StartAudioContext.js
+ * @author Yotam Mann
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @copyright 2016 Yotam Mann
+ */
+(function (root, factory) {
+ if (typeof define === "function" && define.amd) {
+ define([], factory);
+ } else if (typeof module === 'object' && module.exports) {
+ module.exports = factory();
+ } else {
+ root.StartAudioContext = factory();
+ }
+}(this, function () {
+
+ /**
+ * The StartAudioContext object
+ */
+ var StartAudioContext = {
+ /**
+ * The audio context passed in by the user
+ * @type {AudioContext}
+ */
+ context : null,
+ /**
+ * The TapListeners bound to the elements
+ * @type {Array}
+ * @private
+ */
+ _tapListeners : [],
+ /**
+ * Callbacks to invoke when the audio context is started
+ * @type {Array}
+ * @private
+ */
+ _onStarted : [],
+ };
+
+
+ /**
+ * Set the context
+ * @param {AudioContext} ctx
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.setContext = function(ctx){
+ StartAudioContext.context = ctx;
+ return StartAudioContext;
+ };
+
+ /**
+ * Add a tap listener to the audio context
+ * @param {Array|Element|String|jQuery} element
+ * @returns {StartAudioContext}
+ */
+ StartAudioContext.on = function(element){
+ if (Array.isArray(element) || (NodeList && element instanceof NodeList)){
+ for (var i = 0; i < element.length; i++){
+ StartAudioContext.on(element[i]);
+ }
+ } else if (typeof element === "string"){
+ StartAudioContext.on(document.querySelectorAll(element));
+ } else if (element.jquery && typeof element.toArray === "function"){
+ StartAudioContext.on(element.toArray());
+ } else if (Element && element instanceof Element){
+ //if it's an element, create a TapListener
+ var tap = new TapListener(element, onTap);
+ StartAudioContext._tapListeners.push(tap);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * Bind a callback to when the audio context is started.
+ * @param {Function} cb
+ * @return {StartAudioContext}
+ */
+ StartAudioContext.onStarted = function(cb){
+ //if it's already started, invoke the callback
+ if (StartAudioContext.isStarted()){
+ cb();
+ } else {
+ StartAudioContext._onStarted.push(cb);
+ }
+ return StartAudioContext;
+ };
+
+ /**
+ * returns true if the context is started
+ * @return {Boolean}
+ */
+ StartAudioContext.isStarted = function(){
+ return (StartAudioContext.context !== null && StartAudioContext.context.state === "running");
+ };
+
+ /**
+ * @class Listens for non-dragging tap ends on the given element
+ * @param {Element} element
+ * @internal
+ */
+ var TapListener = function(element){
+
+ this._dragged = false;
+
+ this._element = element;
+
+ this._bindedMove = this._moved.bind(this);
+ this._bindedEnd = this._ended.bind(this);
+
+ element.addEventListener("touchmove", this._bindedMove);
+ element.addEventListener("touchend", this._bindedEnd);
+ element.addEventListener("mouseup", this._bindedEnd);
+ };
+
+ /**
+ * drag move event
+ */
+ TapListener.prototype._moved = function(e){
+ this._dragged = true;
+ };
+
+ /**
+ * tap ended listener
+ */
+ TapListener.prototype._ended = function(e){
+ if (!this._dragged){
+ onTap();
+ }
+ this._dragged = false;
+ };
+
+ /**
+ * remove all the bound events
+ */
+ TapListener.prototype.dispose = function(){
+ this._element.removeEventListener("touchmove", this._bindedMove);
+ this._element.removeEventListener("touchend", this._bindedEnd);
+ this._element.removeEventListener("mouseup", this._bindedEnd);
+ this._bindedMove = null;
+ this._bindedEnd = null;
+ this._element = null;
+ };
+
+ /**
+ * Invoked the first time of the elements is tapped.
+ * Creates a silent oscillator when a non-dragging touchend
+ * event has been triggered.
+ */
+ function onTap(){
+
+ //start the audio context with a silent oscillator
+ if (StartAudioContext.context && !StartAudioContext.isStarted()){
+ var osc = StartAudioContext.context.createOscillator();
+ var silent = StartAudioContext.context.createGain();
+ silent.gain.value = 0;
+ osc.connect(silent);
+ silent.connect(StartAudioContext.context.destination);
+ var now = StartAudioContext.context.currentTime;
+ osc.start(now);
+ osc.stop(now+0.5);
+ }
+
+ //dispose all the tap listeners
+ if (StartAudioContext._tapListeners){
+ for (var i = 0; i < StartAudioContext._tapListeners.length; i++){
+ StartAudioContext._tapListeners[i].dispose();
+ }
+ StartAudioContext._tapListeners = null;
+ }
+ //the onstarted callbacks
+ if (StartAudioContext._onStarted){
+ for (var j = 0; j < StartAudioContext._onStarted.length; j++){
+ StartAudioContext._onStarted[j]();
+ }
+ StartAudioContext._onStarted = null;
+ }
+ }
+
+ return StartAudioContext;
+})); \ No newline at end of file