Simulating a mouse click at (x, y) on an HTML5 canvas element - javascript

I've been attempting to programmatically simulate a mouse click at arbitrary coordinates on a canvas element. Because of technology constraints, I need to avoid jQuery which would make this easier.
Using this answer, I am able to get coordinates of manual clicks.
Using this answer, I'm able to programmatically simulate a mouse click. But unfortunately I need to de-jQuery-ify it, which is, I think, where I've run into problems.
If I try to do something like:
document.querySelector("canvas").dispatchEvent(new Event("mousedown", {pageX: 1, pageY: 1}));
or
document.querySelector("canvas").dispatchEvent(new MouseEvent("mousedown", {pageX: 1, pageY: 1}));
or combinations of the above using 'click' instead of 'mousedown'
I still get strange 'undefined' errors that I don't understand (other than that I can see they are referring to 'mousedown') and never successfully simulate the click.
Some working (and not working) examples:
Working: Displays coordinates of clicks
Working: Fires a programmatic click
Not Working: Combining the two above
Not Working: Trying to fire a programmatic click without jQuery

The problem with your jQuery approach is that you are mixing it with a plain JavaScript event listener. This does not work with jQuery.
If you want to trigger an event and listen it using jQuery you have to use it's .trigger() and .mousedown() methods.
Here's an example:
function getMousePosition(canvas, event) {
let rect = canvas.getBoundingClientRect();
let x = event.clientX - rect.left;
let y = event.clientY - rect.top;
document.getElementById('output').innerText = x + ", " + y;
}
canvasElem = document.querySelector("canvas");
$('#canvas_element').mousedown(function(e) {
getMousePosition(canvasElem, e);
});
var e = jQuery.Event("mousedown", {
clientX: 50,
clientY: 50
});
$('#canvas_element').trigger(e);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas_element"></canvas>
<div id="output"></div>
All of the above can be done using just JavaScript too of course.
function getMousePosition(canvas, event) {
let rect = canvas.getBoundingClientRect();
let x = event.clientX - rect.left;
let y = event.clientY - rect.top;
document.getElementById('output').innerText = x + ", " + y;
}
canvasElem = document.querySelector("canvas");
canvasElem.addEventListener("mousedown", function(e) {
getMousePosition(canvasElem, e);
});
canvasElem.dispatchEvent(new MouseEvent("mousedown", {
clientX: 50,
clientY: 50
}));
<canvas id="canvas_element"></canvas>
<div id="output"></div>

Related

Dragend client coordinates incoherent on Safari and Firefox

