Hello there. I am wondering how to make an object rotate to face the current position of the mouse in a canvas. I am not sure if this is a question yet but I am keen to knowing how to do this.
For example, in agar.io, you are a circle which follows your mouse.
This is a great question! It is one I don’t have an answer for right now, and I’m currently fiddling with a solution for you. I did a quick search, and this may help you in the interim: https://stackoverflow.com/questions/40120470/javascript-making-image-rotate-to-always-look-at-mouse-cursor
Thank You! Exactly what I was looking for. I normally do use Stack Overflow but I guess this works better!
Glad to hear you are unblocked
There are several things with the SO solution that aren’t ideal. I wouldn’t use the slower getBoundingClientRect
to get the mouse position relative to any offsets on the page. I would use getMousePosition
from here: https://www.kirupa.com/canvas/follow_mouse_cursor.htm
There are a few areas where I would just use requestAnimationFrame
instead of mousemove, and I will try to provide you with a working solution in a couple of days.
Here is my take on this that addresses some of the perf issues I outlined in my earlier response:
<!DOCTYPE html>
<html>
<head>
<title>Rotate with Mouse</title>
<style>
canvas {
border: #333 10px solid;
}
body {
padding: 50px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="550px" height="350px"></canvas>
<script>
let canvas = document.querySelector("#myCanvas");
let context = canvas.getContext("2d");
let mouseX = 0;
let mouseY = 0;
// deal with page offsets
let canvasPos = getPosition(canvas);
let x_midpoint = canvas.width / 2;
let y_midpoint = canvas.height / 2;
canvas.addEventListener("mousemove", setMousePosition, false);
function setMousePosition(e) {
mouseX = e.clientX - canvasPos.x;
mouseY = e.clientY - canvasPos.y;
// ensure we update only when a frame update is happening
requestAnimationFrame(update);
}
let rectangleWidth = 50;
let rectangleHeight = 50;
function update() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "#F0C808";
context.fillRect(0, 0, canvas.width,canvas.height);
let diffX = mouseX - x_midpoint;
let diffY = mouseY - y_midpoint;
// shift starting point to middle of canvas
context.setTransform(1, 0, 0, 1, x_midpoint, y_midpoint);
// rotate based on the mouse position
context.rotate(Math.atan2(diffY, diffX));
// the triangle
context.beginPath();
context.moveTo(-15, -15);
context.lineTo(-15, 15);
context.lineTo(30, 0);
context.closePath();
// the fill color
context.fillStyle = "#315659";
context.fill();
// reset transform
context.setTransform(1, 0, 0, 1, 0, 0);
// the line
context.beginPath();
context.moveTo(mouseX, mouseY);
context.lineTo(x_midpoint, y_midpoint);
context.lineWidth = 2;
context.setLineDash([2, 5]);
context.strokeStyle = "#315659";
context.stroke();
}
update();
// Deal with page positioning shenanigans
// https://www.kirupa.com/html5/get_element_position_using_javascript.htm
function getPosition(el) {
let xPosition = 0;
let yPosition = 0;
while (el) {
xPosition += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPosition += (el.offsetTop - el.scrollTop + el.clientTop);
el = el.offsetParent;
}
return {
x: xPosition,
y: yPosition
};
}
</script>
</body>
</html>
You can see a video of this in the following tweet:
This is based largely on combining the contents of the Follow the Mouse Cursor, Drawing a Triangle, Canvas Transformations, and Get an Element’s Position articles.
Amazing! Thank You So Much!