Is the isPointToPath function unreliable in JS/CANVAS/HTML?

Check out the snippet below for testing purposes.

The yellow(y) area represents the canvas, returning "n" upon clicking

The red(r) area represents the clickable region, returning "y" upon clicking

The trouble(x) area indicates an error, returning "y" when clicked

How can we fix this?

yyyyyyyyyyyyyyy
yyrrrrrrrrrrryy
yyrrrrrrrrrrryy
yyxxxxxxxxxxxyy
yyyyyyyyyyyyyyy

const canvas = document.getElementById('test');
const context = canvas.getContext('2d');

testClicker();

function testClicker() {
  const buttonz = new Path2D();
  buttonz.rect(canvas.width / 2 - 125, canvas.height / 2 - 70, 250, 80);
  context.fillStyle = 'red';
  context.fill(buttonz);

  var mouseEvent = (event) => {
    // Check whether point is inside rect
    const isPointInPath = context.isPointInPath(buttonz, event.offsetX, event.offsetY);
    let output = isPointInPath ? 'y' : 'n';
    alert(output);
  }

  canvas.addEventListener("click", mouseEvent, false);
}
* {
  margin: 0px;
  padding: 0px;
}

#test {
  position: fixed;
  top: 1%;
  left: calc(50% - 150px);
  width: 300px;
  height: 100px;
  background: yellow;
}
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="style.css">
<html>

<body>
  <canvas id="test"></canvas>
</body>
<script src="main.js"></script>

</html>

Answer №1

You have encountered a discrepancy in the CSS height setting of the canvas (100px) and the canvas's default attribute height (set to 150px).

Your current method relies on canvas.height for path drawing on the canvas.

To address this issue, this code snippet adjusts the height attribute of the canvas to 100.

const canvas = document.getElementById('test');
const context = canvas.getContext('2d');

testClicker();

function testClicker() {
  const buttonz = new Path2D();
  alert(canvas.height);
  buttonz.rect(canvas.width / 2 - 125, canvas.height / 2 - 70, 250, 80);
  context.fillStyle = 'red';
  context.fill(buttonz);

  var mouseEvent = (event) => {
    // Check whether point is inside rect
    alert(event.offsetY);
    const isPointInPath = context.isPointInPath(buttonz, event.offsetX, event.offsetY);
    let a = isPointInPath ? 'y' : 'n';
    alert(a);
  }

  canvas.addEventListener("click", mouseEvent, false);
}
* {
  margin: 0px;
  padding: 0px;
}

#test {
  position: fixed;
  top: 1%;
  left: calc(50% - 150px);
  width: 300px;
  height: 100px;
  background: yellow;
}
<!DOCTYPE html>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<link rel="stylesheet" href="style.css">
<html>

<body>
  <canvas id="test" width="300" height="100"></canvas>
</body>
<script src="main.js"></script>

</html>

Refer to MDN for more information on how setting canvas dimensions using attributes vs. CSS can result in scaling or distortion if they do not match.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Enable the button if at least one checkbox has been selected

I've written some code similar to this: $('input[type=checkbox]').click(function(event) { $('.chuis').each(function() { if(this.checked) { $('#delete_all_vm').prop("disabled",false); } ...

JavaScript's ability to pinpoint individual hits stands out as a distinguishing feature

Is there a creative approach to identifying a distinct user using JavaScript, such as generating a hash to transmit to the server-side? EDIT: The challenge is that I am unable to access the browser directly (e.g. set cookies). Additionally, relying on IPs ...

Comparison of Angular.js formsets to Django's formset

Within Django, formsets allow for the use of multiple forms within one larger form. For example, you can add multiple books to a library formset by repeating the same book form with details such as author and title. I am looking to achieve similar functio ...

Tips for sending data scraped from a website using Express

I have created a web crawler using Axios and am attempting to upload a file through Express. I currently have 10 different crawlers running with corresponding HTML form methods in Express. However, when I click the button, it downloads a blank file first ...

Getting the true height without needing jQuery

