Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
like image 378
Kys Plox Avatar asked Nov 19 '22 17:11

Kys Plox


1 Answers

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

like image 79
heothesennoc Avatar answered Nov 24 '22 01:11

heothesennoc