diff --git a/virtualjoystick.js b/virtualjoystick.js index 804af04..fa07bab 100644 --- a/virtualjoystick.js +++ b/virtualjoystick.js @@ -7,33 +7,42 @@ var VirtualJoystick = function(opts) this._baseEl = opts.baseElement || this._buildJoystickBase(); this._mouseSupport = opts.mouseSupport !== undefined ? opts.mouseSupport : false; this._stationaryBase = opts.stationaryBase || false; - this._baseX = this._stickX = opts.baseX || 0 - this._baseY = this._stickY = opts.baseY || 0 - this._limitStickTravel = opts.limitStickTravel || false - this._stickRadius = opts.stickRadius !== undefined ? opts.stickRadius : 100 - this._useCssTransform = opts.useCssTransform !== undefined ? opts.useCssTransform : false - - this._container.style.position = "relative" - - this._container.appendChild(this._baseEl) - this._baseEl.style.position = "absolute" - this._baseEl.style.display = "none" - this._container.appendChild(this._stickEl) - this._stickEl.style.position = "absolute" - this._stickEl.style.display = "none" + this._baseX = this._stickX = opts.baseX || 0; + this._baseY = this._stickY = opts.baseY || 0; + this._limitStickTravel = opts.limitStickTravel || false; + this._stickRadius = opts.stickRadius !== undefined ? opts.stickRadius : 100; + this._useCssTransform = opts.useCssTransform !== undefined ? opts.useCssTransform : false; + this._show = opts.show || false; + this._releaseX = opts.releaseX !== undefined ? opts.releaseX : null; + this._releaseY = opts.releaseY !== undefined ? opts.releaseY : null; + + this._container.style.position = "relative"; + this._container.appendChild(this._baseEl); + this._baseEl.style.position = "absolute"; + this._baseEl.style.display = "none"; + this._container.appendChild(this._stickEl); + this._stickEl.style.position = "absolute"; + this._stickEl.style.display = "none"; this._pressed = false; this._touchIdx = null; - + if(this._stationaryBase === true){ this._baseEl.style.display = ""; this._baseEl.style.left = (this._baseX - this._baseEl.width /2)+"px"; this._baseEl.style.top = (this._baseY - this._baseEl.height/2)+"px"; } - + this._transform = this._useCssTransform ? this._getTransformProperty() : false; this._has3d = this._check3D(); - + + this._updatePositionOfContainer(); + window.onresize = (function (joystick) { + return function () { + return joystick._updatePositionOfContainer(); + } + })(this); + var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; this._$onTouchStart = __bind(this._onTouchStart , this); this._$onTouchEnd = __bind(this._onTouchEnd , this); @@ -48,9 +57,13 @@ var VirtualJoystick = function(opts) this._container.addEventListener( 'mousedown' , this._$onMouseDown , false ); this._container.addEventListener( 'mouseup' , this._$onMouseUp , false ); this._container.addEventListener( 'mousemove' , this._$onMouseMove , false ); - } + } } +////////////////////////////////////////////////////////////////////////////////// +// // +////////////////////////////////////////////////////////////////////////////////// + VirtualJoystick.prototype.destroy = function() { this._container.removeChild(this._baseEl); @@ -92,7 +105,7 @@ VirtualJoystick.touchScreenAvailable = function() destObj.dispatchEvent = function(event /* , args... */){ if(this._events === undefined) this._events = {}; if( this._events[event] === undefined ) return; - var tmpArray = this._events[event].slice(); + var tmpArray = this._events[event].slice(); for(var i = 0; i < tmpArray.length; i++){ var result = tmpArray[i].apply(this, Array.prototype.slice.call(arguments, 1)) if( result !== undefined ) return result; @@ -122,7 +135,7 @@ VirtualJoystick.prototype.down = function(){ var deltaY = this.deltaY(); if( deltaY <= 0 ) return false; if( Math.abs(deltaX) > 2*Math.abs(deltaY) ) return false; - return true; + return true; } VirtualJoystick.prototype.right = function(){ if( this._pressed === false ) return false; @@ -130,7 +143,7 @@ VirtualJoystick.prototype.right = function(){ var deltaY = this.deltaY(); if( deltaX <= 0 ) return false; if( Math.abs(deltaY) > 2*Math.abs(deltaX) ) return false; - return true; + return true; } VirtualJoystick.prototype.left = function(){ if( this._pressed === false ) return false; @@ -138,39 +151,56 @@ VirtualJoystick.prototype.left = function(){ var deltaY = this.deltaY(); if( deltaX >= 0 ) return false; if( Math.abs(deltaY) > 2*Math.abs(deltaX) ) return false; - return true; + return true; } ////////////////////////////////////////////////////////////////////////////////// -// // +// Dealing with touches/mouse movents ////////////////////////////////////////////////////////////////////////////////// +VirtualJoystick.prototype._UpdateBase = function(){ + this._move(this._baseEl.style, (this._baseX - this._baseEl.width /2), (this._baseY - this._baseEl.height/2)); +} +VirtualJoystick.prototype._UpdateStick = function(){ + this._move(this._stickEl.style, (this._stickX - this._stickEl.width /2), (this._stickY - this._stickEl.height/2)); +} + + VirtualJoystick.prototype._onUp = function() { - this._pressed = false; - this._stickEl.style.display = "none"; - - if(this._stationaryBase == false){ - this._baseEl.style.display = "none"; - - this._baseX = this._baseY = 0; - this._stickX = this._stickY = 0; + this._pressed = false; + this._show ? this._stickEl.style.display = "" : this._stickEl.style.display = "none"; + if(!(this._stationaryBase || this._show)) { this._baseEl.style.display = "none"; } + + if(this._releaseX !=null || this._releaseY !=null){ + if (this._releaseX !=null){ + this._stickX= this._baseX + this._releaseX; + } + if (this._releaseY !=null){ + this._stickY= this._baseY + this._releaseY; + } + } + else { + this._stickX = this._baseX; + this._stickY = this._baseY; } + this._UpdateStick() } + VirtualJoystick.prototype._onDown = function(x, y) { - this._pressed = true; + this._pressed = true; if(this._stationaryBase == false){ this._baseX = x; this._baseY = y; this._baseEl.style.display = ""; - this._move(this._baseEl.style, (this._baseX - this._baseEl.width /2), (this._baseY - this._baseEl.height/2)); + this._UpdateBase() } - + this._stickX = x; this._stickY = y; - + if(this._limitStickTravel === true){ var deltaX = this.deltaX(); var deltaY = this.deltaY(); @@ -178,14 +208,14 @@ VirtualJoystick.prototype._onDown = function(x, y) if(stickDistance > this._stickRadius){ var stickNormalizedX = deltaX / stickDistance; var stickNormalizedY = deltaY / stickDistance; - + this._stickX = stickNormalizedX * this._stickRadius + this._baseX; this._stickY = stickNormalizedY * this._stickRadius + this._baseY; - } + } } - + this._stickEl.style.display = ""; - this._move(this._stickEl.style, (this._stickX - this._stickEl.width /2), (this._stickY - this._stickEl.height/2)); + this._UpdateStick() } VirtualJoystick.prototype._onMove = function(x, y) @@ -193,7 +223,7 @@ VirtualJoystick.prototype._onMove = function(x, y) if( this._pressed === true ){ this._stickX = x; this._stickY = y; - + if(this._limitStickTravel === true){ var deltaX = this.deltaX(); var deltaY = this.deltaY(); @@ -201,20 +231,42 @@ VirtualJoystick.prototype._onMove = function(x, y) if(stickDistance > this._stickRadius){ var stickNormalizedX = deltaX / stickDistance; var stickNormalizedY = deltaY / stickDistance; - + this._stickX = stickNormalizedX * this._stickRadius + this._baseX; this._stickY = stickNormalizedY * this._stickRadius + this._baseY; - } + } } - - this._move(this._stickEl.style, (this._stickX - this._stickEl.width /2), (this._stickY - this._stickEl.height/2)); - } + this._UpdateStick() + } } ////////////////////////////////////////////////////////////////////////////////// // bind touch events (and mouse events for debug) // +// mouse events ////////////////////////////////////////////////////////////////////////////////// +// container offset. +VirtualJoystick.prototype._updatePositionOfContainer = function () { + var x = 0, y = 0; + var element = this._container; + if(this._stationaryBase === true){ + this._UpdateBase() + while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + x += element.offsetLeft; + y += element.offsetTop; + element = element.offsetParent; + } + } + else { + while (element && !isNaN(element.offsetLeft) && !isNaN(element.offsetTop)) { + x += element.offsetLeft - element.scrollLeft; + y += element.offsetTop - element.scrollTop; + element = element.offsetParent; + } + } + this._containerX = x; + this._containerY = y; +} VirtualJoystick.prototype._onMouseUp = function(event) { @@ -224,20 +276,20 @@ VirtualJoystick.prototype._onMouseUp = function(event) VirtualJoystick.prototype._onMouseDown = function(event) { event.preventDefault(); - var x = event.clientX; - var y = event.clientY; + var x = event.clientX - this._containerX; + var y = event.clientY - this._containerY; return this._onDown(x, y); } VirtualJoystick.prototype._onMouseMove = function(event) { - var x = event.clientX; - var y = event.clientY; + var x = event.clientX - this._containerX; + var y = event.clientY - this._containerY; return this._onMove(x, y); } ////////////////////////////////////////////////////////////////////////////////// -// comment // +// touch events // ////////////////////////////////////////////////////////////////////////////////// VirtualJoystick.prototype._onTouchStart = function(event) @@ -248,7 +300,7 @@ VirtualJoystick.prototype._onTouchStart = function(event) // notify event for validation var isValid = this.dispatchEvent('touchStartValidation', event); if( isValid === false ) return; - + // dispatch touchStart this.dispatchEvent('touchStart', event); @@ -259,8 +311,8 @@ VirtualJoystick.prototype._onTouchStart = function(event) this._touchIdx = touch.identifier; // forward the action - var x = touch.pageX; - var y = touch.pageY; + var x = touch.pageX - this._containerX; + var y = touch.pageY - this._containerY; return this._onDown(x, y) } @@ -275,7 +327,7 @@ VirtualJoystick.prototype._onTouchEnd = function(event) // try to find our touch event var touchList = event.changedTouches; for(var i = 0; i < touchList.length && touchList[i].identifier !== this._touchIdx; i++); - // if touch event isnt found, + // if touch event isnt found, if( i === touchList.length) return; // reset touchIdx - mark it as no-touch-in-progress @@ -302,8 +354,8 @@ VirtualJoystick.prototype._onTouchMove = function(event) event.preventDefault(); - var x = touch.pageX; - var y = touch.pageY; + var x = touch.pageX - this._containerX; + var y = touch.pageY - this._containerY; return this._onMove(x, y) } @@ -320,20 +372,20 @@ VirtualJoystick.prototype._buildJoystickBase = function() var canvas = document.createElement( 'canvas' ); canvas.width = 126; canvas.height = 126; - + var ctx = canvas.getContext('2d'); - ctx.beginPath(); - ctx.strokeStyle = this._strokeStyle; - ctx.lineWidth = 6; - ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); - ctx.stroke(); - - ctx.beginPath(); - ctx.strokeStyle = this._strokeStyle; - ctx.lineWidth = 2; - ctx.arc( canvas.width/2, canvas.width/2, 60, 0, Math.PI*2, true); + ctx.beginPath(); + ctx.strokeStyle = this._strokeStyle; + ctx.lineWidth = 6; + ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); ctx.stroke(); - + + ctx.beginPath(); + ctx.strokeStyle = this._strokeStyle; + ctx.lineWidth = 2; + ctx.arc( canvas.width/2, canvas.width/2, 60, 0, Math.PI*2, true); + ctx.stroke(); + return canvas; } @@ -346,20 +398,20 @@ VirtualJoystick.prototype._buildJoystickStick = function() canvas.width = 86; canvas.height = 86; var ctx = canvas.getContext('2d'); - ctx.beginPath(); - ctx.strokeStyle = this._strokeStyle; - ctx.lineWidth = 6; - ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); + ctx.beginPath(); + ctx.strokeStyle = this._strokeStyle; + ctx.lineWidth = 6; + ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); ctx.stroke(); return canvas; } ////////////////////////////////////////////////////////////////////////////////// -// move using translate3d method with fallback to translate > 'top' and 'left' +// move using translate3d method with fallback to translate > 'top' and 'left' // modified from https://github.com/component/translate and dependents ////////////////////////////////////////////////////////////////////////////////// -VirtualJoystick.prototype._move = function(style, x, y) +VirtualJoystick.prototype._move = function(style, x, y) // moves the top left of cavas to (x,y). { if (this._transform) { if (this._has3d) { @@ -373,7 +425,7 @@ VirtualJoystick.prototype._move = function(style, x, y) } } -VirtualJoystick.prototype._getTransformProperty = function() +VirtualJoystick.prototype._getTransformProperty = function() { var styles = [ 'webkitTransform', @@ -391,11 +443,11 @@ VirtualJoystick.prototype._getTransformProperty = function() if (null != el.style[style]) { return style; } - } + } } - -VirtualJoystick.prototype._check3D = function() -{ + +VirtualJoystick.prototype._check3D = function() +{ var prop = this._getTransformProperty(); // IE8<= doesn't have `getComputedStyle` if (!prop || !window.getComputedStyle) return module.exports = false;