A virtual joystick for touch capable interfaces
npm install nipplejs --save
// OR
bower install nipplejs --save
Check out the demo here.
Import it the way you want into your project :
// CommonJS
var manager = require('nipplejs').create(options);
// AMD
define(['nipplejs'], function (nipplejs) {
var manager = nipplejs.create(options);
});
// Global
<script type="text/javascript" src="./dist/nipplejs.min.js"></script>
<script type="text/javascript">
var manager = nipplejs.create(options);
</script>
You can configure your joystick in different ways :
var options = {
zone: Element, // active zone
color: String,
size: Integer,
threshold: Float, // before triggering a directional event
fadeTime: Integer,
multitouch: Boolean,
maxNumberOfNipples: Number
};
All options are optional.
The dom element in which all your joysticks will be injected.
<div id="zone_joystick"></div>
<script type="text/javascript" src="./nipplejs.min.js"></script>
<script type="text/javascript">
var options = {
zone: document.getElementById('zone_joystick');
};
var manager = nipplejs.create(options);
</script>
This zone also serve as the mouse/touch events handler.
It represents the zone where all your joysticks will be active.
The background color of your joystick's elements.
Can be any valid CSS color.
The size in pixel of the outer circle.
The inner circle is 50% of this size.
This is the strength needed to trigger a directional event.
Basically, the center is 0 and the outer is 1.
You need to at least go to 0.1 to trigger a directional event.
The time it takes for joystick to fade-out and fade-in when activated or de-activated.
Enable the multitouch capabilities.
If, for reasons, you need to have multiple nipples into the same zone.
Otherwise it will only get one, and all new touches won't do a thing.
If you need to, you can also control the maximum number of instance that could be created.
Obviously in a multitouch configuration.
Your manager has the following signature :
{
on: Function,
off: Function,
get: Function, // get a specific joystick
options: {
zone: Element,
multitouch: Boolean,
maxNumberOfNipples: Number
}
}
If you whish to listen to internal events like :
manager.on('event#1 event#2', function (evt, data) {
// Do something.
});
Note that you can listen to multiple events at once by separating them either with a space or a comma (or both, I don't care).
To remove an event handler :
manager.off('event', handler);
If you don't specify the handler, all handlers for that type will be removed.
An helper to get an instance via its identifier.
// Will return the nipple instanciated by the touch identified by 0
manager.get(0);
Each joystick has the following signature :
{
on: Function,
off: Function,
el: Element,
show: Function, // fade-in
hide: Function, // fade-out
add: Function, // inject into dom
remove: Function, // remove from dom
identifier: Number,
trigger: Function,
position: { // position of the center
x: Number,
y: Number
},
backPosition: { // position of the back part
x: Number,
y: Number
},
frontPosition: { // position of the front part
x: Number,
y: Number
},
ui: {
el: Element,
front: Element,
back: Element
},
options: {
color: String,
size: Number,
threshold: Number,
fadeTime: Number
}
}
The same as the manager.
Dom element in which the joystick gets created.
<div class="nipple">
<div class="front"></div>
<div class="back"></div>
</div>
Will show the joystick at the last known place.
You can pass a callback that will be executed at the end of the fade-in animation.
Will fade-out the joystick.
You can pass a callback that will be executed at the end of the fade-out animation.
Add the joystick's element to the dom.
Remove the joystick's element from the dom.
Returns the unique identifier of the joystick.
Tied to its touch's identifier.
Trigger an internal event from the joystick.
The same as on
you can trigger multiple events at the same time.
The absolute position of the center of the joystick.
The absolute position of the back part of the joystick's ui.
The absolute position of the front part of the joystick's ui.
The object that store its ui elements
{
el: <div class="nipple"></div>
back: <div class="back"></div>
front: <div class="front"></div>
}
You can listen events both on the manager and all the joysticks.
But some of them are specific to its instance.
If you need to listen to each joystick, for example, you can :
manager.on('added', function (evt, nipple) {
nipple.on('start move end dir plain', function (evt) {
// DO EVERYTHING
});
}).on('removed', function (evt, nipple) {
nipple.off('start move end dir plain');
});
A joystick just got added.
Will pass the instance alongside the event.
A joystick just got removed.
Fired at the end of the fade-out animation.
Will pass the instance alongside the event.
Other events are available on both the manager and joysticks.
When listening on the manager,
you can also target a joystick in particular by prefixing
the event with its identifier, 0:start
for example.
Else you'll get all events from all the joysticks.
A joystick is activated. (the user pressed on the active zone)
Will pass the instance alongside the event.
A joystick is de-activated. (the user released the active zone)
Will pass the instance alongside the event.
A joystick is moved.
Comes with data :
{
identifier: 0, // the identifier of the touch/mouse that triggered it
position: { // absolute position of the center in pixels
x: 125,
y: 95
},
force: 0.2, // strength in %
distance: 25.4, // distance from center in pixels
pressure: 0.1, // the pressure applied by the touch
angle: {
radian: 1.5707963268, // angle in radian
degree: 90
},
instance: Nipple // the nipple instance that triggered the event
}
When a direction is reached after the threshold.
Direction are split with a 45° angle.
// \ UP /
// \ /
// LEFT RIGHT
// / \
// /DOWN \
You can also listen to specific direction like :
dir:up
dir:down
dir:right
dir:left
In this configuration only one direction is triggered at a time.
When a plain direction is reached after the threshold.
Plain directions are split with a 90° angle.
// UP |
// ------ LEFT | RIGHT
// DOWN |
You can also listen to specific plain direction like :
plain:up
plain:down
plain:right
plain:left
In this configuration two directions can be triggered at a time,
because the user could be both up
and left
for example.
Is triggered at the end of the fade-in animation.
Will pass the instance alongside the event.
hidden
Is triggered at the end of the fade-out animation.
Will pass the instance alongside the event.
Your help is more than welcome, I would be very honored to have you on my side.
Here are some very basic guidelines.
Please follow these guidelines so your commits will be taken by the self-generated changelog.
There are both JSCS and ESLint in the project.
To test your code against them simply run npm run prebuild
.
We follow a 4 spaces rule around here.
You can use the available scripts if needed.
npm run watch
will run the build each time a change is detected.npm run prebuild
will test the formatting and the linting of your code.
Once you're satisfied with your changes, you can also include a build.
npm run build
to generate built files.- commit your build with the message
chore: new build
. npm version patch|minor|major
depending on your change. Changelog will be generated and bower's version synced and everything is automatically committed (not pushed though).