CascadiaJS, November 2013
I'm @bradbouse.
Film School → Ad Agencies → Startups → Here
Forget those recruiters!
Make something useless.
But give this a try. It has worked for me.
Most web dev is moving text around.
Try something new.
It won't work in IE
It might not work on Windows.
It might not work without developer flags.
It might need expensive hardware.
And that's ok.
Coming from a recovering ActionScripter.
JS Engines are fast (thanks v8!)
Modern browsers: Canvas, SVG, CSS3
Moderner browsers: webGL and webRTC
Libraries: graphics/physics/3D/particles
Input devices: Kinect, Leap, Oculus Rift, Arduino
Ubiquitous, fast, and powerful.
Flash (ActionScript)
Processing (Java-ish)
OpenFrameworks (C++)
Cinder (C++)
Canvas: Browser sees one big square.
SVG: Browser sees a square inside a square.
Canvas Libraries: JS sees two squares, browser sees one.
Speed matters.
GPUs aren't just for mining BitCoin.
We're looking for surprise and delight.
But what haven't you clicked?
Touch
Webcam! (Demo)
External hardware (Arduino, Kinect, Oculus, and Leap)
...
@controller = new Leap.Controller({enableGestures: true})
//Set up a method to listen for frames...
@controller.loop(
(frame)->
//Do something awesome here.
)
//Listen to events from Leap
@controller.on('ready', ()->console.log("LEAP: ready"))
@controller.on('connect', ()->console.log("LEAP: connect"))
@controller.on('disconnect', ()->console.log("LEAP: disconnect"))
~20-90fps
{
"currentFrameRate":41.8666,
"gestures":[
],
"hands":[
{
"direction":[
-0.0266162,
0.146813,
-0.988806
],
"id":77,
"palmNormal":[
-0.389214,
-0.912623,
-0.125025
],
"palmPosition":[
115.035,
171.469,
-41.5293
],
"palmVelocity":[
5.43727,
-1.82765,
15.3623
],
"r":[
[
0.981607,
0.108195,
-0.157292
],
[
-0.0838155,
0.984489,
0.154128
],
[
0.171529,
-0.13811,
0.97545
]
],
"s":1.20843,
"sphereCenter":[
137.828,
163.689,
-96.022
],
"sphereRadius":53.52,
"stabilizedPalmPosition":[
115.845,
169.405,
-42.1059
],
"t":[
66.3909,
-5.94365,
-29.0868
],
"timeVisible":7.79126
}
],
"id":576683,
"interactionBox":{
"center":[
0,
200,
0
],
"size":[
221.418,
221.418,
154.742
]
},
"pointables":[
{
"direction":[
0.0311235,
-0.0974021,
-0.994758
],
"handId":77,
"id":95,
"length":87.6252,
"stabilizedTipPosition":[
126.97,
159.292,
-155.551
],
"timeVisible":2.66912,
"tipPosition":[
126.888,
162.142,
-155.141
],
"tipVelocity":[
5.98264,
-0.22555,
8.8473
],
"tool":false,
"touchDistance":0.139815,
"touchZone":"hovering"
},
{
"direction":[
-0.0886096,
-0.231428,
-0.968808
],
"handId":77,
"id":65,
"length":77.2424,
"stabilizedTipPosition":[
85.1323,
160.774,
-143.87
],
"timeVisible":3.17219,
"tipPosition":[
85.3095,
163.473,
-144.145
],
"tipVelocity":[
7.06236,
-1.15117,
-1.18688
],
"tool":false,
"touchDistance":-0.231083,
"touchZone":"touching"
},
{
"direction":[
0.265041,
0.116697,
-0.95715
],
"handId":77,
"id":32,
"length":72.2835,
"stabilizedTipPosition":[
172.964,
173.215,
-144.496
],
"timeVisible":0.433577,
"tipPosition":[
172.193,
173.445,
-144.096
],
"tipVelocity":[
9.59312,
4.66446,
-2.93894
],
"tool":false,
"touchDistance":0.333278,
"touchZone":"hovering"
},
{
"direction":[
0.605547,
0.0398785,
-0.794809
],
"handId":77,
"id":74,
"length":52.6733,
"stabilizedTipPosition":[
206.995,
152.038,
-88.7095
],
"timeVisible":0.047254,
"tipPosition":[
207.907,
152.12,
-89.3827
],
"tipVelocity":[
59.7907,
1.5625,
-30.8251
],
"tool":false,
"touchDistance":0.333333,
"touchZone":"hovering"
},
{
"direction":[
-0.388312,
0.617854,
-0.683718
],
"handId":77,
"id":45,
"length":44.7898,
"stabilizedTipPosition":[
29.7561,
219.239,
-52.1798
],
"timeVisible":3.17219,
"tipPosition":[
28.3511,
219.518,
-51.9544
],
"tipVelocity":[
9.13187,
-17.3379,
6.18593
],
"tool":false,
"touchDistance":-0.150288,
"touchZone":"touching"
}
],
"r":[
[
0.690598,
-0.710438,
-0.135473
],
[
0.645118,
0.689778,
-0.328677
],
[
0.32695,
0.139587,
0.934676
]
],
"s":-112.951,
"t":[
-21556.7,
-18003.8,
4323.1
],
"timestamp":334232761045
}
Motion over time.
//Motion scale
frame.scaleFactor(sinceFrame)
//Linear action
frame.translation(sinceFrame)
//Rotation
frame.rotationAngle(sinceFrame, axis)
catchGesture:(gesture)->
# Fired continuously *during* every gesture
# We only want swipes that look intentional
if gesture.type=="swipe" && gesture.state !="start"
if gesture.duration > 500 && !@gesturesMap[gesture.id]
#how far did the user travel in one direction?
distance = Math.abs(gesture.startPosition[0] - gesture.position[0])
if distance > 100
console.log("SWIPE:", gesture)
// Do something with the gesture.
"In conceptual art the idea or concept is the most important aspect of the work. When an artist uses a conceptual form of art, it means that all of the planning and decisions are made beforehand and the execution is a perfunctory affair. The idea becomes a machine that makes the art." -- Sol LeWitt
http://github.com/wholepixel/solving-sol
Try it with paper.js, d3.js, processing.js or anything else.
Let me know if you make anything!
bradbouse / gmail
Slides at wholepixel.com/cascadia