How can I convert screen coordinates from a click to 2D scaled world coordinates?

I need a way to convert screen coordinates obtained from mouse clicks to world coordinates in my 2D game.

To create a zoom effect controlled by the user, before drawing a model I will scale all of it's points by a world scale value.

The screen origin (0,0) is at the top left corner while the world has it's center (0,0) at the center of the screen (width/2, height/2).

I need a function to convert the coords obtained by mouse clicks (screen coords) to the corresponding scaled-world coordinates, so that I can determine what world element is clicked by the user in this scaled world.

Any of my approaches worked as required and unfortunately none of the found solutions where aplicable to my case.

This is a very simple example JS Bin:

• Use the mouse wheel to zoom in/out
• Click on the screen to set a point

Thanks!

You're almost there.

The theory: for each "transform" you apply to the world coordinates to turn them into screen coordinates, you need to undo each one of them.

You have three transforms.

1. The ctx.translate(centerX, centerY). You correctly undo this transform with const x = -centerX + coords.x; const y = -centerY + coords.y;.
2. You've told the browser to scale the canvas output but not scale the input clicks. For now, take out the width:100%; height:100% on the canvas. Without that, if you don't use mousewheel to zoom, you will see that your code works correctly. (yay!)
3. But we still need to handle the mousewheel zoom: the converted.x * worldScale, converted.y * worldScale. You haven't undone this one. In the convert function, use const x = (coords.x - centerX) / worldScale; const y = (coords.y - centerY) / worldScale;

Here's a JS Bin: https://jsbin.com/nexitukime/1/edit?html,output

If you want to have the canvas sized to 100% you'll need to undo the browser scaling by using getBoundingClientRect() to find out how big the browser has made the output, and then undo that first before you run convert().

• Nice!! Thank you very much for taking the time to explain the details and sharing code. It's very clear now :) May 17, 2019 at 13:53