gotty/js/spice-web-client/lib/virtualjoystick.js
Soren L. Hansen c66ae7b2e4 First, primitive stab at SPiCE integration
Launch an Xspice and run:
echo -ne "\033]844;127.0.0.1;9876\007"

This will launch a SPiCE client connecting to 127.0.0.1:9876.

Still need to add all the security stuff and generally be
more defensive in the implementation.
2021-04-16 06:50:05 -07:00

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;
}