1

I am making a html game and want to add onscreen buttons.

To do this I think I need to know what pixel the mouse is at when I click.

If anyone knows how to do that or has another way to make buttons LMK.

markE
  • 102,905
  • 11
  • 164
  • 176
MickDom
  • 157
  • 2
  • 12
  • 4
    Possible duplicate of [How do I get the coordinates of a mouse click on a canvas element?](http://stackoverflow.com/questions/55677/how-do-i-get-the-coordinates-of-a-mouse-click-on-a-canvas-element) – user3297291 Apr 18 '16 at 15:58
  • That could be useful, don't know how I couldn't find that. – MickDom Apr 18 '16 at 17:55

1 Answers1

3

Here are the basics of finding a mouse position:

  1. Get a reference to the DOM element on which you want to listen for mouse events.

    var canvas=document.getElementById("canvas");
    
  2. The browser reports mouse coordinates relative to the top-left of the window rather than relative to your canvas element, so you need to account for the difference between the window & canvas positions. Use .getBoundingClientRect to fetch the offset of the canvas element within the window.

    // save the canvas offset in global variables
    var BB=canvas.getBoundingClientRect();
    var BBoffsetX=BB.left;
    var BBoffsetY=BB.top;
    
  3. Tell the browser you want to be told when the user does something with the mouse by subscribing to mouse events. You can do this using .onmousedown, .onmousemove, .onmouseup & .onmouseout and giving the browser functions to execute when these events occur.

    // listen for mousedown events, call handleMousedown() when they occur
    // listen for mousemove events, call handleMousemove() when they occur
    // listen for mouseup events, call handleMouseup() when they occur
    // listen for mouseout events, call handleMouseout() when they occur
    
    canvas.onmousedown=handleMousedown;
    canvas.onmousemove=handleMousemove;
    canvas.onmouseup=handleMouseup;
    canvas.onmouseout=handleMouseup;
    
  4. Respond to mouse events by coding mouse handler functions. The browser will automatically send an mouseevent argument when it executes the handler. That mouseevent contains clientX & clientY properties which are the X,Y coordinates relative to the top-left corner of the visible client area. To get the mouse position inside the canvas you must subtract BBoffsetX & BBoffsetY which were calculated in step#2.

    // this function is called every time the user presses the mouse down.
    // "e" is the mouseevent argument the browser automatically sends 
    function handleMousedown(e){
         // calculate the mouse position RELATIVE TO THE CANVAS
         var mouseX=e.clientX-BBoffsetX;
         var mouseY=e.clientY-BBoffsetY;
    
         // you have the mouse position so now do your button stuff
    }
    
  5. A refinement if the window will be scrolled...If the page content is larger than will fit in the browser display area, the browser will add scrollbars to let the user scroll to view all the page content. When the window scrolls, your offsets calculated in step#2 will become invalid so they must be recalculated. You can subscribe to the window.onscroll event and recalculate the offsets when scrolling occurs.

    // listen for events that invalidate the canvas offsets
    window.onscroll=function(e){ setBB(); }
    window.onresize=function(e){ setBB(); }
    
    // recalculate the offsets
    function setBB(){
        BB=canvas.getBoundingClientRect();
        BBoffsetX=BB.left;
        BBoffsetY=BB.top;
    }        
    

About your custom buttons

Here's a simple button system...

  • It displays (very!) simple custom drawn buttons,
  • It also shows how to get the mouse click position when mouse events occur,
  • It shows how to hit-test which custom drawn button the mouse is over,
  • It redraws the "hit" button to indicate it is pressed or released.

...You're welcome to start with it...

var $clicked=$('#clicked');

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

var clickedButton;
var buttons=[];
buttons.push(makeButton(1,20,20,50,20,'One','skyblue','gray','black',
    function(){ $clicked.text('You clicked: '+this.id+' with label: '+this.label); },
    function(){ $clicked.text('You released: '+this.id+' with label: '+this.label); }
));
buttons.push(makeButton(2,20,50,50,20,'Two','lightgreen','gray','black',
    function(){ $clicked.text('You clicked: '+this.id+' with label: '+this.label); },
    function(){ $clicked.text('You released: '+this.id+' with label: '+this.label); }
));

//
drawAll();

//
$("#canvas").mousedown(function(e){handleMouseDown(e);});
$("#canvas").mouseup(function(e){handleMouseUpOut(e);});
$("#canvas").mouseout(function(e){handleMouseUpOut(e);});


function makeButton(id,x,y,w,h,label,fill,stroke,labelcolor,clickFn,releaseFn){
    return({
        id:id,
        x:x, y:y, w:w, h:h,
        fill:fill, stroke:stroke, labelcolor:labelcolor,
        label:label,
        click:clickFn,
        release:releaseFn
    });
}

function drawAll(){
    for(var i=0;i<buttons.length;i++){
        drawButton(buttons[i],false);
    }
}

function drawButton(b,isDown){
    ctx.clearRect(b.x-1,b.y-1,b.w+2,b.h+2);
    ctx.fillStyle=b.fill;
    ctx.fillRect(b.x,b.y,b.w,b.h);
    ctx.strokeStyle=b.stroke;
    ctx.strokeRect(b.x,b.y,b.w,b.h);
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    ctx.fillStyle=b.labelcolor;
    ctx.fillText(b.label,b.x+b.w/2,b.y+b.h/2);
    if(isDown){
        ctx.beginPath();
        ctx.moveTo(b.x,b.y+b.h);
        ctx.lineTo(b.x,b.y);
        ctx.lineTo(b.x+b.w,b.y);
        ctx.strokeStyle='black';
        ctx.stroke();
    }
}

function findButton(mx,my){
    for(var i=0;i<buttons.length;i++){
        var b=buttons[i];
        if(mx>b.x && mx<b.x+b.w && my>b.y && my<b.y+b.h){
            return(buttons[i]);
        }
    }
    return(null);
}

function handleMouseDown(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  
  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  // check if a button was clicked under the mouse
  var b=findButton(mouseX,mouseY);
  if(b){
      clickedButton=b;
      drawButton(b,true);
      b.click();
  }
}

function handleMouseUpOut(e){
  // tell the browser we're handling this event
  e.preventDefault();
  e.stopPropagation();
  
  // release any clicked button
  if(clickedButton){
      drawButton(clickedButton,false);
      clickedButton.release();
      clickedButton=null;
  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4 id=clicked>Click a button.</h4>
<canvas id="canvas" width=300 height=300></canvas>
markE
  • 102,905
  • 11
  • 164
  • 176
  • 1
    +1 Though I will point out that for users the OP should consider checking every mousemove if the mouse is over the button and provide feedback (either with appropriate cursor `canvas.style.cursor = "pointer";` or button effect). This gives a very positive feel to the whole UI. Also users are generally used to the ability to drag away from the button if they change their mind mid click. The click should only be register when both the down and up events are over the button. – Blindman67 Apr 19 '16 at 01:22
  • @Blindman67. Good point! :-) For production I certainly would expand my (very!) simple buttons to include hover/blur effects and another hit-test in mouseup & mouseout to allow for cancellation. – markE Apr 19 '16 at 01:54
  • Confused as to what the variable b is. – MickDom Apr 21 '16 at 03:34
  • variable `b` equals each button object as we move through the `buttons` array -- `b` is a cache variable. The reason a cache variable is used is so we don't have to make the browser repeatedly take the effort to look up the `i-th` element in the buttons array. – markE Apr 21 '16 at 03:44