HTML5: Mouse position outside the canvas?

Started by
2 comments, last by JohnnyCode 10 years ago

I've searched on google for a long time now, how do I detect whether the mouse position is outside of the canvas? Once it's outside, the mouse processing stops. A key rule of my game is when a user touches the side of the screen, the game is over. An explosion along the border of the canvas is what's supposed to happen, but using the last known position of the mouse inside the canvas as the explosion point will confuse users. This is a real pain on HTML5, in spite of how easy the port of my existing game has been from C++.

If you don't know what I'm talking about, here's a link to my [unfinished] web port: http://looptil.shogun3d.net (doesn't work on Firefox, yet; use IE, Chrome or Safari).

I understand you can use the events 'mouseout' and 'mouseover' to find out when the mouse leaves the canvas and returns, but how do you get the exact position of the mouse when it's outside the canvas? This sucks. Any ideas? Thanks.

Shogun.

Advertisement

In my JavaScript + HTML5 canvas games, I've written and used this file to deal with mouse input:


(function (window) {
	var mouse = {
		down: false,
		x: -1,
		y: -1
	};

	var previousMouse = {
		down: false,
		x: -1,
		y: -1
	};


	var mouseLetGo = false;



	var updateMouse = function () {
		previousMouse.down = mouse.down;
		previousMouse.x = mouse.x;
		previousMouse.y = mouse.y;
		
		if (mouseLetGo) {
			mouse.down = false;
			mouseLetGo = false;
		}
	};



	var getMousePosition = function (event) {
		var x = -1;
		var y = -1;

		if ((event.x === undefined) || (event.y === undefined)) {
			x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
		} else {
			x = event.x;
			y = event.y;
		}

		x -= canvas.offsetLeft + canvasBorderThickness;
		y -= canvas.offsetTop + canvasBorderThickness;

		return [x, y];
	};



	var setMousePosition = function (event) {
		event = event || window.event;
		var pos = getMousePosition(event);
		mouse.x = pos[0];
		mouse.y = pos[1];

	};



	var onMouseDown = function (event) {
		mouse.down = true;
		setMousePosition(event);
	};



	var onMouseMove = function (event) {
		setMousePosition(event);
	};



	var onMouseUp = function (event) {
		mouseLetGo = true;
		setMousePosition(event);
	};



	var isMouseDown = function () {
		return mouse.down;
	};



	var isMouseUp = function () {
		return !mouse.down
	};



	var getMouseX = function () {
		return mouse.x;
	};



	var getMouseY = function () {
		return mouse.y;
	};



	var isMouseOver = function (x, y, width, height) {
		return ((getMouseX() >= x) && (getMouseX() <= x + width) && (getMouseY() >= y) && (getMouseY() <= y + height));
	};



	var wasMouseDown = function () {
		return previousMouse.down;
	};



	var wasMouseUp = function () {
		return !previousMouse.down;
	};



	var setMouseDown = function (down) {
		mouse.down = down;
	};



	window.updateMouse = updateMouse;
	window.onMouseDown = onMouseDown;
	window.onMouseMove = onMouseMove;
	window.onMouseUp = onMouseUp;
	window.isMouseDown = isMouseDown;
	window.isMouseUp = isMouseUp;
	window.getMouseX = getMouseX;
	window.getMouseY = getMouseY;
	window.isMouseOver = isMouseOver;
	window.wasMouseDown = wasMouseDown;
	window.wasMouseUp = wasMouseUp;
	window.setMouseDown = setMouseDown;
})(window);

In onload, I connect those functions up to the events:


canvas.onmousedown = onMouseDown;
canvas.onmousemove = onMouseMove;
canvas.onmouseup = onMouseUp;

In each frame of the game, I call the updateMouse(); function.

The getMouseX/Y() functions return the pixel position of the mouse based on the top left corner of the canvas. This means that if x < 0 or x > canvasWidth (and same for y), then it is out of the screen. The mouse events don't fire once the mouse is outside the canvas though (apart from the first with a -1/canvasWidth + 1/canvasHeight + 1 value).

Using your method, you could try to clamp the last known position of the mouse to the screen.


// Assume mouse closest to left side first
var drawAtX = 0;
var drawAtY = mouse.y;
var shortestDistance = mouse.x;

// If closer to top
if (mouse.y < shortestDistance) {
	shortestDistance = mouse.y;
	drawAtX = mouse.x;
	drawAtY = 0;
}

// Right side
if (canvasWidth - mouse.x < shortestDistance) {
	shortestDistance = canvasWidth - mouse.x;
	drawAtX = canvasWidth;
	drawAtY = mouse.y;
}

// Bottom side
if (canvasHeight - mouse.y < shortestDistance) {
	shortestDistance = canvasHeight - mouse.y;
	drawAtX = mouse.x;
	drawAtY = canvasHeight;
}

Or if you know the 2 last positions of the mouse (and so deltaX and deltaY), you could continue in the direction the mouse was moving until it hits the edge.

Falling block colour flood game thing I'm making: http://jsfiddle/dr01d3k4/JHnCV/

I don't have a tested solution, but how about jQuery .mousemove on a surrounding div or .pageX on the document?

http://api.jquery.com/mousemove/

http://api.jquery.com/event.pagex/

http://stackoverflow.com/questions/4517198/how-to-get-mouse-position-in-jquery-without-mouse-events?answertab=active#tab-top

Cheers /Carsten

I understand you can use the events 'mouseout' and 'mouseover' to find out when the mouse leaves the canvas and returns, but how do you get the exact position of the mouse when it's outside the canvas?

you can attach another mousemove event to <body> object of document- this event will contain event object knowing position in pattern of document/body. you of course cannot track mouse position outside of the very window, though, you can get window.screen property that is actualy pixel resulution of client computer/device.

This topic is closed to new replies.

Advertisement