HTML5 Game - Canvas Event Mobile Event

Attaching touch event listeners to regions on a mobile device

The web applications are running on mobile devices and interacted with touch events from touchstart, touchend, and touchmove events.

The following code adds touch event listeners to the triangle and circle.

Demo

ResultView the demo in separate window

<!DOCTYPE HTML>
<html>
    <head>
    <meta name="viewport" content="width=device-width, initial-scale=0.552, user-scalable=no"/>       
        <script>
class EventManager{/*from  w  w w.  ja  v a  2 s .  co  m*/
   constructor(canvasId){
    this.canvas = document.getElementById(canvasId);
    this.context = this.canvas.getContext("2d");
    this.drawStage = undefined;
    this.listening = false;
    
    // desktop flags
    this.mousePos = null;
    this.mouseDown = false;
    this.mouseUp = false;
    this.mouseOver = false;
    this.mouseMove = false;
    
    // mobile flags
    this.touchPos = null;
    this.touchStart = false;
    this.touchMove = false;
    this.touchEnd = false;
    
    // Region Events
    this.currentRegion = null;
    this.regionIndex = 0;
    this.lastRegionIndex = -1;
    this.mouseOverRegionIndex = -1;
  }
  getContext(){
    return this.context;
  }

  getCanvas(){
    return this.canvas;
  }
  clear(){
    this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }
  getCanvasPos = function(){
    let obj = this.getCanvas();
    let top = 0;
    let left = 0;
    while (obj.tagName != "BODY") {
        top += obj.offsetTop;
        left += obj.offsetLeft;
        obj = obj.offsetParent;
    }
    return {
        top: top,
        left: left
    };
  }
  setDrawStage(func){
    this.drawStage = func;
    this.listen();
  }
  reset(evt){
    if (!evt) {
        evt = window.event;
    }
    
    this.setMousePosition(evt);
    this.setTouchPosition(evt);
    this.regionIndex = 0;
    
    if (this.drawStage !== undefined) {
        this.drawStage();
    }
    
    // desktop flags
    this.mouseOver = false;
    this.mouseMove = false;
    this.mouseDown = false;
    this.mouseUp = false;
    
    // mobile touch flags
    this.touchStart = false;
    this.touchMove = false;
    this.touchEnd = false;
  }  
  listen(){
    let that = this;
    
    if (this.drawStage !== undefined) {
        this.drawStage();
    }
    
    // desktop events
    this.canvas.addEventListener("mousedown", function(evt){
        that.mouseDown = true;
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("mousemove", function(evt){
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("mouseup", function(evt){
        that.mouseUp = true;
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("mouseover", function(evt){
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("mouseout", function(evt){
        that.mousePos = null;
    }, false);
    
    // mobile events
    this.canvas.addEventListener("touchstart", function(evt){
        evt.preventDefault();
        that.touchStart = true;
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("touchmove", function(evt){
        evt.preventDefault();
        that.reset(evt);
    }, false);
    
    this.canvas.addEventListener("touchend", function(evt){
        evt.preventDefault();
        that.touchEnd = true;
        that.reset(evt);
    }, false);
  }
  getMousePos(evt){
    return this.mousePos;
  }
  getTouchPos(evt){
    return this.touchPos;
  }
  setMousePosition(evt){
    let mouseX = evt.clientX - this.getCanvasPos().left + window.pageXOffset;
    let mouseY = evt.clientY - this.getCanvasPos().top + window.pageYOffset;
    this.mousePos = {
        x: mouseX,
        y: mouseY
    };
  }
  setTouchPosition(evt){
    if (evt.touches !== undefined && evt.touches.length == 1) { // Only deal with one finger
        let touch = evt.touches[0]; // Get the information for finger #1
        let touchX = touch.pageX - this.getCanvasPos().left + window.pageXOffset;
        let touchY = touch.pageY - this.getCanvasPos().top + window.pageYOffset;
        
        this.touchPos = {
            x: touchX,
            y: touchY
        };
    }
  }
  beginRegion = function(){
    this.currentRegion = {};
    this.regionIndex++;
  }
  addRegionEventListener = function(type, func){
     let event = (type.indexOf('touch') == -1) ? 'on' + type : type;
     this.currentRegion[event] = func;
  }
  closeRegion(){
    let pos = this.touchPos || this.mousePos;
    
    if (pos !== null && this.context.isPointInPath(pos.x, pos.y)) {
        if (this.lastRegionIndex != this.regionIndex) {
            this.lastRegionIndex = this.regionIndex;
        }
        
        // handle onmousedown
        if (this.mouseDown && this.currentRegion.onmousedown !== undefined) {
            this.currentRegion.onmousedown();
            this.mouseDown = false;
        }
        
        // handle onmouseup
        else if (this.mouseUp && this.currentRegion.onmouseup !== undefined) {
            this.currentRegion.onmouseup();
            this.mouseUp = false;
        }
        
        // handle onmouseover
        else if (!this.mouseOver && this.regionIndex != this.mouseOverRegionIndex && this.currentRegion.onmouseover !== undefined) {
            this.currentRegion.onmouseover();
            this.mouseOver = true;
            this.mouseOverRegionIndex = this.regionIndex;
        }
        
        // handle onmousemove
        else if (!this.mouseMove && this.currentRegion.onmousemove !== undefined) {
            this.currentRegion.onmousemove();
            this.mouseMove = true;
        }
        
        // handle touchstart
        if (this.touchStart && this.currentRegion.touchstart !== undefined) {
            this.currentRegion.touchstart();
            this.touchStart = false;
        }
        
        // handle touchend
        if (this.touchEnd && this.currentRegion.touchend !== undefined) {
            this.currentRegion.touchend();
            this.touchEnd = false;
        }
        
        // handle touchmove
        if (!this.touchMove && this.currentRegion.touchmove !== undefined) {
            this.currentRegion.touchmove();
            this.touchMove = true;
        }
        
    }
    else if (this.regionIndex == this.lastRegionIndex) {
        this.lastRegionIndex = -1;
        this.mouseOverRegionIndex = -1;
        
        // handle mouseout condition
        if (this.currentRegion.onmouseout !== undefined) {
            this.currentRegion.onmouseout();
        }
    }
}
}

             function writeMessage(context, message){ 
                 context.font = "18pt Calibri"; 
                 context.fillStyle = "black"; 
                 context.fillText(message, 10, 25); 
             } 
             window.onload = function(){ 
                 let events = new EventManager("myCanvas"); 
                 let canvas = events.getCanvas(); 
                 let context = events.getContext(); 
                 let message = ""; 

                 events.setDrawStage(function(){ 
               this.clear(); 
                    // draw blue triangle 
                    this.beginRegion(); 
                    context.beginPath(); 
                    context.lineWidth = 4; 
                    context.strokeStyle = "black"; 
                    context.fillStyle = "#00D2FF"; 
                    context.moveTo(50, 50); 
                    context.lineTo(180, 80); 
                    context.lineTo(80, 170); 
                    context.closePath(); 
                    context.fill(); 
                    context.stroke(); 

                    this.addRegionEventListener("touchmove", function(){ 
                        let touchPos = events.getTouchPos(); 
                         
                        if (touchPos !== null) { 
                            let touchX = touchPos.x - 20; 
                            let touchY = touchPos.y - 50; 
                             
                            message = "Triangle touch position: " +   
                            touchX + "," + touchY; 
                        } 
                    }); 
                     
                    this.closeRegion(); 
                    // draw yellow rectangle 
                    // this is an example of a shape 
                    // with no event listeners 
                    context.beginPath(); 
                    context.lineWidth = 4; 
                    context.strokeStyle = "black"; 
                    context.fillStyle = "yellow"; 
                    context.rect(200, 65, 150, 75); 
                    context.fill(); 
                    context.stroke(); 

                    // draw red circle 
                    this.beginRegion(); 
                    context.beginPath(); 
                   context.arc(450, canvas.height / 2, 70, 0, Math.PI *  2, true); 
                    context.fillStyle = "red"; 
                    context.fill(); 
                    context.stroke(); 

                    this.addRegionEventListener("touchstart", function(){ 
                        message = "Touchstart red circle!"; 
                    }); 
                     
                    this.addRegionEventListener("touchend", function(){ 
                        message = "Touchend red circle!"; 
                    }); 
                     
                    this.closeRegion(); 

              writeMessage(context, message); 
                }); 
             
            }; 

        </script>
    </head>
    <body>
        <canvas id="myCanvas" width="600" height="250" style="border:1px solid black;">
        </canvas>
    </body>
</html>

Note

Touch events on mobile devices work in much the same way as desktop events.

The mobile equivalent of mousedown is touchstart, the equivalent of mouseup is touchend, and the equivalent of mousemove is touchmove.

Related Topics