Coordinates given from the wrong element - javascript

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.

Related

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?

Do DOM events work with pointer lock?

I have used the pointer lock on my canvas element, and the canvas is on full screen. I want to detect right clicks and left clicks to respond to them. Is it possible to respond to clicks in full screen and pointer lock? I already know how to use the pointer lock api and the fullscreen api, I don't want any answers explaining how to use them. Any help would be appreciated.
Based on the experiments I've done, the short answer is "it depends." Take a look at the following demo. There is a canvas scaled to be a quarter of the screen size in each dimension. When you move the cursor over it, a white circle appears on the canvas. When you left click, you'll draw a red circle to the canvas, and when you right click, you'll draw a cyan circle to the canvas. When you click the "Full screen" button, you'll activate pointer lock and enter fullscreen mode. If you press the "Esc" key, you'll exit pointer lock and fullscreen mode.
Note that you'll need to copy and paste the code into a file and load it. The demo won't run if you just click "Run code snippet."
As far as your question, there are two issues, I'm aware of:
In Chrome, both right- and left-click events are triggered even while in fullscreen/pointer lock. However, in Firefox, only left-click events are triggered; I was unable to get right-click events using any of the handlers I tried (click, mousedown, mouseup, contextmenu). When not in fullscreen/pointer lock, both left- and right-click events get triggered as expected in both browsers. If anyone has any solutions for listening to right-click events while in fullscreen/pointer lock, I'd love to hear them.
It seems that in pointer lock in both Chrome/Firefox, events no longer trickle down to elements contained in the element with pointer lock, but they continue to bubble up to parent elements. So in the demo, the canvas is inside a div. The div has pointer lock. onclick handlers are attached to the canvas, div, and document to report click events in the console. Without pointer lock, clicking on the canvas triggers onclick handlers for all three elements (canvas, div, and document). However, with pointer lock on the div, the onclick handler for the canvas never gets triggered, though the handlers for the div and the document do.
I also identified a couple other quirks to Firefox that, while not directly related to your initial question, might be helpful to folks interested in implementing this sort of thing:
When fullscreen mode is entered, Firefox will apply styles to the fullscreen element to get it to fill the screen. I was unable to get the canvas styled correctly (i.e. to take up the full screen) when it was placed full screen. Rather, I had to wrap the canvas in a div and enter full screen on the div. See the Fullscreen API documentation on MDN for more info:
if you're trying to emulate WebKit's behavior on Gecko, you need to place the element you want to present inside another element, which you'll make fullscreen instead, and use CSS rules to adjust the inner element to match the appearance you want.
In Firefox, activating fullscreen mode deactivated pointer lock. In order to get both activated, I had to first activate fullscreen mode and then activate pointer lock. However the simple two lines of code:
canvasContainer.requestFullscreen();
canvasContainer.requestPointerLock();
did not work. My understanding of what was happening is that the call to requestPointerLock got initiated before full screen mode was fully established. This led to pointer lock being activated and then quickly deactivated again. I found it necessary to wait until fullscreen mode was fully established before calling requestPointerLock(). Checking that document.mozFullScreenElement !== null seemed to be sufficient for checking that full screen mode was completely operational. The following following click handler definition worked to solve this problem for me:
document.getElementById('fullscreen_button').onclick = function(e) {
// When button is clicked, enter both full screen and pointer lock
canvasContainer.requestFullscreen();
var timeout = 2000;
var interval = window.setInterval(function() {
if (document.mozFullScreenElement !== null) {
window.clearInterval(interval);
canvasContainer.requestPointerLock();
} else if (timeout <= 0) {
addErrorMessage('Unable to establish pointer lock.');
clearTimeout(interval);
} else {
timeout -= 50;
}
}, 50);
}
This function repeatedly checks if full screen mode is established. When it is, it initiate pointer lock. If fullscreen mode can't be determined after 2 s, it times out.
I haven't done any testing in IE.
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<style>
</style>
</head>
<body>
<p id="msgs">Click 'Full screen' button below to go full screen. <br>
Click the left mouse button to draw a red circle. <br>
Click any other mouse button to draw a cyan circle. <br>
Press the 'Esc' key to exit full screen.</p>
<div id="canvas_container">
<canvas id="canvas"> </canvas>
</div>
<br>
<button id='fullscreen_button'>Full screen</button>
</body>
<script>
// Display constants
var CANVAS_BG_COLOR = 'rgb(75, 75, 75)';
var LEFT_CLICK_COLOR = 'rgb(255, 150, 150)';
var OTHER_CLICK_COLOR = 'rgb(150, 255, 255)';
var CURSOR_COLOR = 'rgb(200, 200, 200)';
var CANVAS_SCALING_FACTOR = 4; // Ratio between screen dimension and canvas dimension before going full-screen
// Store mouse position
var mouseX, mouseY;
// Setup onscreen canvas, smaller than the screen by a factor of CANVAS_SCALING_FACTOR
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = screen.width/CANVAS_SCALING_FACTOR;
canvas.height = screen.height/CANVAS_SCALING_FACTOR;
// Create an offscreen canvas that's the same as the size of the screen
var offscreenCanvas = document.createElement('canvas');
var offscreenCtx = offscreenCanvas.getContext('2d');
offscreenCanvas.width = screen.width;
offscreenCanvas.height = screen.height;
var canvasContainer = document.getElementById('canvas_container');
// Radius of the circle drawn and of the circle cursor
var circleRadius = 12;
var cursorRadius = circleRadius/CANVAS_SCALING_FACTOR
offscreenCtx.drawCircle = ctx.drawCircle = function (x, y, color, radius) {
this.fillStyle = color;
this.beginPath();
this.arc(x, y, radius, 0, 2*Math.PI, true);
this.fill();
}
offscreenCtx.clearCanvas = function() {
this.fillStyle = CANVAS_BG_COLOR;
this.fillRect(0, 0, this.canvas.width, this.canvas.height);
}
ctx.update = function() {
// Copy the offscreen canvas, scaling down if not in full-screen mode
this.drawImage(offscreenCanvas, 0, 0, offscreenCanvas.width, offscreenCanvas.height,
0, 0, canvas.width, canvas.height);
// Draw the cursor
this.drawCircle(mouseX, mouseY, CURSOR_COLOR, cursorRadius);
}
function pointerLockActive() {
return document.pointerLockElement===canvasContainer || document.mozPointerLockElement === canvasContainer;
}
// Perform initial canvas setup
offscreenCtx.clearCanvas();
ctx.update();
// Setup pointerlock and fullscreen API functions for cross-browser support
function addErrorMessage(msg) {
document.getElementById('msgs').innerHTML += ('<br><font color="red">' + msg + '</font>');
}
canvasContainer.requestPointerLock = canvasContainer.requestPointerLock || canvasContainer.mozRequestPointerLock;
canvasContainer.requestFullscreen = canvasContainer.webkitRequestFullscreen || canvasContainer.mozRequestFullScreen || canvasContainer.msRequestFullscreen
if (!canvasContainer.requestPointerLock) addErrorMessage('Error: Pointer lock not available');
if (!canvasContainer.requestFullscreen) addErrorMessage('Error: Full screen mode not available');
canvasContainer.addEventListener('mousemove', function(e) {
if (pointerLockActive()) {
// If in pointer lock, then cursor positions need to be updated manually;
// Normal cursor positions (e.g. e.clientX and e.clientY) don't get updated in pointer lock
mouseX += e.movementX, mouseY += e.movementY;
// Prevent the mouse from moving off-screen
mouseX = Math.min(Math.max(0, mouseX), canvas.width);
mouseY = Math.min(Math.max(0, mouseY), canvas.height);
} else {
// If pointer lock is inactive, then mouse position is just position relative to canvas offset
mouseX = (e.pageX - canvas.offsetLeft)
mouseY = (e.pageY - canvas.offsetTop)
}
ctx.update(); // Update the onscreen canvas
}, false);
// Handle entering and exiting pointer lock; pointer lock status is yoked to full screen status; both are entered and exited at the same time
document.addEventListener('pointerlockchange', function(e) {
if (!pointerLockActive()) {
console.log('Pointer lock deactivated');
canvas.width /= CANVAS_SCALING_FACTOR;
canvas.height /= CANVAS_SCALING_FACTOR
cursorRadius /= CANVAS_SCALING_FACTOR;
} else {
console.log('Pointer lock activated')
canvas.width *= CANVAS_SCALING_FACTOR;
canvas.height *= CANVAS_SCALING_FACTOR;
cursorRadius *= CANVAS_SCALING_FACTOR;
// Set the initial mouse position to be the middle of the canvas
mouseX = screen.width/2, mouseY = screen.height/2;
}
// Update the onscreen canvas
ctx.update();
});
document.getElementById('fullscreen_button').onclick = function(e) {
// When button is clicked, enter both full screen and pointer lock
canvasContainer.requestFullscreen();
var timeout = 2000;
var interval = window.setInterval(function() {
if (document.mozFullScreenElement !== null) {
window.clearInterval(interval);
canvasContainer.requestPointerLock();
} else if (timeout <= 0) {
addErrorMessage('Unable to establish pointer lock.');
clearTimeout(interval);
} else {
timeout -= 50;
}
}, 50);
}
canvasContainer.onclick = function(e) {
console.log('canvasContainer clicked');
if (pointerLockActive())
// If pointer lock is active, then use the mouseX and mouseY positions that are manually updated by the mousemove event handler
var cursorX = mouseX, cursorY = mouseY;
else
// Otherwise use the mouse positions passed in the event object
// If not in full screen mode, the cursor position has to be scaled up, because the mouse position is relative to the onscreen canvas, but we're drawing on the offscreen canvas, which is larger by a factor of fullscreenScale
var cursorX = (e.pageX - canvas.offsetLeft)*CANVAS_SCALING_FACTOR, cursorY = (e.pageY - canvas.offsetTop)*CANVAS_SCALING_FACTOR;
// If the left mouse button is clicked (e.which===1), draw a circle of one color
// If any other mouse button is clicked, draw a circle of another color
var color = e.which === 1 ? LEFT_CLICK_COLOR : OTHER_CLICK_COLOR;
offscreenCtx.drawCircle(cursorX, cursorY, color, circleRadius);
ctx.update();
};
// Detect canvas right-click events. Prevent default behavior (e.g. context menu display) and pass on to the onclick handler to do the rest of the work
canvasContainer.oncontextmenu = function(e) {
e.preventDefault();
this.onclick(e);
}
canvas.onclick = function() {
console.log('canvas clicked');
}
document.onclick = function() {
console.log('document clicked');
}
</script>
</html>
This worked for me to handle rightClick after pointer was locked.
const onMouseDown = (evt) => {
switch (evt.which) {
case 1: return handleLeftClick();
case 3: return handleRightClick();
}
};
document.body.addEventListener('mousedown', onMouseDown, true);

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

