HTML Virtual Joystick

A simple HTML virtual joystick in Javascript and CSS

by vrmeup

HTML

<html>
<body>
</body>
<pre id="pos"></pre>
</html>

CSS

body {
  background-color:green;
  overflow:hidden;
}

.joystick-panel {
    position: absolute; 
    aspect-ratio: 1/1;
    background: white;
    display: block;
    border-radius: 50%;
    background-color: rgba(255,255,255,0.2);
}

.joystick-thumb {
  position: relative;
  left: 0px;
  top: 0px;
  height: 50% ;
  aspect-ratio: 1/1;
  border-radius: 50%;
  background-color: rgba(255,255,255,0.3);
}

#joystick1 {
    left: calc(15pt) ;
    top: calc(100% - 115pt) ;
    width: 100pt ;
}

#joystick2 {
    left: calc(100% - 115pt) ;
    top: calc(100% - 115pt) ;
    width: 100pt ;
}

JavaScript

class Joystick {

    constructor(id, parent, padding) {
        this.padding = padding || 0.2 ;
    		this.x = 0.0 ;
        this.y = 0.0 ;
        this._panel = document.createElement("div")  ;
        this._panel.id = id || 'joystick' ;
        this._panel.classList.add("joystick-panel");
        this._thumb = document.createElement("div")  ;
        this._panel.appendChild(this._thumb);
        this._thumb.classList.add("joystick-thumb") ;
        (parent || document.body).append(this._panel);      
        
        this._thumb.addEventListener("touchstart", (e) => this.onTouchStart(e)) ;
        this._thumb.addEventListener("touchmove", (e) => this.onTouchMove(e)) ;
        this._thumb.addEventListener("touchend", (e) => this.onTouchEnd(e)) ;
        this._thumb.addEventListener("touchcancel", (e) => this.onTouchCancel(e)) ;

				this._thumb.addEventListener("mousedown", (e) => this.onTouchStart(e)) ;
        this._thumb.addEventListener("mousemove", (e) => this.onTouchMove(e)) ;
        this._thumb.addEventListener("mouseup", (e) => this.onTouchEnd(e)) ;
        
        this.resetThumb();
    }

    hide() {
        this._panel.style.display = "none" ;
    }

    show() {
        this._panel.style.display = "" ;
    }

    onTouchStart(e) {
        if(e.changedTouches) {
            this._touchIdentified = e.changedTouches.item(0).identifier ;
            this.handled(e);
        } else {
        	this._touchIdentified = -2 ; // mouse
        }
    }
    
    onTouchMove(e) {
        const touch = this.findTouch(e.changedTouches, this._touchIdentified, e) ;
        if(touch) {
            this.moveThumbTo(touch.pageX, touch.pageY);
            this.handled(e);
        }
    }

    onTouchEnd(e) {
        const touch = this.findTouch(e.changedTouches, this._touchIdentified, e) ;
        if(touch) {
            this._touchIdentified = -1 ;
            this.onTouchCancel(e);
        }
    }

    onTouchCancel(e) {
        this._touchIdentified = -1 ;
       ...