Currently working on image editing with some drag&drop.
Having something functional on chrome, but on Safari, dragend event returns stupid coordinates (e.clientX and e.clientY). Just tried on Firefox, and the values are now empty.
So this is supposed to return the mouse position on canvas when the user drops an image, which works great on Chrome, but on Safari clientX is way too big and clientY is negative...
sticker.addEventListener("dragend", (e) => {
let coords = new Array(
document.getElementById("canvas").getBoundingClientRect()
).map((rect) => {
console.log(e.clientX(e.clientY));
return [(e.clientX - rect.left)(e.clientY - rect.top)].join();
});
});
My solution was to keep track of the position given by the drag callback function (which doens't have the problem 'dragEnd' have) and then when 'dragEnd' is triggered I just use the last values from those temp variables.
Example:
drag (ev) {
this.last_x = ev.clientX;
this.last_y = ev.clientY;
...
},
dragEnd (ev) {
this.x = this.last_x;
this.y = this.last_y;
...
}
I hope this help.
Some browsers will indeed return fake values for this event, because it may well occur on a different document and even an other application than the one your page is running on.
This is somehow information leakage, and browsers don't like it.
An easy workaround is to instead listen to the drop event that should fire on your canvas element. In this event, it is admitted that the user gave you all permissions about the dragged content, so browsers will give you the correct coordinates.
const ctx = canvas.getContext('2d');
ctx.fillText('drop here', 20, 20);
canvas.addEventListener('drop', e => draw(e, 'red'));
canvas.addEventListener('dragover',e=>e.preventDefault());
sticker.addEventListener('dragstart', e=>{e.dataTransfer.setData('text', null)});
function draw(e, color) {
e.preventDefault();
const rect = canvas.getBoundingClientRect();
ctx.beginPath();
ctx.arc((e.clientX - rect.left), (e.clientY - rect.top), 5, 0, Math.PI*2);
ctx.fillStyle = color;
ctx.fill();
}
canvas {
border:1px solid;
}
<div id="sticker" draggable="true">drag me</div>
<canvas id="canvas"></canvas>

Click on HTML5 canvas

I want to simulate clicks on a canvas with javascript\jQuery for testing reasons, but I didn't find a solution. Here's my code:
var e = new jQuery.Event("click");
e.pageX = X[index];
e.pageY = Y[index];
$("#gamecanvas").trigger(e);
Is it possible to do that ?
For example this game (I searched randomly on the web) How can I click from JS\jQuery ?
It depends on the event's used on the canvas , whether it's a click , mousedown , .... etc
In the example you just mentioned , the lucn event uses two event :
One (mousemove) for calculating coordinate to get clientX and clientY
Second (mousedown) for lunching ball using last calculated coordinate
So your code should be like :
var mousemove = new jQuery.Event("mousemove");
mousemove.clientX = x;//passed valuue
mousemove.clientY =y;//passed valuue
var mousedown = new jQuery.Event("mousedown");
$("#canvas").trigger(mousemove);
$("#canvas").trigger(mousedown);
Here a pluncker where I created a script to luanch a ball with passed input coordinate or jus throw the ball in the basket directly :)
See here livePlunker
See url code plunker
Hope this will help :
This example may help you
$('#canvas_element').on("mousedown mouseup", function(e) {
$('#output').text($('#output').text() + (e.type + " event fired at coords: " + e.pageX + ", " + e.pageY));
});
x_coord = 1;
y_coord = 1;
var e = jQuery.Event( "mousedown", { pageX: x_coord, pageY: y_coord } );
$('#canvas_element').trigger(e);
// execute more code
var e = jQuery.Event( "mouseup", { pageX: 255, pageY: 255 } );
$('#canvas_element').trigger(e);
working link
This is because, pageX and pageY doesn't get the coordinates of the canvas, I had the same issue my self when trying to create a signature pad.
use this instead:
var e = new jQuery.Event("click");
//for IE, safari, opera, chrome
if(e.offsetX != null) {
e.offsetX= X[index];
e.offsetY= Y[index];
}
//for firefox
if(e.layerX!= null) {
e.layerX= X[index];
e.layery= Y[index];
}
$("#gamecanvas").trigger(e);
Without know you use case the documentation for jQuery tells me yes:
http://api.jquery.com/trigger/
Why you don't search by your self through the very well documented API for jquery?

Coordinates given from the wrong element

