user3770735
user3770735

Reputation: 215

Simple Button in HTML5 canvas

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.

Upvotes: 21

Views: 66462

Answers (2)

A1rPun
A1rPun

Reputation: 16837

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>

Upvotes: 23

Commi
Commi

Reputation: 91

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

Upvotes: 4

Related Questions