mirror of
https://github.com/sorenisanerd/gotty.git
synced 2024-11-14 01:14:25 +00:00
352 lines
11 KiB
JavaScript
352 lines
11 KiB
JavaScript
|
var VirtualJoystick = function(opts)
|
||
|
{
|
||
|
opts = opts || {};
|
||
|
this._container = opts.container || document.body;
|
||
|
this._stickEl = opts.stickElement || this._buildJoystickStick();
|
||
|
this._baseEl = opts.baseElement || this._buildJoystickBase();
|
||
|
this._mouseLeft = opts.mouseLeft || this._buildJoystickButton();
|
||
|
this._mouseSupport = 'mouseSupport' in opts? opts.mouseSupport : false;
|
||
|
this._range = opts.range || 60;
|
||
|
|
||
|
this._timer = null;
|
||
|
|
||
|
this._callback = 'callback' in opts? opts.callback : false;
|
||
|
this._callbackcontext = 'callbackcontext' in opts? opts.callbackcontext: this;
|
||
|
this._callbackButton = 'callbackbutton' in opts? opts.callbackbutton : false;
|
||
|
this._referenceItem = opts.referenceItem;
|
||
|
|
||
|
this._container.style.position = "relative";
|
||
|
|
||
|
this._container.appendChild(this._baseEl);
|
||
|
this._container.appendChild(this._mouseLeft);
|
||
|
|
||
|
this._baseEl.style.position = "absolute"
|
||
|
this._baseEl.style.display = "block";
|
||
|
|
||
|
this._mouseLeft.style.position = "absolute"
|
||
|
this._mouseLeft.style.display = "block";
|
||
|
|
||
|
//calculate positions
|
||
|
var jcnt = $(this._referenceItem);
|
||
|
var baseTop = jcnt.height()-jcnt.offset().top-130;
|
||
|
var baseLeft = 20;
|
||
|
var baseRight = 20;
|
||
|
this._baseEl.style.top = baseTop+'px';
|
||
|
this._baseEl.style.left = baseLeft+'px';
|
||
|
|
||
|
this._container.appendChild(this._stickEl);
|
||
|
this._stickEl.style.position = "absolute"
|
||
|
this._stickEl.style.display = "none";
|
||
|
|
||
|
this._mouseLeft.style.top = baseTop+20+'px';
|
||
|
this._mouseLeft.style.right = baseRight+'px';
|
||
|
|
||
|
this._pressed = false;
|
||
|
this._baseX = 0;
|
||
|
this._baseY = 0;
|
||
|
this._stickX = 0;
|
||
|
this._stickY = 0;
|
||
|
|
||
|
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
this._$onTouchStart = __bind(this._onTouchStart , this);
|
||
|
this._$onTouchEnd = __bind(this._onTouchEnd , this);
|
||
|
this._$onTouchMove = __bind(this._onTouchMove , this);
|
||
|
this._$onTouchStartButton = __bind(this._onTouchStartButton, this);
|
||
|
this._$onTouchEndButton = __bind(this._onTouchEndButton, this);
|
||
|
this._baseEl.addEventListener( 'touchstart' , this._$onTouchStart , false );
|
||
|
this._mouseLeft.addEventListener( 'touchstart' , this._$onTouchStartButton , false );
|
||
|
this._mouseLeft.addEventListener( 'touchend' , this._$onTouchEndButton , false );
|
||
|
this._container.addEventListener( 'touchend' , this._$onTouchEnd , false );
|
||
|
this._container.addEventListener( 'touchmove' , this._$onTouchMove , false );
|
||
|
if( this._mouseSupport ){
|
||
|
this._$onMouseDown = __bind(this._onMouseDown , this);
|
||
|
this._$onMouseUp = __bind(this._onMouseUp , this);
|
||
|
this._$onMouseMove = __bind(this._onMouseMove , this);
|
||
|
this._$onMouseDownButton = __bind(this._onMouseDownButton, this);
|
||
|
this._$onMouseUpButton = __bind(this._onMouseUpButton, this);
|
||
|
this._baseEl.addEventListener( 'mousedown' , this._$onMouseDown , false );
|
||
|
this._container.addEventListener( 'mouseup' , this._$onMouseUp , false );
|
||
|
this._mouseLeft.addEventListener( 'mousedown' , this._$onTouchStartButton , false );
|
||
|
this._mouseLeft.addEventListener( 'mouseup' , this._$onTouchEndButton , false );
|
||
|
this._container.addEventListener( 'mousemove' , this._$onMouseMove , false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype.destroy = function()
|
||
|
{
|
||
|
this._container.removeChild(this._baseEl);
|
||
|
this._container.removeChild(this._stickEl);
|
||
|
|
||
|
this._mouseLeft.removeEventListener( 'touchstart' , this._$onTouchStartButton , false );
|
||
|
this._mouseLeft.removeEventListener( 'touchend' , this._$onTouchEndButton , false );
|
||
|
this._container.removeChild(this._mouseLeft);
|
||
|
|
||
|
this._container.removeEventListener( 'touchstart' , this._$onTouchStart , false );
|
||
|
this._container.removeEventListener( 'touchend' , this._$onTouchEnd , false );
|
||
|
this._container.removeEventListener( 'touchmove' , this._$onTouchMove , false );
|
||
|
if( this._mouseSupport ){
|
||
|
this._container.removeEventListener( 'mouseup' , this._$onMouseUp , false );
|
||
|
this._container.removeEventListener( 'mousedown' , this._$onMouseDown , false );
|
||
|
this._container.removeEventListener( 'mousemove' , this._$onMouseMove , false );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @returns {Boolean} true if touchscreen is currently available, false otherwise
|
||
|
*/
|
||
|
VirtualJoystick.touchScreenAvailable = function()
|
||
|
{
|
||
|
return 'createTouch' in document ? true : false;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
VirtualJoystick.prototype.deltaX = function(){ return this._stickX - this._baseX; }
|
||
|
VirtualJoystick.prototype.deltaY = function(){ return this._stickY - this._baseY; }
|
||
|
|
||
|
VirtualJoystick.prototype.up = function(){
|
||
|
if( this._pressed === false ) return false;
|
||
|
var deltaX = this.deltaX();
|
||
|
var deltaY = this.deltaY();
|
||
|
if( deltaY >= 0 ) return false;
|
||
|
if( Math.abs(deltaY) < this._range && Math.abs(deltaY) < Math.abs(deltaX) ){
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
VirtualJoystick.prototype.down = function(){
|
||
|
if( this._pressed === false ) return false;
|
||
|
var deltaX = this.deltaX();
|
||
|
var deltaY = this.deltaY();
|
||
|
if( deltaY <= 0 ) return false;
|
||
|
if( Math.abs(deltaY) < this._range && Math.abs(deltaY) < Math.abs(deltaX) ){
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
VirtualJoystick.prototype.right = function(){
|
||
|
if( this._pressed === false ) return false;
|
||
|
var deltaX = this.deltaX();
|
||
|
var deltaY = this.deltaY();
|
||
|
if( deltaX <= 0 ) return false;
|
||
|
if( Math.abs(deltaX) < this._range && Math.abs(deltaY) > Math.abs(deltaX) ){
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
VirtualJoystick.prototype.left = function(){
|
||
|
if( this._pressed === false ) return false;
|
||
|
var deltaX = this.deltaX();
|
||
|
var deltaY = this.deltaY();
|
||
|
if( deltaX >= 0 ) return false;
|
||
|
if( Math.abs(deltaX) < this._range && Math.abs(deltaY) > Math.abs(deltaX) ){
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// //
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
VirtualJoystick.prototype._onUp = function()
|
||
|
{
|
||
|
this._pressed = false;
|
||
|
this._stickEl.style.display = "none";
|
||
|
//this._baseEl.style.display = "none";
|
||
|
|
||
|
this._baseX = this._baseY = 0;
|
||
|
this._stickX = this._stickY = 0;
|
||
|
this._eraseInterval();
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onDown = function(x, y)
|
||
|
{
|
||
|
this._pressed = true;
|
||
|
this._stickX = x;
|
||
|
this._stickY = y;
|
||
|
|
||
|
this._stickEl.style.display = "";
|
||
|
this._stickEl.style.left = (this._stickX - this._stickEl.width /2)+"px";
|
||
|
this._stickEl.style.top = (this._stickY - this._stickEl.height/2)+"px";
|
||
|
this._startInterval();
|
||
|
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onMove = function(x, y)
|
||
|
{
|
||
|
if( this._pressed === true ){
|
||
|
this._stickX = x;
|
||
|
this._stickY = y;
|
||
|
this._stickEl.style.left = (x - this._stickEl.width /2)+"px";
|
||
|
this._stickEl.style.top = (y - this._stickEl.height/2)+"px";
|
||
|
this._startInterval();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._startInterval = function(x, y) {
|
||
|
this._eraseInterval();
|
||
|
var centerXBase = $(this._baseEl).offset().left + ($(this._baseEl).width()/2);
|
||
|
var centerXStick = $(this._stickEl).offset().left + ($(this._stickEl).width()/2);
|
||
|
this.offsetX = parseInt((centerXStick - centerXBase) / 5);
|
||
|
|
||
|
//////
|
||
|
|
||
|
var centerYBase = $(this._baseEl).offset().top + ($(this._baseEl).height()/2);
|
||
|
var centerYStick = $(this._stickEl).offset().top + ($(this._stickEl).height()/2);
|
||
|
|
||
|
this.offsetY = parseInt((centerYStick - centerYBase) / 5);
|
||
|
|
||
|
if(this.offsetX > 15) {
|
||
|
this.offsetX = 15;
|
||
|
}
|
||
|
|
||
|
if(this.offsetY > 15) {
|
||
|
this.offsetY = 15;
|
||
|
}
|
||
|
//calculate movements from offsets
|
||
|
|
||
|
var self = this;
|
||
|
this._timer = setInterval(function() {
|
||
|
if(self._callback) {
|
||
|
self._callback.call(self._callbackcontext, [self.offsetX, self.offsetY]);
|
||
|
}
|
||
|
}, 10);
|
||
|
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._eraseInterval = function() {
|
||
|
if(this._timer) {
|
||
|
clearTimeout(this._timer);
|
||
|
this._timer = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// bind touch events (and mouse events for debug) //
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
VirtualJoystick.prototype._onMouseUp = function(event)
|
||
|
{
|
||
|
return this._onUp();
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onMouseDown = function(event)
|
||
|
{
|
||
|
var x = event.pageX;
|
||
|
var y = event.pageY;
|
||
|
return this._onDown(x, y);
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onMouseMove = function(event)
|
||
|
{
|
||
|
var x = event.pageX;
|
||
|
var y = event.pageY;
|
||
|
return this._onMove(x, y);
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onTouchStart = function(event)
|
||
|
{
|
||
|
if( event.touches.length != 1 ) return;
|
||
|
|
||
|
event.preventDefault();
|
||
|
|
||
|
var x = event.touches[ 0 ].pageX;
|
||
|
var y = event.touches[ 0 ].pageY;
|
||
|
return this._onDown(x, y)
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onTouchEnd = function(event)
|
||
|
{
|
||
|
//??????
|
||
|
// no preventDefault to get click event on ios
|
||
|
event.preventDefault();
|
||
|
|
||
|
return this._onUp()
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onTouchMove = function(event)
|
||
|
{
|
||
|
if(event.touches && event.touches.length != 1 ) return;
|
||
|
|
||
|
event.preventDefault();
|
||
|
|
||
|
var x = event.touches[ 0 ].pageX;
|
||
|
var y = event.touches[ 0 ].pageY;
|
||
|
return this._onMove(x, y)
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onTouchStartButton = function(event)
|
||
|
{
|
||
|
if( event.touches && event.touches.length != 1 ) return;
|
||
|
|
||
|
event.preventDefault();
|
||
|
this._callbackButton.call(this._callbackcontext, ['down']);
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._onTouchEndButton = function(event)
|
||
|
{
|
||
|
//??????
|
||
|
// no preventDefault to get click event on ios
|
||
|
event.preventDefault();
|
||
|
this._callbackButton.call(this._callbackcontext, ['up']);
|
||
|
}
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
// build default stickEl and baseEl //
|
||
|
//////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
VirtualJoystick.prototype._buildJoystickBase = function()
|
||
|
{
|
||
|
var canvas = document.createElement( 'canvas' );
|
||
|
canvas.style.zIndex = 2;
|
||
|
canvas.width = 126;
|
||
|
canvas.height = 126;
|
||
|
|
||
|
var ctx = canvas.getContext('2d');
|
||
|
ctx.beginPath();
|
||
|
ctx.strokeStyle = "cyan";
|
||
|
ctx.lineWidth = 6;
|
||
|
ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true);
|
||
|
ctx.stroke();
|
||
|
|
||
|
ctx.beginPath();
|
||
|
ctx.strokeStyle = "cyan";
|
||
|
ctx.lineWidth = 2;
|
||
|
ctx.arc( canvas.width/2, canvas.width/2, 60, 0, Math.PI*2, true);
|
||
|
ctx.stroke();
|
||
|
|
||
|
return canvas;
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._buildJoystickStick = function()
|
||
|
{
|
||
|
var canvas = document.createElement( 'canvas' );
|
||
|
canvas.style.zIndex = 2;
|
||
|
canvas.width = 86;
|
||
|
canvas.height = 86;
|
||
|
var ctx = canvas.getContext('2d');
|
||
|
ctx.beginPath();
|
||
|
ctx.strokeStyle = "cyan";
|
||
|
ctx.lineWidth = 6;
|
||
|
ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true);
|
||
|
ctx.stroke();
|
||
|
return canvas;
|
||
|
}
|
||
|
|
||
|
VirtualJoystick.prototype._buildJoystickButton = function()
|
||
|
{
|
||
|
var canvas = document.createElement( 'canvas' );
|
||
|
canvas.style.zIndex = 2;
|
||
|
canvas.width = 86;
|
||
|
canvas.height = 86;
|
||
|
var ctx = canvas.getContext('2d');
|
||
|
ctx.beginPath();
|
||
|
ctx.strokeStyle = "green";
|
||
|
ctx.lineWidth = 6;
|
||
|
ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true);
|
||
|
ctx.stroke();
|
||
|
return canvas;
|
||
|
}
|