bacon_demo.js.coffee | |
---|---|
$(document).ready ->
if !window.DeviceOrientationEvent
alert = $('<h4>').text("Your browser doesn't seem to support DeviceOrientationEvent, try Chrome")
alert.insertAfter("h3") | |
Utlity functionsThese just make the resulting stream code more readable | f =
sum: (a,b) -> a + b
multiply: (a,b) -> a * b
average: (ns) -> _.inject(ns, f.sum, 0) / (ns.length||1)
floor: (n) -> Math.floor(n) |
Get the height/width of the document | doc =
getHeight: -> $(window).height()
getWidth: -> $(window).width() |
Streams | |
Get window resize events as a stream | resizeStream = $(window).asEventStream("resize")
|
Creates Bacon properties for the current doc width and height
| doc.size =
width: resizeStream.map( doc.getWidth ).toProperty( doc.getWidth() )
height: resizeStream.map( doc.getHeight ).toProperty( doc.getHeight() ) |
Use the HTML5 "deviceorientation" event as a stream | motionStream = $(window).asEventStream("deviceorientation")
|
Create new streams from the motionStream by pulling out the gamma (left-right angle) and beta (up-down angle) from the original deviceorientation event (see: http://www.html5rocks.com/en/tutorials/device/orientation/) | angle =
lr: motionStream.map '.originalEvent.gamma'
ud: motionStream.map '.originalEvent.beta' |
Normalize the angle streams from -90 -> 90, to 0 -> 1 | angleRatio =
lr: angle.lr.map (v) -> ((v + 90) / 180)
ud: angle.ud.map (v) -> ((v + 90) / 180) |
Average the last 5 angles to smooth everything out a bit This uses slidingWindow which creates a stream whose values are an array of the last 5 values of the angleRatio streams, and then averages them back down to a single value (an unweighted moving average) | angleRatioSmooth =
lr: angleRatio.lr.slidingWindow(5).map(f.average)
ud: angleRatio.ud.slidingWindow(5).map(f.average) |
Combine the current document size, with the current smoothed and normalized device angle to the ball's position Combine is great. It takes the current value of the doc.width property and the latest value of the angleRationSmooth stream, passing it to our f.multiply function. This creates a new stream of the two multiplied together Then we are flooring them so that we don't get pixel rendering issues | position =
lr: doc.size.width.combine(angleRatioSmooth.lr, f.multiply)
.map(f.floor)
ud: doc.size.height.combine(angleRatioSmooth.ud, f.multiply)
.map(f.floor)
|
Assign the position to the bacon Every time either of our position streams updates, the bacon's appopriate css value will get updated | $bacon = $('.bacon')
position.ud.assign $bacon, 'css', 'top'
position.lr.assign $bacon, 'css', 'left'
|