Skip to content

Commit

Permalink
Committing proximity event
Browse files Browse the repository at this point in the history
  • Loading branch information
padolsey committed Jul 28, 2010
1 parent 82843d8 commit 770e838
Show file tree
Hide file tree
Showing 3 changed files with 268 additions and 0 deletions.
63 changes: 63 additions & 0 deletions proximity-event/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
Proximity event for jQuery
---

---

Inspired, in part, by this plugin: [jquery.onProximityFade.js](http://github.com/linowski/onProximityFade/blob/master/jquery.onProximityFade-1.0.0.js)

---

This special event allows you to detect the cursor's proximity to any given element and respond as you wish. It has been implemnted as an event which mleans that you can bind to it as you would with native DOM events such as `click` and `mouseover`.

It's easier just to show you:

jQuery('#elem').bind('proximity', {max: 300}, function(event, proximity, distance){

// This will be fired whenever the cursor resides within
// 300 pixels of #elem
// Arguments:
// event: Regular event object
// proximity: a number between 0 and 1 (the closer to zero the further from the element the cursor is)
// distance: the cursor's distance from the element in pixels
});

**[See the demo](http://qd9.co.uk/project/jQuery-plugins/proximity/demo.html)!**

The second argument to `bind` is the data object and is used by the proximity event to determine your preferences. Available options include (defaults are shown):

{
max: 100, // This determines how close the cursor has to be to the element
// in order for the event to fire (measured in pixels)
// It also determines the proximity argument passed to your
// handler - i.e. if it's 0.99 then we can assume that the
// cursor is pretty close to the max)
min: 0, // This acts like invisible padding around the element. If the
// cursor lies within this distance then the proximity will be
// treated as 1.00 (as if the element was being hovered over)
throttle: 0, // You can set this to any number (milliseconds) to determine
// the maximum frequency of event handler calls. If you set it
// to, for example, 100, then the handler will only be called
// (at most) every 100 milliseconds. By default your handler
// will be called whenever the document's mousemove event is
// fired (assuming the cursor lies within the min/max bounds)
fireOutOfBounds: 1 // This can be set to a number or a boolean.
// As a number it will determine how many times the event will
// be fired once the cursor is moving about outside of the
// min/max bounds. It's set to one so that you're guarenteed to
// encounter 0.00 and 1.00 proximities. If set to false then
// there is no guarentee that you will know when the cursor
// is moving about outside of bounds. If set to true then the
// event will be fired on every one of the document's
// mousemove events. Note that this doesn't effect the proximity
// argument passed to your handler. If the cursor is moving around
// outside of the max bound then it will be 0.00
}

Typically you won't need to override any of these other than the `max` bound. Note that these values can be mutated after an event has been bound, via `event.data` (the `event` is passed to your handler).

60 changes: 60 additions & 0 deletions proximity-event/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Proximity event for jQuery: Demo</title>
<style type="text/css">
body {
font-family: sans-serif;
margin: 0 auto;
width: 900px;
}
#demo {
padding: 20px;
font-size: 10px;
color: red;
background: #EEE;
border: 2px solid #CCC;
line-height: 50px;
}
#data {
font-family: monospace;
margin: 10px 0;
}
</style>
</head>
<body>

<h1>Proximity event for jQuery: Demo</h1>

<p>As you move closer to the box below the red text will get bigger (up to 5em).</p>
<div id="demo">MOVE CLOSER!</div>
<div id="data"></div>
<p><a href="http://github.com/jamespadolsey/jQuery-plugins/proximity-event/">See the repo here!</a></p>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script>
<script src="jquery.onproximity.js"></script>
<script>

var box = $('#demo'),
data = $('#data');

box.bind('proximity', {max:300}, function(e, proximity, distance){

// font-size moves between 10px and 30px
box.css('font-size', (proximity * 29 + 10) + 'px');

data.text(
proximity === 0 ?
'[OUT OF BOUNDS]'
: 'Distance from box: ' + distance.toFixed(3) + 'px, Proximity: ' + proximity.toFixed(3)
);

box.css('background', proximity === 1 ? 'yellow' : '');

});

</script>

</body>
</html>
145 changes: 145 additions & 0 deletions proximity-event/jquery.onproximity.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/**
* Proximity event for jQuery
* ---
* @author James Padolsey (http://james.padolsey.com)
* @version 0.1
* @updated 28-JUL-09
* ---
* @info http://github.com/jamespadolsey/jQuery-plugins/proximity-event/
*/

(function($){

var elems = $([]),
doc = $(document);

$.event.special.proximity = {

defaults: {
max: 100,
min: 0,
throttle: 0,
fireOutOfBounds: 1
},

setup: function(data) {

if (!elems[0])
doc.mousemove(handle);

elems = elems.add(this);

},

add: function(o) {

var handler = o.handler,
data = $.extend({}, $.event.special.proximity.defaults, o.data),
lastCall = 0,
nFiredOutOfBounds = 0,
hoc = $(this);

o.handler = function(e, pageX, pageY) {

var max = data.max,
min = data.min,
throttle = data.throttle,
date = +new Date,
distance,
proximity,
inBounds,
fireOutOfBounds = data.fireOutOfBounds;

if (throttle && lastCall + throttle > date) {
return;
}

lastCall = date;

distance = calcDistance(hoc, pageX, pageY);
inBounds = distance < max && distance > min;

if (fireOutOfBounds || inBounds) {

if (inBounds) {
nFiredOutOfBounds = 0;
} else {

// If fireOutOfBounds is a number then keep incrementing a
// counter to determine how many times the handler's been
// called out of bounds. Note: the counter is reset whenever
// the cursor goes back inBounds...

if (typeof fireOutOfBounds === 'number' && nFiredOutOfBounds > fireOutOfBounds) {
return;
}
++nFiredOutOfBounds;
}

proximity = e.proximity = 1 - (
distance < max ? distance < min ? 0 : distance / max : 1
);

e.distance = distance;
e.pageX = pageX;
e.pageY = pageY;
e.data = data;

return handler.call(this, e, proximity, distance);

}

};

},

teardown: function(){

elems = elems.not(this);

if (!elems[0])
doc.unbind('mousemove', handle);

}

};

function calcDistance(el, x, y) {

// Calculate the distance from the closest edge of the element
// to the cursor's current position

var left, right, top, bottom, offset,
cX, cY, dX, dY,
distance = 0;

offset = el.offset();
left = offset.left;
top = offset.top;
right = left + el.outerWidth();
bottom = top + el.outerHeight();

cX = x > right ? right : x > left ? x : left;
cY = y > bottom ? bottom : y > top ? y : top;

dX = Math.abs( cX - x );
dY = Math.abs( cY - y );

return Math.sqrt( dX * dX + dY * dY );

}

function handle(e) {

var x = e.pageX,
y = e.pageY,
i = -1,
fly = $([]);

while (fly[0] = elems[++i]) {
fly.triggerHandler('proximity', [x,y]);
}

}

}(jQuery));

0 comments on commit 770e838

Please sign in to comment.