let element = document.getElementById('test'); console.log(element.scrollHeight); <div style="height: 30px;" id="test"> <p>ffffffffff</p> <p>gggggggggg</p> ...

Is it feasible to overlay a PNG image on top of a button while still allowing the button to be clickable?

Can you place an image (.png) on top of a button and still make the button clickable? https://i.sstatic.net/9Z8nH.jpg ...

Forwarding requests via middleware in next.js 13 AppDir: true

I am currently working on implementing a redirect feature in next.js 13 when the jwt back-end is not received. This is being done with the appdir activated. This is the code in my middleware.ts file: import { NextResponse } from 'next/server' im ...

Tips for filling jstree with information in Grails

I am currently facing difficulties in populating a jstree within a Grails gsp. Here is what I have attempted so far (rewritten for clarity): <script> $("#treeView").jsTree(); </script> <div id="treeView"> <g:each in="${atomMa ...

The mp4 video on the website will only load if the Chrome developer tools are activated

Whenever I try to play the video set as the background of the div, it only starts playing if I refresh the page with Chrome dev tools open. HTML: <div id="videoDiv"> <div id="videoBlock"> <img src="" id="vidSub"> <video preload="prel ...

Redirecting an Incorrect Request to a 404 Error Page

I am working on setting up a server that will allow users to access specific valid paths: localhost:9090/admin localhost:9090/project1 If a user enters any other invalid paths, they should be redirected to the root and then to the default path localhos ...

Detecting slopes using THREE.js

Can someone please advise on how to properly detect slopes in a car game? I want the car to recognize the slope as such, rather than mistaking it for a collision object. I've been looking everywhere for answers but have yet to come across anything use ...

Sending JSON data from AngularJS to Laravel Controller through POST request

I have encountered an issue while using AngularJS to send POST data to a Laravel controller for saving into a database. The problem lies in the incorrect parsing of data from AngularJS to Laravel. The data being passed looks like this: $scope.invoice_ite ...

CSS3PIE is failing to function properly in Internet Explorer

Looking for a solution to achieve rounded corners in Internet Explorer? Consider using . In my CSS file named template.css, I have included the following code which is loaded when the page loads on Joomla 1.5. .form_field {color:#222 !important; border:2p ...

Changing a JSON object into an array

Is there a way to transform the data below using either lodash or JavaScript : [ { "roleId": "1", "name": "Superadmin" "permissions": [ { "permissionId": "1", "action": "Remove" } ] }, "id": "2", "name" ...

Is there a way to trigger the bootstrap datetimepicker when a custom button is clicked, while also storing the selected value in a hidden textbox

When the ADD button is clicked, a datetimepicker should open. After selecting a value from the datetimepicker, it should be saved in the textbox with ID #myTextBox. <div> <input id="myTextBox" type="text" ng-model="c" data-provide="datepicker ...

Issue with login form in IONIC: Form only functions after page is refreshed

Encountering an issue with my Ionic login form where the submit button gets disabled due to invalid form even when it's not, or sometimes displays a console error stating form is invalid along with null inputs. This problem seems to have surfaced afte ...

Arrange TD's from various TR's underneath each other in a stack

Imagine we have a table that needs to be made responsive. <table> <tr> <td>Dog Image</td> <td>Cat Image</td> </tr> <tr> <td>Dog Text</td> <td>Cat Text</td> & ...

Exploring the complete range of bootstrap classes within collapsible buttons and editing them to suit your needs

I am currently working on implementing collapsible buttons into my web application, which is created using Google Apps Script (GAS). The buttons are functioning correctly and toggle the content visibility as intended through jQuery. I have inserted the ne ...

How to extract selected value from a dropdown menu in a React component

Is there a way for me to retrieve the chosen value from the dropdown menu? The select dropdown contains 12 options. My goal is to capture the selected value and then utilize it in handlecolumnchange to manipulate the number of columns added or removed. Des ...

Distinguishing between creating controllers in AngularJS

I am a beginner in the world of AngularJS and I have come across two different examples when it comes to creating a controller. However, the one that is more commonly used doesn't seem to be working for me. The problem with the first example is that ...