Developer - Entrepeneur - Rockstar

Leap Motion Colorpicker

| Javascript, jQuery, Leap Motion | 0 Comments

Soon I will publish demo of painting on a 3D mesh using a Leap Motion inside a browser. In anticipation of this I'd like to show you a little something I wrote for that demo. It is a colorpicker that you can control with a Leap Motion (as well as a mouse). I will show you how to re-create this step by step. Let's dive in!

Before we start, here's a demo of the result:

To pick a color make sure you have a connected leap motion device (or use an ancient mouse)

Instructions:
Reach forward with one hand closed. To pick a color, open your hand and follow instructions below. Once you have selected the color you want, close your hand and move it away.

  • Hue: move your hand sideways
  • Saturation: move your hand up (saturated) or down (desaturated)
  • Lightness: move your hand towards (darker) or away from (lighter) the screen
 


The colorpicker I use in this example is a great jQuery plugin called farbtastic. By the way, if you visit that link, and I srtongly encourage you to do so, scroll around on the page. It really is a beautiful piece of work.

Anyway, back to business. You could actually use any colorpicker that you'd like, or create your own. All we do here is translate your hands position into three values: hue, saturation and lightness. These values are then used to set the value for the colorpicker. I'll explain how to use this technique with farbtastic.

The first thing we need is leapjs, a javascript library to interact with the Leap Motion. To use it in your script, simply add the following to you html:

<script src="//js.leapmotion.com/0.3.0-beta3/leap.min.js"></script>

If you want to use farbtasic make sure jquery is added as well and of course farbtastic itself. Check the farbtastic website on how to set this up. However, to instantiate the colorPicker variable with farbtastic in a way so that we can use it later, make sure it is added like this:

var colorPicker;
$(function() {
 colorPicker = $.farbtastic('#colorpicker', '#color');
});

Next, we need to define some things.

var controller = new Leap.Controller();
var HSL = {
 h: 0,
 s: 0,
 l: 0
}
var xRange = [-140, 140];
var yRange = [ 170, 500];
var zRange = [ 0, 200];

var hRange = [0, 360];
var sRange = [0, 100];
var lRange = [0, 100];

First we create a leap controller. Then we add an object to contain the HSL (Hue, Saturation, Lightness) values. Next we define 6 ranges.

The x, y and z ranges depict the values for your hands position. These ranges might not be perfect for everyone, but after some trial and error these values seem to work well for most people.

These values will get translated values in the h, s and l ranges. For example: whenever x is less than or equal -140 (your hand is all the way to the left), the hue will become 0. If x is greater than or equal to 140, the hue will be 360. For each value if x between -140 and 140, the value of the hue will be mapped to a value between 0 and 360.

We need to get updates from the Leap Motion. Whenever a hand is seen with at least 4 fingers (so an open hand) it need to update the color.

controller.on('frame', function(frame) {
 if (frame.hands.length < 1) return;

 if(frame.pointables.length > 3)
 {
   var hand = frame.hands[0];
   updateColorFromPosition(hand.palmPosition);
   colorPicker.setHSL([HSL.h/360, HSL.s/100, HSL.l/100]);
 }
});

controller.connect();

The code above is pretty self explanatory. The line with colorPicker.setHSL() depends on what colorpicker you use. The real interesting part is in the functions updateColorFromPosition() and mapAxisValueToHSLProperty.

function updateColorFromPosition(position) {
 var x = position[0];
 var y = position[1];
 var z = position[2];
 
 HSL.h = mapAxisValueToHSLProperty(x, xRange, hRange);
 HSL.s = mapAxisValueToHSLProperty(y, yRange, sRange);
 HSL.l = mapAxisValueToHSLProperty(z, zRange, lRange);
}

function mapAxisValueToHSLProperty(value, valueRange, propertyRange) {
 Math.round(
   constrain(
     map(
       value,
       valueRange[0],
       valueRange[1],
       propertyRange[0],
       propertyRange[1]
     ),
     propertyRange[0], propertyRange[1]
   )
 );  
}

First we get the x, y and z position of the hand. Then we map these values to HSL. To make sure these are valid values, we constrain them to the HSL range. Finally the values are rounded.

There are still some functions you are missing. The javascript Math object has many helpful functions. Unfortunately map is not one of them. Neither are constrain, lerp and norm, so we defines these ourselves.

function constrain(val, min, max){
 return val < min ? min : (val > max ? max : val);
}

function map(val, min1, max1, min2, max2){
 return lerp( norm(val, min1, max1), min2, max2 );
}

function lerp(ratio, start, end){
 return start + (end - start) * ratio;
}

function norm(val, min, max){
 return (val - min) / (max - min);
}

And that's it. Let me know what you think! I've made the demo available as a download.

Download the demo   View the demo online

Add Comment