Zooming in at mouse position p5.js (jsfiddle included)
Asked Answered
U

1

7

I'm trying to zoom at mouse position, like say on google maps. It kind of works but it shifts the point i want to zoom in on wherever it matches up with the original.Then when i zoom at that point it works fine. I think I need to translate the point back to the mouse, but I'm not sure how to do it exactly.

This is the code before i draw:

  translate(zoomLocation.x, zoomLocation.y);
  scale(zoom);
  translate(-zoomLocation.x, -zoomLocation.y);
  drawGrid();

And this is when I zoom:

  event.preventDefault();
  zoomLocation = {
    x: zoomLocation.x + (mouseX - zoomLocation.x) / zoom,
    y: zoomLocation.y + (mouseY - zoomLocation.y) / zoom
  };
  zoom -= zoomSensitivity * event.delta;

let colors = {
  background: 0,
  gridLines: "white"
};

let nVariables = 4;

let zoom = 1;
let zoomLocation = {
  x: 0,
  y: 0
};
let zoomSensitivity = 0.0002;

function draw() {
  translate(zoomLocation.x, zoomLocation.y);
  scale(zoom);
  translate(-zoomLocation.x, -zoomLocation.y);
  drawGrid();


  stroke("blue");
  ellipse(zoomLocation.x + (mouseX - zoomLocation.x) / zoom, zoomLocation.y + (mouseY - zoomLocation.y) / zoom, 10, 10);

  stroke("red");
  ellipse(zoomLocation.x, zoomLocation.y, 10, 10);

}

function setup() {
  zoomLocation = {
    x: 0,
    y: windowHeight / 2
  }
  createCanvas(windowWidth, windowHeight);
}

function mouseWheel(event) {
  event.preventDefault();
  let oldZoom = zoom;
  zoomLocation = {
    x: zoomLocation.x + (mouseX - zoomLocation.x) / zoom,
    y: zoomLocation.y + (mouseY - zoomLocation.y) / zoom
  };
  zoom -= zoomSensitivity * event.delta;
}

function drawGrid() {
  let nCells = 2 ** nVariables;
  if (nCells > 2048) {
    if (!window.confirm(`You are about to create ${nCells} cells. This might lag your browser. Are you sure?`)) {
      return;
    }
  }
  background(colors.background);
  let gridWidth = windowWidth - 2;
  let gridHeight = min(gridWidth / nCells, windowHeight / 2 - 2);
  let gridY = windowHeight / 2;
  stroke(colors.gridLines);
  line(0, gridY, gridWidth, gridY);
  line(0, gridY + gridHeight, gridWidth, gridY + gridHeight);
  for (let i = 0; i < nCells + 1; i++) {
    line(i * (gridWidth / nCells), gridY, i * (gridWidth / nCells), gridY + gridHeight)
  }

  let curveHeight = 2;

  let drawVariable = (n) => {
    let p1 = {
      x: 1 / (2 ** (n + 1)) * gridWidth,
      y: gridY
    };
    let c1 = {
      x: p1.x,
      y: p1.y + gridWidth / (2 ** n) * curveHeight
    };
    let p2 = {
      y: p1.y
    };
    let c2 = {
      y: c1.y
    };;
    noFill();
    stroke("red");
    if (n == 0) {
      p2.x = gridWidth;
      c2.x = p2.x;
      c1.y = c2.y = p1.y + gridWidth / 2 * curveHeight;
      curve(c1.x, c1.y, p1.x, p1.y, p2.x, p2.y, c2.x, c2.y);
      return;
    }
    for (let i = 3; i < 2 ** (n + 1); i += 2) {
      p2.x = i / (2 ** (n + 1)) * gridWidth
      c2.x = p2.x;
      if ((i - 3) % 4 == 0) {
        curve(c1.x, c1.y, p1.x, p1.y, p2.x, p2.y, c2.x, c2.y);
      } else {
        p1.x = p2.x;
        c1.x = c2.x;
      }
    }
  };

  for (let i = 0; i < nVariables; i++) {
    drawVariable(i);
  }
}
body {
  margin: 0
}

button {
  outline: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/addons/p5.dom.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
Unyoke answered 18/6, 2017 at 10:35 Comment(3)
What is your desired effect?Wiburg
The point under the mouse should remain at the same place on the screen, like zooming in google maps for exampleUnyoke
this question should have more activity. I really needed thisShaner
P
3

What you're looking for is an application of Affine Transformation. Here's an example where I'm applying transformations incrementally to transform + scale at the mouse pointer location for a Google Maps type zoom effect: Zoom Effect in p5.js Web Editor.

This is a good medium article that explains why this works: Zooming at the Mouse Coordinates with Affine Transformations

This is another good article that has some mathematical explanations on how it achieves the effects: Affine Transformations — Pan, Zoom, Skew

Portal answered 11/1, 2022 at 1:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.