Owen M
Owen M

Reputation: 2764

How do I properly get the mouse position in Javascript?

I made a small JS program that is supposed to simulate ball physics, where the HTML canvas is supposed to resize to the window height. I have made it so that the canvas resizes, but when it resizes the mouse position doesn't work right, and the balls don't appear on the screen when it is clicked (like they're supposed to). I've been using clientX & clientY to get the mouse position, but I don't know if that's the best method. Here is the code:

<!DOCTYPE <!DOCTYPE html>

<html>

<head>

	<style type="text/css">


		BODY {
            background: #00000;
		}

		#myCanvas {
			background-color: black;
		}



	</style>

	<title>Ball Simulator</title>

	<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

	<script type="text/javascript">
		
	$(function() {
	  c = document.getElementById('myCanvas');
	  ctx = c.getContext("2d");
	  objects = [];
	  init()
	  c.addEventListener("mousedown", onMouseDown);
	  c.addEventListener("mouseup", onMouseUp);
	  ctx.fillStyle = "#FFFFFF";
	});

	function resizeCanvas() {
	  c.width = window.innerWidth;
	  c.height = window.innerHeight;
	}

	function ball(x, y, radius, xVel, yVel) {
	  this.x = x;
	  this.y = y;
	  this.radius = radius;
	  this.xVel = xVel;
	  this.yVel = yVel;
	  this.direction = Math.random() * Math.PI * 2

	  objects.push([x, y, radius, xVel, yVel, this.direction])
	};

	function stylusBall(x, y, radius) {

	  ctx.beginPath();
	  ctx.arc(x, y, radius, 0, 2 * Math.PI);
	  ctx.fill();

	}

	function getDistance(x1, y1, x2, y2) {

	  return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));

	};

	function getVerticalDistance(y1, y2) {
	  return y2 - y1
	};

	function getAngle(x1, y1, x2, y2) {

	  return Math.atan2(x2 - x1, y2 - y1);

	};

	function updateData() {
	  ctx.clearRect(0, 0, 6000, 3100);
	  for (i = 0; i < objects.length; i++) {
	    var close = false
	    var x = objects[i][0];
	    var y = objects[i][1];
	    var radius = objects[i][2];
	    var xVel = objects[i][3];
	    var yVel = objects[i][4];
	    var dir = objects[i][5];

	    for (n = 0; n < objects.length; n++) {

	      if (n != i) {
	      	close = false
	        var nX = objects[n][0];
	        var nY = objects[n][1];
	        var nRadius = objects[n][2];
	        var nAngle = getAngle(x, y, nX, nY);

	        var distance = getDistance(x, y, nX, nY);

	        if (distance == (nRadius + radius) || distance < (nRadius + radius)) {

	          var bounceForce = 1.5
	          xVel = xVel * -1 + bounceForce * Math.cos(nAngle);
	          yVel = yVel * -1 + bounceForce * Math.sin(nAngle);
	          close = true

	        };

	      };

	    }

	    if (getVerticalDistance(y, window.innerHeight - 5 - radius) > 0 && !close) {
	      yVel += 2;
	    } else if (getVerticalDistance(y, window.innerHeight - 5 - radius) < 0) {
	      yVel = yVel * -1;

	      if (getVerticalDistance(y, window.innerHeight - 5 - radius) < -20) {
	        y = y - 50
	      }
	    }

	    yVel *= 0.97;
	    xVel *= 0.99;

	    objects[i][3] = xVel
	    objects[i][4] = yVel

	    objects[i][0] = x + xVel
	    objects[i][1] = y + yVel

	  };

//	  window.requestAnimationFrame(updateData)

	};

	function drawArrow(x1, y1, x2, y2) {

	}

	function mouseMove(e) {
	  mouseX = e.clientX;
	  mouseY = e.clientY;
	}

	function onMouseDown() {
	  createRadius = 5;

	  anim = requestAnimationFrame(increase);
	};

	function increase() {
	  if (createRadius < 80) {
	    createRadius += 3;
	  }
	  newStylus = new stylusBall(mouseX, mouseY, createRadius)
	  anim = requestAnimationFrame(increase);
	};

	function onMouseUp() {
	  window.cancelAnimationFrame(anim);
	  newBall = new ball(mouseX, mouseY, createRadius, 0, 0);
	};

	function render() {

	  for (i = 0; i < objects.length; i++) {
	    ctx.beginPath();

	    ctx.arc(objects[i][0], objects[i][1], objects[i][2], 0, 2 * Math.PI);

	    ctx.fill();
	  };
//	  window.requestAnimationFrame(render)
	};


	function loop() {
		c.width = window.innerWidth;
		c.height = window.innerHeight;
		updateData();
		render();
		window.requestAnimationFrame(loop);
	}

	function init() {
	  loop();
	}
	</script>

</head>

  <body style="margin: 0;">

    <canvas id='myCanvas' onmousemove="mouseMove(event)">

  </body>

</html>

Upvotes: 0

Views: 7197

Answers (2)

gipouf
gipouf

Reputation: 1241

If you want to get the mouse position relative to the canvas top-left point, you should use event.offsetX and event.offsetY (given that you have attached the mousemove event handler to the canvas element).

Try this:

function mouseMove(e) {
      var mouseX = e.offsetX;
      var mouseY = e.offsetY;
}

Upvotes: 0

lili2311
lili2311

Reputation: 76

I think this this what can help, you need to get the mouse position relative to the canvas. So creating a function to get the mouse position:

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}

Then when you are adding an event listener for both mousedown & mouseup events, you can set the mouse position:

canvas.addEventListener('mousedown', function(evt) {
    isMouseDown = true;
    mousePos = getMousePos(canvas, evt);
    message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
    writeMessage(canvas, message);

  }, false);

Upvotes: 1

Related Questions