Using the mouse position to zoom in on a map

void draw() {
  if(w) {camY -= 5;}
  if(s) {camY += 5;}
  if(a) {camX -= 5;}
  if(d) {camX += 5;}
    
  background(220);
  push();
  translate(mouseX, mouseY);
  scale(camScale);
  translate(-mouseX, -mouseY);
  translate(-camX, -camY);
  drawGrid();
  pop();
}

Hello everyone! I am attempting to make a 2D top down “map” sort of thing in Processing for a simulation I’m working on. I’m trying to make it so you can pan the camera with WASD and zoom into the point where your mouse is with the scroll wheel. However, I can’t figure out how to make it zoom in on the point where the mouse is without also causing the mouse to move the whole map around. The above code is what I currently have

Note: the w, a, s, and d variables are booleans that are just true if you hold down that key, those arent the source of the issue.

I know the issue is something with the scale function, since the second I comment it out it no longer interferes with the position of the grid I’m drawing

This sketch was made by @Chrisir scale with mouse


int logoSize = 25;
float scalePercentage, radius2;

void setup() {
  size(800, 800);

  ellipseMode(CENTER);
}

void draw() {
  background(255);
  strokeWeight(20);
  fill(0);
  text(mouseX, 19, 19);

  noFill();
  // increase
  scalePercentage = map (mouseX,
    0, width,
    0, 4);

  translate  (width/2, height/2);
  scale(scalePercentage);

  ellipse(0, 0, logoSize+50+378, logoSize-50+378);
  ellipse(0, -60, logoSize-50+378, logoSize-175+378);
  //
  ellipse(0, 0, logoSize-175+378, logoSize-50+378);
}

@jafal That’s not quite what I’m looking for, thank you for the reply though! I have a top down map(imagine like a minimap from a video game) and I can pan around it with WASD and I want the camera to zoom in on the point of the position of the mouse on said map. So the center of the zoom should be the mouseX and mouseY

1 Like

@jafal https://youtube.com/shorts/MHEGoKpM5mE

As you can see, it’s able to zoom in on the point where the mouse is, but the entire grid also follows the mouse(but only when the zoom scale isnt equal to 1) when the position of the map should only be able to be changed by WASD

Also note: I use the scroll wheel to change the camScale variable

can you make an mcve please

Look at this topic may you find some hints

1 Like

@Chrisir

int gridSize = 20;
int camX = 0;
int camY = 0;
float camScale = 1;
boolean w = false, a = false, s = false, d = false;

void setup() {
  size(800, 800);
}

void draw() {
  if(w) {camY -= 5;}
  if(s) {camY += 5;}
  if(a) {camX -= 5;}
  if(d) {camX += 5;}
    
  background(220);
  
  push();
  translate(mouseX, mouseY);
  scale(camScale);
  translate(-mouseX, -mouseY);
  translate(-camX, -camY);
  drawGrid();
  pop();
}

void drawGrid() {
  for(int i = 0; i < 50; i++) {
    for(int j = 0; j < 50; j++) {
      fill(255);
      square(i*gridSize, j*gridSize, gridSize);
    }
  }
}

void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  if(e == 1) {e = 1/1.1;}
  if(e == -1) {e = 1.1;}
  if(camScale * e >= 0.2) {
    camScale *= e;
  } else {
    camScale = 0.2;
  }
}

void keyPressed() {
  if (key == 'w') {w = true;}
  if (key == 's') {s = true;}
  if (key == 'a') {a = true;}
  if (key == 'd') {d = true;}
}

void keyReleased() {
  if (key == 'w') {w = false;}
  if (key == 's') {s = false;}
  if (key == 'a') {a = false;}
  if (key == 'd') {d = false;}
}

Basically I just cant figure out how to stop the grid from moving alongside the mouse while also still allowing it to zoom in on where the mouse is located

1 Like

I cannot say something wise here

In theory when mouse is pressed store its position in 2 separate variables and then use those in draw instead of mouseX and mouseY

The whole idea is called Viewport you might want to use the search function of the forum for this

Just as a quick update, I ended up figuring it out! So it turns out I was performing the zooming correctly, but the issue was in the fact that the camera’s origin is in the top left corner. So when I zoomed out, the entire camera appeared to move down and to the right. I fixed it by just adding code to shift the camera up and to the left by half of the amount that it zooms if that makes sense

camX and camY should be floats, not ints.

draw() should not translate by the mouse position. Instead, when you change the scale, you need to change camX and camY so that they move relative to the world-space position of the mouse.

I simplified draw() and updated mouseWheel() to make the changes:

int gridSize = 20;
float camX = 0;
float camY = 0;
float camScale = 1;
boolean w = false, a = false, s = false, d = false;

void setup() {
  size(800, 800);
}

void draw() {
  if(w) {camY -= 5;}
  if(s) {camY += 5;}
  if(a) {camX -= 5;}
  if(d) {camX += 5;}
    
  background(220);
  
  push();
  scale(camScale);
  translate(-camX, -camY);
  drawGrid();
  pop();
}

void drawGrid() {
  for(int i = 0; i < 50; i++) {
    for(int j = 0; j < 50; j++) {
      fill(255);
      square(i*gridSize, j*gridSize, gridSize);
    }
  }
}

void mouseWheel(MouseEvent event) {
  float e = event.getCount();
  if(e == 1) {e = 1/1.1;}
  if(e == -1) {e = 1.1;}
  float oldScale = camScale;
  if(camScale * e >= 0.2) {
    camScale *= e;
  } else {
    camScale = 0.2;
  }
  float worldX = camX + mouseX/oldScale;
  camX = worldX - mouseX/camScale;
  float worldY = camY + mouseY/oldScale;
  camY = worldY - mouseY/camScale;
}

void keyPressed() {
  if (key == 'w') {w = true;}
  if (key == 's') {s = true;}
  if (key == 'a') {a = true;}
  if (key == 'd') {d = true;}
}

void keyReleased() {
  if (key == 'w') {w = false;}
  if (key == 's') {s = false;}
  if (key == 'a') {a = false;}
  if (key == 'd') {d = false;}
}
2 Likes

Thanks for posting

Interesting to know for me and I am sure also for others

2 Likes