20

I am new to Javascript and i am in the process of making a project web based (HTML) With my basic knowledge i have managed to create a form and drawn a rectangle on it.

I would now like to be able to click the rectangle , using it like a button but I cannot seem to find any tutorials or answers that can help me.

This is the code for my rectangle :

function Playbutton(top, left, width, height, lWidth, fillColor, lineColor) {
    context.beginPath();
    context.rect(250, 350, 200, 100); 
    context.fillStyle = '#FFFFFF'; 
    context.fillStyle = 'rgba(225,225,225,0.5)';
    context.fillRect(25,72,32,32);
    context.fill(); 
    context.lineWidth = 2;
    context.strokeStyle = '#000000'; 
    context.stroke();
    context.closePath();
    context.font = '40pt Kremlin Pro Web';
    context.fillStyle = '#000000';
    context.fillText('Start', 345, 415);
  }

I am aware that you need to find the x,y coordinates and mouse position in order to click in the area of the rectangle. But i'm really stuck at this point. It maybe really simple and logic, but we have all had to go past this stage.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
user3770735
  • 205
  • 1
  • 3
  • 5
  • I understand you want to draw your button on a canvas. Is there a specific need for this, or may I advise you to use the HTML `` tag and style it via CSS, which would be the standard way. Any mouse events and so on are then handled without further configuration by the browser. – Peter Sorowka Jun 24 '14 at 10:36
  • 1
    If you need to do this on a canvas element, here is a good answer: http://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element. I would use a – jme11 Jun 24 '14 at 10:44
  • I also suggest you to use HTML and CSS for the layout as previous posters suggested. For the JavaScript part I would recommend you to use jQuery. It's a very easy to use library. Drawing things with canvas as in your example is used for more advanced things. Very few websites use it at the moment. – B. Martin Jun 24 '14 at 10:47
  • Thank you for you answers. To summarize my project , I have successfully drawn a football pitch on canvas (World cup related), and have drawn 8 t-shirts which are fully functional and are used as buttons when a player chooses a color. Once both teams have chosen their shirt color. A "Play" button appears and this is the button that I can't seem to make 'clickable'. I have already seen posts using and – user3770735 Jun 24 '14 at 11:05

2 Answers2

21

You were thinking in the right direction. You can solve this multiple ways like using a html button as suggested in the comments.

If you do need to handle click events inside your canvas you can add a click handler to the canvas. This code will determine if the mouse pointer is inside your bounding rectangle:

// Function to get the mouse position
function getMousePos(canvas, event) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: event.clientX - rect.left,
    y: event.clientY - rect.top,
  };
}

// Function to check whether a point is inside a rectangle
function isInside(pos, rect) {
  return pos.x > rect.x && pos.x < rect.x + rect.width && pos.y < rect.y + rect.height && pos.y > rect.y
}

// The rectangle should have x,y,width,height properties
var rect = {
  x: 100,
  y: 100,
  width: 200,
  height: 100,
};

// Binding the click event on the canvas
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
canvas.addEventListener('click', function(evt) {
  var mousePos = getMousePos(canvas, evt);

  if (isInside(mousePos, rect)) {
    alert('clicked inside rect');
  } else {
    alert('clicked outside rect');
  }
}, false);

// Question code
function Playbutton(rect, lWidth, fillColor, lineColor) {
  context.beginPath();
  context.rect(rect.x, rect.y, rect.width, rect.height);
  context.fillStyle = 'rgba(225,225,225,0.5)';
  context.fill();
  context.lineWidth = 2;
  context.strokeStyle = '#000000';
  context.stroke();
  context.closePath();
  context.font = '40pt Kremlin Pro Web';
  context.fillStyle = '#000000';
  context.fillText('Start', rect.x + rect.width / 4, rect.y + 64);
}
Playbutton(rect);
<canvas id="myCanvas" width=800 height=800></canvas>
A1rPun
  • 16,287
  • 7
  • 57
  • 90
  • Thank you very much @A1rPun , this is what I originally had in mind. I have tried this code, unfortunately it still doesn't want to be clicked. But i'm on the right lines now so hopefully I will be able to suss it out much quicker now as I used the same the same function (getMousePos) for the t-shirts a few weeks ago and they work – user3770735 Jun 24 '14 at 11:36
  • I'm glad it helped you but does the jsFiddle not work for you? – A1rPun Jun 24 '14 at 11:51
  • I does work on jsFiddle, but not within my other code. I doesn't appear to change anything but the syntax stays correct – user3770735 Jun 24 '14 at 11:57
  • It still doesn't work , the error message i receive is : Uncaught TypeError: Cannot read property 'x' of undefined – user3770735 Jun 26 '14 at 08:44
  • The `isInside` function expects an object with the properties `x`,`y`,`width` and `height`. – A1rPun Jun 26 '14 at 09:35
  • There is a typo inside `isInside` function, `rect.heigth` change to `rect.height`. – Oen44 Jan 08 '17 at 14:16
4

Path2d may be of interest, though it's experimental:

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath

Basically, you'd do all of your drawing into a Path, and use the .isPointInPath method to do the checking. For a rectangle like you're describing, you can do that math pretty simply, but the glory of this is you can have a complex path set up, and it will do the collision detection for you:

//get canvas/context
const canvas = document.getElementById("myCanvas")
const context = canvas.getContext("2d")

//create your shape data in a Path2D object
const path = new Path2D()
path.rect(250, 350, 200, 100)
path.rect(25,72,32,32)
path.closePath()

//draw your shape data to the context
context.fillStyle = "#FFFFFF"
context.fillStyle = "rgba(225,225,225,0.5)"
context.fill(path)
context.lineWidth = 2
context.strokeStyle = "#000000"
context.stroke(path)

function getXY(canvas, event){ //adjust mouse click to canvas coordinates
  const rect = canvas.getBoundingClientRect()
  const y = event.clientY - rect.top
  const x = event.clientX - rect.left
  return {x:x, y:y}
}

document.addEventListener("click",  function (e) {
  const XY = getXY(canvas, e)
  //use the shape data to determine if there is a collision
  if(context.isPointInPath(path, XY.x, XY.y)) {
    // Do Something with the click
    alert("clicked in rectangle")
  }
}, false)

jsFiddle

Commi
  • 101
  • 1
  • 2