HTML5 Game - Creating a drawing application

Introduction

The following code shows how to create a drawing application.

Demo

ResultView the demo in separate window

<!DOCTYPE HTML>
<html>
    <head>
        <style>
            canvas {//from www.  j av a2  s . com
                border: 1px solid black;
                font-family: "Helvetica Neue", "Arial", "Lucida Grande", "Lucida Sans Unicode", "Microsoft YaHei", sans-serif;
                font-size: 13px;
                line-height: 1.5;
                color: #474747;
            }
            
            #toolbar {
                width: 590px;
                border: 1px solid black;
                border-bottom: 0px;
                padding: 5px;
                background-color: #f8f8f8;
            }
            
            input[type = 'text'] {
                width: 30px;
            margin: 0px 5px 0px 5px;
            }
            
            label {
                margin-left: 40px;
            }
            
            label:first-of-type {
                margin-left: 0px;
            }
            
            input[type = 'button'] {
                float: right;
            }
            
            #colorSquare {
                position: relative;
                display: inline-block;
                width: 20px;
                height: 20px;
                background-color: blue;
                top: 4px;
            }
        </style>
        <script>
class EventManager{
   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 addPoint(events, points){
                let context = events.getContext();
                let drawingPos = events.getMousePos();
                
                if (drawingPos !== null) {
                    points.push(drawingPos);
                }
            }
            
            function drawPath(canvas, points, canvasImg){
                let context = canvas.getContext("2d");
                
                // clear canvas
                context.clearRect(0, 0, canvas.width, canvas.height);
                
                // redraw canvas before path
                context.drawImage(canvasImg, 0, 0, canvas.width, canvas.height);
                
                // draw patch
                context.beginPath();
                context.lineTo(points[0].x, points[0].y);
                for (let n = 1; n < points.length; n++) {
                    let point = points[n];
                    context.lineTo(point.x, point.y);
                }
                context.stroke();
            }
            
            function updateColorSquare(){
                let red = document.getElementById("red").value;
                let green = document.getElementById("green").value;
                let blue = document.getElementById("blue").value;
                
                let colorSquare = document.getElementById("colorSquare");
                colorSquare.style.backgroundColor = "rgb(" + red + "," + green + "," + blue + ")";
            }
            
            function getCanvasImg(canvas){
                let img = new Image();
                img.src = canvas.toDataURL();
                return img;
            }
            
            window.onload = function(){
                let events = new EventManager("myCanvas");
                let canvas = events.getCanvas();
                let context = events.getContext();
                let isMouseDown = false;
                let canvasImg = getCanvasImg(canvas);
                let points = [];
                
                // initialize drawing params
                let red = document.getElementById("red").value;
                let green = document.getElementById("green").value;
                let blue = document.getElementById("blue").value;
                let size = document.getElementById("size").value;
                
                // attach listeners
                document.getElementById("red").addEventListener("keyup", function(evt){
                    updateColorSquare();
                }, false);
                
                document.getElementById("green").addEventListener("keyup", function(evt){
                    updateColorSquare();
                }, false);
                
                document.getElementById("blue").addEventListener("keyup", function(evt){
                    updateColorSquare();
                }, false);
                
                document.getElementById("clearButton").addEventListener("click", function(evt){
                    events.clear();
                    points = [];
                    canvasImg = getCanvasImg(canvas);
                }, false);
                
                document.getElementById("saveButton").addEventListener("click", function(evt){
                    // open new window with saved image so user
                    // can right click and save to their computer
                    window.open(canvas.toDataURL());
                }, false);
                
                canvas.addEventListener("mousedown", function(){
                    let drawingPos = events.getMousePos();
                    
                    // update drawing params
                    red = document.getElementById("red").value;
                    green = document.getElementById("green").value;
                    blue = document.getElementById("blue").value;
                    size = document.getElementById("size").value;
                    
                    // start drawing path
                    context.strokeStyle = "rgb(" + red + "," + green + "," + blue + ")";
                    context.lineWidth = size;
                    context.lineJoin = "round";
                    context.lineCap = "round";
                    addPoint(events, points);
                    isMouseDown = true;
                }, false);
                
                canvas.addEventListener("mouseup", function(){
                    isMouseDown = false;
                    if (points.length > 0) {
                        drawPath(this, points, canvasImg);
                        // reset points
                        points = [];
                    }
                    canvasImg = getCanvasImg(this);
                }, false);
                
                canvas.addEventListener("mouseout", function(){
                    if (document.createEvent) {
                        let evt = document.createEvent('MouseEvents');
                        evt.initEvent("mouseup", true, false);
                        this.dispatchEvent(evt);
                    }
                    else {
                        this.fireEvent("onmouseup");
                    }
                }, false);
                
                events.setDrawStage(function(){
                    if (isMouseDown) {
                        addPoint(this, points);
                        drawPath(canvas, points, canvasImg);
                    }
                });
            };
        </script>
    </head>
    <body>
        <div id="toolbar">
            <label>
                Color
            </label>
            R: <input type="text" id="red" maxlength="3" class="short" value="0">G: <input type="text" id="green" maxlength="3" class="short" value="0">B: <input type="text" id="blue" maxlength="3" class="short" value="255">
            <div id="colorSquare">
            </div>
            <label>
                Size:
            </label>
            <input type="text" id="size" maxlength="3" class="short" value="20">px<input type="button" id="clearButton" value="Clear"><input type="button" id="saveButton" value="Save">
        </div>
        <canvas id="myCanvas" width="600" height="250">
        </canvas>
    </body>
</html>

Related Topic