I am trying to learn Javascript by following a guide on creating a Minesweeper game using a canvas. It's all going great apart from the fact that when I click on the options bar, it registers it as a click on the canvas.This is a screenshot of the whole game so far. I can still click on the canvas and it works as it should, but clicking on the options bar (The part with the smiley face), it also registers as a click on the canvas, and removes one of the tiles.
Here is the code that registers the mouse click:
'
if(e.offsetX) { //Get's mouse pos relative to the canvas pos
mouseX = e.offsetX;
mouseY = e.offsetY;
}
else if(e.layerX) {
mouseX = e.layerX;
mouseY = e.layerY;
}
//mouseX = e.pageX; //Gets mouse pos relatiove to page
//mouseY = e.pageY;
//console.log("Mouse Pos on screen (x, y) = " + mouseX + "," + mouseY);//Validate that the mouse position is being recorded.
//Algorithm to tell which cube the click was on.
if (Math.floor(mouseX/settings.width) < settings.columns && Math.floor(mouseY/settings.height) < settings.rows){
clickX = Math.floor(mouseX/settings.width);
clickY = Math.floor(mouseY/settings.height);
console.log("Coords of clicked box (x,y)" + clickX + "," + clickY);
}
`
Hopefully this is enough for someone to find a problem with it, because I can't.
I think the problem is that you're capturing the click events for the whole window in one function, so whether you're clicking on the canvas or the new game div, or elsewhere in the window, you're trying to apply that click to your canvas. You'd be better advised to have a click event for the canvas itself, and another click event for the new game (which should really be a button, not a div, but I digress)
If you really want to carry on this way, you could explicitly limit your function to only care about your canvas. if you make gCanvas global (shudder)
var gCanvas = null;
function canvasLoad() {
gCanvas = document.getElementById("gameCanvas");
...
}
Then in your event function you can check the target of the event and only action on things that fired from your canvas
window.onclick = function(e){
...
//Algorithm to tell which cube the click was on.
if (
(e.target === gCanvas )
)
{
if (Math.floor(mouseX/settings.width) < settings.columns &&
Math.floor(mouseY/settings.height) < settings.rows)
{
clickX = Math.floor(mouseX/settings.width);
clickY = Math.floor(mouseY/settings.height);
console.log("Coords of clicked box (x,y)" + clickX + "," + clickY);
}
}
Note that this isn't the solution I'd go with. A tighter binding of the event to the object that fired it is much more satisfactory.
<canvas id = "gameCanvas" width="153" height="153"
style="border:1px solid #000000;" #
onclick='return myCanvasEventHandler()'></canvas>
This will explicitly limit the myCanvasEventHandler() function to fire only on events from the canvas itself.

How to sense if a certain area of an Html Canvas is clicked

I am making a game on a canvas which requires clicking a certain area of a canvas.
I need to find a way to find the coordinates of a mouse and how to sense if a cartain area is clicked.
i want a command that looks like this:
if(MouseX>20 && MouseX<40 && MouseY >20 && MouseY <40 && MouseClick==true){
alert("you clicked this area");
}
You could create an event listener for your mouse move and track you x and y coordinate. Another listener will could be created for the click event and that is when you can access if the click was in a certain location.
fiddle
var mousePos = {
x: null,
y: null
}
document.addEventListener("mousemove", function(e) {
mousePos.x = e.clientX;
mousePos.y = e.clientY;
});
document.addEventListener("click", function(e) {
console.log(mousePos);
});
Both listeners are not strictly necessary, since the clientX and clientY are both on the event of the click, but I find that it is usually good to know the location of the mouse even when the button has not just been clicked.
UPDATE
I am used to dealing with full screen canvases, but it is true that the code I have put here will only give you mouse position on the document and not the canvas. .layerX and .layerY on the event object will give you the position relative to your element.
If you are interested just in canvas area, use this cross-browser code:
var canvas = document.querySelector('canvas');
canvas.addEventListener('click', function (e) {
var MouseX = e.pageX - this.offsetLeft;
var MouseY = e.pageY - this.offsetTop;
});

Create text at click location onclick

So I need text to appear at the location I click in a program I'm working on, problem is I have absolutely no idea how to do it. So my questions are:
Is this possible?
If so, what can I do to achieve this result?
Thanks for any guidance <3 I'm currently using javascript but if I require a plugin like jquery to do this, I'm open to suggestions.
More detail: when I click on a canvas, anywhere on it - I want the ability to output text at that location. Eventually I will have separate texts appear above, below, left and right of the click location so the user knows what forces are coming from where.
you could get the clientX and clientY of the mouseclick position with your own function using the javascript addEventListener method. once you get the position of the mouseclick, you could use javascript.createElement("P") and position that element exactly where you want it. look more into these two links: http://www.kirupa.com/html5/getting_mouse_click_position.htm and http://www.htmlforums.com/html-xhtml/t-putting-text-in-a-specific-location-129657.html. an example code could be this
<html>
<body>
<script type="text/javascript">
var body = document.body;
body.addEventListener("click", getPosition);
function getPosition(e)
{
var x = e.clientX;
var y = e.clientY;
document.write("<p id='add'>TEXT</p>");
var text = document.getElementById('add');
text.style.position = "absolute";
text.style.top = y;
text.style.left = x;
}
</script>
</body>
</html>
You can get the click location like below and use that to place your text.
$("#myButton").click(function(e) {
alert(e.clientX + ", "+ e.clientY);
})
canvas.addEventListener("mousedown", getPosition, false);
function getPosition(event)
{
var x = event.x;
var y = event.y;
var canvas = document.getElementById("canvas");
x -= canvas.offsetLeft;
y -= canvas.offsetTop;
}

Categories