Hide the cursor and make it stop moving using Javascript

I'm making a 3D game where the camera needs to be pretty much identical to the World of Warcraft one. That means, that once the screen is clicked, the cursor disappears, and when the mouse is moved, the camera rotates around a focus point (the player).
I made most of the code, the cursor does disappear when the screen is clicked, but the problem is that it is still moving, even though it isn't shown. That feels unnatural, and I'd like to have the cursor to stay at the same spot for the whole time.
So, how do I achieve this with Javascript?
The only support reqs are the latest versions of Chrome and Firefox.
You can't manipulate the position of the cursor like that in JavaScript because of the security implications that it incurs.
If I am getting your question right,
Not possible via javascript, you will need flash.
But yes, some progess is really going on,
Pointer lock api
Update: (I had free time, so I played with it)
You can try something like this, its not perfect,not recommended and it fails when original mouse reaches the screen borders (however you can restrict the mouse movements in a wrapper, that will solve the problem).
Html:
<body style='width:100%;min-height:800px;overflow:hidden'>
<img id='fakeCursor' src='http://i50.tinypic.com/359d3km.jpg' style='z-index:1000;position:absolute;display:none' />
<div href='javascript:void(0);' style='position:absolute;left:50px;top:10px;width:100px;height:100px;background:gray;' onclick='console.log("fake click 1");return false;'>Fake click 1</div>
<div href='javascript:void(0);' style='position:absolute;left:50px;top:130px;width:100px;height:100px;background:gray;' onclick='console.log("fake click 2");return false;'>Fake click 2</div>
</body>
Javascript:
var clientX,clientY;
var fakeCursor = document.getElementById('fakeCursor');
var isFakeMouse = false;
document.onclick = function(e){
if(isFakeMouse){
if(document.elementFromPoint(fakeCursor.style.left,fakeCursor.style.top)!=null){
document.elementFromPoint(fakeCursor.style.left,fakeCursor.style.top).click();
return false;
}
fakeCursor.style.display = 'inline';
fakeLeft = clientX;
fakeTop = clientY;
var mouseLastLeft = -1;
var mouseLastTop = -1;
document.onmousemove = function(e){
if(mouseLastLeft ===-1 && mouseLastTop ===-1){
mouseLastLeft = e.clientX;
mouseLastTop = e.clientY;
return;
}
fakeCursor.style.left = (parseInt(fakeCursor.style.left) + ((mouseLastLeft - e.clientX)*-1)) + 'px';
fakeCursor.style.top = (parseInt(fakeCursor.style.top) + ((mouseLastTop - e.clientY)*-1)) + 'px';
mouseLastLeft = e.clientX;
mouseLastTop = e.clientY;
}
}
else{
isFakeMouse = true;
document.body.style.cursor = "none";
fakeCursor.style.display = 'none';
fakeCursor.style.left = clientX = e.clientX;
fakeCursor.style.top = clientY = e.clientY;
document.onmousemove = null;
}
}
Here, at first click on document, the real mouse hides. When user clicks document again, real mouse would be still hidden and a new fake mouse (an image) will take its place. Position of the fake mouse would be the same where user has left the real mouse. fake mouse works (tries) to work like real mouse.
Sorry for inline css and javascrict

Categories