Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 626
user3770735 Avatar asked Jun 24 '14 10:06

user3770735


People also ask

Can I put a button on canvas?

You can, however, position your buttons absolutely over top of a canvas or render areas in your canvas that 'look' like buttons and handle the events yourself (a lot of work).


2 Answers

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

But if you do need to handle click events inside your canvas you can do something like this:

Add a click handler to the canvas and when the mouse pointer is inside your bounding rectangle you can fire your click function:

//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
}

var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//The rectangle should have x,y,width,height properties
var rect = {
    x:250,
    y:350,
    width:200,
    height:100
};
//Binding the click event on the canvas
canvas.addEventListener('click', function(evt) {
    var mousePos = getMousePos(canvas, evt);

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

jsFiddle

like image 93
A1rPun Avatar answered Oct 27 '22 06:10

A1rPun


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

like image 33
Commi Avatar answered Oct 27 '22 06:10

Commi