I am trying to get the mouse position on a transformed canvas. Here is my resize method:
window.addEventListener('resize', resize);
function resize() {
screenWidth = window.innerWidth;
screenHeight = window.innerHeight;
scaleFillNative = MathMAX(screenWidth / maxScreenWidth, screenHeight / maxScreenHeight);
mainCanvas.width = screenWidth;
mainCanvas.height = screenHeight;
mainContext.setTransform(scaleFillNative, 0, 0, scaleFillNative, Math.floor((screenWidth - (maxScreenWidth * scaleFillNative)) / 2),
Math.floor((screenHeight - (maxScreenHeight * scaleFillNative)) / 2));
}
The maxScreenWidth and maxScreenHeight represents the native screen dimensions that the canvas should be transformed to.
The actual resizing works fine. The issue however is that I am trying to render a circle at the mouse position on the canvas. The mouse position is set as follows:
window.addEventListener('mousemove', gameInput, false);
var mouseX, mouseY;
function gameInput(e) {
e.preventDefault();
e.stopPropagation();
mouseX = e.clientX;
mouseY = e.clientY;
}
And it is then rendered like this:
renderCircle(mouseX / scaleFillNative, mouseY / scaleFillNative, 10);
The x position is rendered correctly. However when I resize the window so that the width is less than the height, it no longer renders at the correct x location. The y position is always offset.
I don't know exactly what you have tried so far, but for a basic mouse coordinate to transformed canvas (non skewed), you'll have to do
mouseX = (evt.clientX - canvas.offsetLeft - translateX) / scaleX;
mouseY = (evt.clientY - canvas.offsetTop - translateY) / scaleY;
But canvas.offsetXXX
doesn't take scroll amount into account, so this demo uses getBoundingRect
instead.
var ctx = canvas.getContext('2d'); window.addEventListener('resize', resize); // you probably have these somewhere var maxScreenWidth = 1800, maxScreenHeight = 1200, scaleFillNative, screenWidth, screenHeight; // you need to set available to your mouse move listener var translateX, translateY; function resize() { screenWidth = window.innerWidth; screenHeight = window.innerHeight; // here you set scaleX and scaleY to the same variable scaleFillNative = Math.max(screenWidth / maxScreenWidth, screenHeight / maxScreenHeight); canvas.width = screenWidth; canvas.height = screenHeight; // store these values translateX = Math.floor((screenWidth - (maxScreenWidth * scaleFillNative)) / 2); translateY = Math.floor((screenHeight - (maxScreenHeight * scaleFillNative)) / 2); ctx.setTransform(scaleFillNative, 0, 0, scaleFillNative, translateX, translateY); } window.addEventListener('mousemove', mousemoveHandler, false); function mousemoveHandler(e) { // Note : I don't think there is any event default on mousemove, no need to prevent it // normalize our event's coordinates to the canvas current transform // here we use .getBoundingRect() instead of .offsetXXX // because we also need to take scroll into account, // in production, store it on debounced(resize + scroll) events. var rect = canvas.getBoundingClientRect(); var mouseX = (e.clientX - rect.left - translateX) / scaleFillNative, mouseY = (e.clientY - rect.top - translateY) / scaleFillNative; ctx.fillRect(mouseX - 5, mouseY - 5, 10, 10); } // an initial call resize();
<canvas id="canvas"></canvas>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.