Various updates
authorRory Hardy <rory.cronin-hardy@cerner.com>
Thu, 8 Aug 2013 02:53:31 +0000 (21:53 -0500)
committerRory Hardy <rory.cronin-hardy@cerner.com>
Thu, 8 Aug 2013 02:53:31 +0000 (21:53 -0500)
Enhanced the pointer.
Cleaned up the code.
Added additional optional parameters.
Updated documentation.

modified:   README.md
modified:   index.html
modified:   plugin/leap/leap.js

README.md
index.html
plugin/leap/leap.js

index 15cabcffa1af7e2a667a34ee7727d867c54a3a43..c740bca12ff873af7c5a7b80fa38ff5655a774f6 100644 (file)
--- a/README.md
+++ b/README.md
@@ -628,10 +628,10 @@ Reveal.initialize({
 ## Leap Motion
 The Leap Motion plugin lets you utilize your [Leap Motion](https://www.leapmotion.com/) device to control basic navigation of your presentation. The gestures currently supported are:
 
-##### 1 hand + 1 finger
+##### 1 to 2 fingers
 * Pointer &mdash; Point to anything on screen. Move your finger past the device to expand the pointer.
 
-##### 1 hand + 2 or more fingers
+##### 1 hand + 3 or more fingers
 
 * Left
 * Right
@@ -647,11 +647,13 @@ Toggle the overview mode. Do it a second time to exit the overview.
 
 #### Config Options
 You can edit the following options:
+* autoCenter: Defaults to true. Center the pointer based on where you put your finger into the leap motions detection field.
+* gestureDelay: Defaults to 500. How long to delay between gestures in milliseconds.
 * naturalSwipe: Defaults to true. Swipe as though you were touching a touch screen. Set to false to invert.
-* pointerSize: Defaults to 15. The minimum height and width of the pointer.
 * pointerColor: Defaults to #00aaff. The color of the pointer.
-* pointerOpacity: Defaults to 0.75. The opacity of the pointer.
-* gestureDelay: Defaults to 500. How long to delay between gestures in milliseconds.
+* pointerOpacity: Defaults to 0.7. The opacity of the pointer.
+* pointerSize: Defaults to 15. The minimum height and width of the pointer.
+* pointerTolerance: Defaults to 120. Bigger = slower pointer.
 
 Example configuration:
 ```js
index fab2780dc45341285315307cfc1af558ca25a9b1..5aa8dfe049ed431d07ee81453f59f2597944fbd8 100644 (file)
@@ -370,7 +370,8 @@ function linkify( selector ) {
                                        { src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
                                        { src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
                                        { src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
-                                       { src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
+                                       { src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } },
+                                       { src: 'plugin/leap/leap.js', async: true }
                                        // { src: 'plugin/search/search.js', async: true, condition: function() { return !!document.body.classList; } }
                                        // { src: 'plugin/remotes/remotes.js', async: true, condition: function() { return !!document.body.classList; } }
                                ]
index a6051535494dc445637077320f082f9f2c482c2f..8ec51ecaff7ac3cdc8d04a4863f9af63d57ca796 100644 (file)
@@ -23,78 +23,103 @@ var b=right.criteria;if(a!==b){if(a>b||a===void 0)return 1;if(a<b||b===void 0)re
  */
 
 (function () {
-  var controller  = new Leap.Controller({ enableGestures: true }),
-      leapConfig  = Reveal.getConfig().leap,
-      pointer     = document.createElement('div'),
-      body        = document.body,
+  var body        = document.body,
+      controller  = new Leap.Controller({ enableGestures: true }),
       lastGesture = 0,
+      leapConfig  = Reveal.getConfig().leap,
+      pointer     = document.createElement( 'div' ),
       config      = {
-        naturalSwipe   : true,      // Swipe as if it were a touch screen.
-        pointerSize    : 15,        // Default height/width of the pointer.
-        pointerColor   : '#00aaff', // Default color of the pointer.
-        pointerOpacity : 0.75,      // Default opacity of the pointer.
-        gestureDelay   : 500        // How long to delay between gestures.
+        autoCenter       : true,      // Center pointer around detected position.
+        gestureDelay     : 500,       // How long to delay between gestures.
+        naturalSwipe     : true,      // Swipe as if it were a touch screen.
+        pointerColor     : '#00aaff', // Default color of the pointer.
+        pointerOpacity   : 0.7,       // Default opacity of the pointer.
+        pointerSize      : 15,        // Default height/width of the pointer.
+        pointerTolerance : 120        // Bigger = slower pointer.
       },
-      now;
+      now,
+      entered;
 
       // Merge user defined settings with defaults
-      if ( leapConfig ) {
-        for (key in leapConfig) {
+      if( leapConfig ) {
+        for( key in leapConfig ) {
           config[key] = leapConfig[key];
         }
       }
 
       pointer.id = 'leap';
 
-      pointer.style.filter          = 'alpha(opacity="' + config.pointerOpacity * 100 + '")';
       pointer.style.opacity         = config.pointerOpacity;
       pointer.style.backgroundColor = config.pointerColor;
 
-      body.appendChild(pointer);
+      body.appendChild( pointer );
 
-  controller.on('frame', function (frame) {
+  // Leap's loop
+  controller.on( 'frame', function ( frame ) {
     // Timing code to rate limit gesture execution
     now = new Date().getTime();
 
-    // Pointer code
-    if ( frame.hands.length === 1 && frame.fingers.length === 1 ) {
-      var size  =  -2 * frame.hands[0].palmPosition[2];
+    // Pointer: 1 to 2 fingers. Strictly one finger works but may cause innaccuracies.
+    // The innaccuracies were observed on a development model and may not be an issue with consumer models.
+    if( frame.fingers.length > 0 && frame.fingers.length < 3 ) {
+      // Invert direction and multiply by 3 for greater effect.
+      var size = -3 * frame.fingers[0].tipPosition[2];
 
-      if ( size < config.pointerSize ) {
-        size = config.pointerSize
+      if( size < config.pointerSize ) {
+        size = config.pointerSize;
       }
 
-      pointer.style.bottom =
-        frame.hands[0].palmPosition[1] * (body.offsetHeight / 100) - body.offsetHeight + 'px';
-
-      pointer.style.left =
-        frame.hands[0].palmPosition[0] * (body.offsetWidth / 100) + (body.offsetWidth / 2) + 'px';
-
-      pointer.style.visibility   = 'visible';
       pointer.style.width        = size     + 'px';
       pointer.style.height       = size     + 'px';
       pointer.style.borderRadius = size - 5 + 'px';
-    } 
+      pointer.style.visibility   = 'visible';
+
+      tipPosition = frame.fingers[0].tipPosition;
+
+      if( config.autoCenter ) {
+        // Check whether the finger has entered the z range of the Leap Motion. Used for the autoCenter option.
+        if( !entered ) {
+          entered         = true;
+          enteredPosition = frame.fingers[0].tipPosition;
+        }
+
+        pointer.style.top =
+          (-1 * (( tipPosition[1] - enteredPosition[1] ) * body.offsetHeight / config.pointerTolerance )) +
+            ( body.offsetHeight / 2 ) + 'px';
+
+        pointer.style.left =
+          (( tipPosition[0] - enteredPosition[0] ) * body.offsetWidth / config.pointerTolerance ) +
+            ( body.offsetWidth / 2 ) + 'px';
+      }
+      else {
+        pointer.style.top  = ( 1 - (( tipPosition[1] - 50) / config.pointerTolerance )) *
+          body.offsetHeight + 'px';
+
+        pointer.style.left = ( tipPosition[0] * body.offsetWidth / config.pointerTolerance ) +
+          ( body.offsetWidth / 2 ) + 'px';
+      }
+    }
     else {
       // Hide pointer on exit
+      entered                  = false;
       pointer.style.visibility = 'hidden';
     }
-    
+
     // Gestures
-    if ( frame.gestures.length > 0 && (now - lastGesture) > config.gestureDelay ) {
+    if( frame.gestures.length > 0 && (now - lastGesture) > config.gestureDelay ) {
       var gesture = frame.gestures[0];
 
       // One hand gestures
       if( frame.hands.length === 1 ) {
-        // Swipe gestures. 2+ fingers.
-        if ( frame.fingers.length > 1 && gesture.type === 'swipe' ) {
+        // Swipe gestures. 3+ fingers.
+        if( frame.fingers.length > 2 && gesture.type === 'swipe' ) {
           // Define here since some gestures will throw undefined for these.
           var x = gesture.direction[0],
               y = gesture.direction[1];
 
           // Left/right swipe gestures
-          if ( Math.abs(x) > Math.abs(y) ) {
-            if ( x > 0 ) {
+          if( Math.abs( x ) > Math.abs( y )) {
+            if( x > 0 ) {
               config.naturalSwipe ? Reveal.left() : Reveal.right();
             }
             else {
@@ -105,7 +130,7 @@ var b=right.criteria;if(a!==b){if(a>b||a===void 0)return 1;if(a<b||b===void 0)re
           // Up/down swipe gestures
           }
           else {
-            if ( y > 0 ) {
+            if( y > 0 ) {
               config.naturalSwipe ? Reveal.down() : Reveal.up();
             }
             else {
@@ -115,11 +140,11 @@ var b=right.criteria;if(a!==b){if(a>b||a===void 0)return 1;if(a<b||b===void 0)re
             lastGesture = now;
           }
         }
-        // Two hand gestures
       }
-      else if ( frame.hands.length == 2 ) {
-        // All upwards 2 hand gestures = toggle overview
-        if ( gesture.direction[1] > 0 ) {
+      // Two hand gestures
+      else if( frame.hands.length === 2 ) {
+        // Upward two hand swipe gesture
+        if( gesture.direction[1] > 0 && gesture.type === 'swipe' ) {
           Reveal.toggleOverview();
         }